2019-11-15 23:26:29 +01:00
< ? php
/**
* Module Name : Site Stats
* Module Description : Collect valuable traffic stats and insights .
* Sort Order : 1
* Recommendation Order : 2
* First Introduced : 1.1
* Requires Connection : Yes
* Auto Activate : Yes
* Module Tags : Site Stats , Recommended
* Feature : Engagement
* Additional Search Queries : statistics , tracking , analytics , views , traffic , stats
*
2021-04-27 08:32:47 +02:00
* @ package automattic / jetpack
2019-11-15 23:26:29 +01:00
*/
use Automattic\Jetpack\Connection\Client ;
2021-04-27 08:32:47 +02:00
use Automattic\Jetpack\Connection\Manager as Connection_Manager ;
2020-09-15 14:30:05 +02:00
use Automattic\Jetpack\Connection\XMLRPC_Async_Call ;
2020-05-06 17:20:49 +02:00
use Automattic\Jetpack\Redirect ;
2020-10-20 18:05:12 +02:00
use Automattic\Jetpack\Status ;
2021-04-27 08:32:47 +02:00
use Automattic\Jetpack\Tracking ;
2019-11-15 23:26:29 +01:00
if ( defined ( 'STATS_VERSION' ) ) {
return ;
}
define ( 'STATS_VERSION' , '9' );
2021-04-27 08:32:47 +02:00
defined ( 'STATS_DASHBOARD_SERVER' ) || define ( 'STATS_DASHBOARD_SERVER' , 'dashboard.wordpress.com' );
2019-11-15 23:26:29 +01:00
add_action ( 'jetpack_modules_loaded' , 'stats_load' );
/**
* Load Stats .
*
* @ access public
* @ return void
*/
function stats_load () {
Jetpack :: enable_module_configurable ( __FILE__ );
// Generate the tracking code after wp() has queried for posts.
add_action ( 'template_redirect' , 'stats_template_redirect' , 1 );
add_action ( 'wp_head' , 'stats_admin_bar_head' , 100 );
add_action ( 'wp_head' , 'stats_hide_smile_css' );
2020-03-03 18:49:45 +01:00
add_action ( 'embed_head' , 'stats_hide_smile_css' );
2019-11-15 23:26:29 +01:00
add_action ( 'jetpack_admin_menu' , 'stats_admin_menu' );
// Map stats caps.
add_filter ( 'map_meta_cap' , 'stats_map_meta_caps' , 10 , 3 );
2021-04-27 08:32:47 +02:00
add_action ( 'admin_init' , 'stats_merged_widget_admin_init' );
2019-11-15 23:26:29 +01:00
2020-11-18 09:10:44 +01:00
add_filter ( 'jetpack_xmlrpc_unauthenticated_methods' , 'stats_xmlrpc_methods' );
2019-11-15 23:26:29 +01:00
add_filter ( 'pre_option_db_version' , 'stats_ignore_db_version' );
2021-04-27 08:32:47 +02:00
// Add an icon to see stats in WordPress.com for a particular post.
2019-11-15 23:26:29 +01:00
add_action ( 'admin_print_styles-edit.php' , 'jetpack_stats_load_admin_css' );
add_filter ( 'manage_posts_columns' , 'jetpack_stats_post_table' );
add_filter ( 'manage_pages_columns' , 'jetpack_stats_post_table' );
add_action ( 'manage_posts_custom_column' , 'jetpack_stats_post_table_cell' , 10 , 2 );
add_action ( 'manage_pages_custom_column' , 'jetpack_stats_post_table_cell' , 10 , 2 );
2021-08-17 08:33:07 +02:00
2021-09-07 21:40:48 +02:00
require_once __DIR__ . '/stats/class-jetpack-stats-upgrade-nudges.php' ;
add_action ( 'updating_jetpack_version' , array ( 'Jetpack_Stats_Upgrade_Nudges' , 'unset_nudges_setting' ) );
2019-11-15 23:26:29 +01:00
}
/**
* Delay conditional for current_user_can to after init .
*
* @ access public
* @ return void
*/
function stats_merged_widget_admin_init () {
if ( current_user_can ( 'view_stats' ) ) {
add_action ( 'load-index.php' , 'stats_enqueue_dashboard_head' );
add_action ( 'jetpack_dashboard_widget' , 'stats_jetpack_dashboard_widget' );
}
}
/**
* Enqueue Stats Dashboard
*
* @ access public
* @ return void
*/
function stats_enqueue_dashboard_head () {
add_action ( 'admin_head' , 'stats_dashboard_head' );
}
/**
* Checks if filter is set and dnt is enabled .
*
* @ return bool
*/
function jetpack_is_dnt_enabled () {
/**
* Filter the option which decides honor DNT or not .
*
* @ module stats
* @ since 6.1 . 0
*
* @ param bool false Honors DNT for clients who don ' t want to be tracked . Defaults to false . Set to true to enable .
*/
if ( false === apply_filters ( 'jetpack_honor_dnt_header_for_stats' , false ) ) {
return false ;
}
foreach ( $_SERVER as $name => $value ) {
2021-04-27 08:32:47 +02:00
if ( 'http_dnt' === strtolower ( $name ) && 1 === ( int ) $value ) {
2019-11-15 23:26:29 +01:00
return true ;
}
}
return false ;
}
/**
* Prevent sparkline img requests being redirected to upgrade . php .
* See wp - admin / admin . php where it checks $wp_db_version .
*
* @ access public
* @ param mixed $version Version .
* @ return string $version .
*/
function stats_ignore_db_version ( $version ) {
if (
is_admin () &&
2021-04-27 08:32:47 +02:00
isset ( $_GET [ 'page' ] ) && 'stats' === $_GET [ 'page' ] && // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2022-06-16 14:01:47 +02:00
isset ( $_GET [ 'chart' ] ) && strpos ( $_GET [ 'chart' ], 'admin-bar-hours' ) === 0 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
2019-11-15 23:26:29 +01:00
) {
global $wp_db_version ;
return $wp_db_version ;
}
return $version ;
}
/**
* Maps view_stats cap to read cap as needed .
*
* @ access public
* @ param mixed $caps Caps .
* @ param mixed $cap Cap .
* @ param mixed $user_id User ID .
* @ return array Possibly mapped capabilities for meta capability .
*/
function stats_map_meta_caps ( $caps , $cap , $user_id ) {
// Map view_stats to exists.
if ( 'view_stats' === $cap ) {
$user = new WP_User ( $user_id );
$user_role = array_shift ( $user -> roles );
$stats_roles = stats_get_option ( 'roles' );
// Is the users role in the available stats roles?
2021-04-27 08:32:47 +02:00
if ( is_array ( $stats_roles ) && in_array ( $user_role , $stats_roles , true ) ) {
2019-11-15 23:26:29 +01:00
$caps = array ( 'read' );
}
}
return $caps ;
}
/**
* Stats Template Redirect .
*
* @ access public
* @ return void
*/
function stats_template_redirect () {
global $current_user ;
2022-04-02 10:26:41 +02:00
if (
is_feed ()
|| is_robots ()
|| is_embed ()
|| is_trackback ()
|| is_preview ()
|| jetpack_is_dnt_enabled ()
) {
2019-11-15 23:26:29 +01:00
return ;
}
2020-10-20 18:05:12 +02:00
// Staging Sites should not generate tracking stats.
$status = new Status ();
if ( $status -> is_staging_site () ) {
return ;
}
2019-11-15 23:26:29 +01:00
// Should we be counting this user's views?
if ( ! empty ( $current_user -> ID ) ) {
$count_roles = stats_get_option ( 'count_roles' );
if ( ! is_array ( $count_roles ) || ! array_intersect ( $current_user -> roles , $count_roles ) ) {
return ;
}
}
2022-04-02 10:26:41 +02:00
/**
* Allow excluding specific IP addresses from being tracked in Stats .
* Note : for this to work well , visitors ' IP addresses must :
* - be stored and returned properly in IP address headers ;
* - not be impacted by any caching setup on your site .
*
* @ module stats
*
* @ since 10.6
*
* @ param array $excluded_ips An array of IP address strings to exclude from tracking .
*/
$excluded_ips = ( array ) apply_filters ( 'jetpack_stats_excluded_ips' , array () );
// Should we be counting views for this IP address?
if (
! empty ( $excluded_ips )
&& in_array ( Jetpack :: current_user_ip ( true ), $excluded_ips , true )
) {
return ;
}
2019-11-15 23:26:29 +01:00
add_action ( 'wp_footer' , 'stats_footer' , 101 );
2020-12-10 14:04:11 +01:00
add_action ( 'web_stories_print_analytics' , 'stats_footer' );
2019-11-15 23:26:29 +01:00
}
/**
* Stats Build View Data .
*
* @ access public
* @ return array .
*/
function stats_build_view_data () {
global $wp_the_query ;
2021-04-27 08:32:47 +02:00
$blog = Jetpack_Options :: get_option ( 'id' );
$tz = get_option ( 'gmt_offset' );
$v = 'ext' ;
2019-11-15 23:26:29 +01:00
$blog_url = wp_parse_url ( site_url () );
2021-04-27 08:32:47 +02:00
$srv = $blog_url [ 'host' ];
$j = sprintf ( '%s:%s' , JETPACK__API_VERSION , JETPACK__VERSION );
2019-11-15 23:26:29 +01:00
if ( $wp_the_query -> is_single || $wp_the_query -> is_page || $wp_the_query -> is_posts_page ) {
// Store and reset the queried_object and queried_object_id
// Otherwise, redirect_canonical() will redirect to home_url( '/' ) for show_on_front = page sites where home_url() is not all lowercase.
// Repro:
// 1. Set home_url = https://ExamPle.com/
// 2. Set show_on_front = page
// 3. Set page_on_front = something
// 4. Visit https://example.com/ !
2020-11-18 09:10:44 +01:00
$queried_object = isset ( $wp_the_query -> queried_object ) ? $wp_the_query -> queried_object : null ;
$queried_object_id = isset ( $wp_the_query -> queried_object_id ) ? $wp_the_query -> queried_object_id : null ;
try {
$post_obj = $wp_the_query -> get_queried_object ();
$post = $post_obj instanceof WP_Post ? $post_obj -> ID : '0' ;
} finally {
$wp_the_query -> queried_object = $queried_object ;
$wp_the_query -> queried_object_id = $queried_object_id ;
}
2019-11-15 23:26:29 +01:00
} else {
$post = '0' ;
}
return compact ( 'v' , 'j' , 'blog' , 'post' , 'tz' , 'srv' );
}
/**
* Stats Footer .
*
* @ access public
* @ return void
*/
function stats_footer () {
$data = stats_build_view_data ();
if ( Jetpack_AMP_Support :: is_amp_request () ) {
2022-06-16 14:01:47 +02:00
/**
* Filter the parameters added to the AMP pixel tracking code .
*
* @ module stats
*
* @ since 10.9
*
* @ param array $data Array of options about the site and page you ' re on .
*/
$data = ( array ) apply_filters ( 'jetpack_stats_footer_amp_data' , $data );
2019-11-15 23:26:29 +01:00
stats_render_amp_footer ( $data );
} else {
2022-06-16 14:01:47 +02:00
/**
* Filter the parameters added to the JavaScript stats tracking code .
*
* @ module stats
*
* @ since 10.9
*
* @ param array $data Array of options about the site and page you ' re on .
*/
$data = ( array ) apply_filters ( 'jetpack_stats_footer_js_data' , $data );
2019-11-15 23:26:29 +01:00
stats_render_footer ( $data );
}
}
2021-04-27 08:32:47 +02:00
/**
* Render the stats footer
*
* @ param array $data Array of data for the JS stats tracker .
*/
2019-11-15 23:26:29 +01:00
function stats_render_footer ( $data ) {
2021-04-27 08:32:47 +02:00
// phpcs:disable WordPress.WP.EnqueuedResources.NonEnqueuedScript
// When there is a way to use defer with enqueue, we can move to it and inline the custom data.
$script = 'https://stats.wp.com/e-' . gmdate ( 'YW' ) . '.js' ;
2019-11-15 23:26:29 +01:00
$data_stats_array = stats_array ( $data );
$stats_footer = <<< END
2021-04-27 08:32:47 +02:00
< script src = '{$script}' defer ></ script >
< script >
2019-11-15 23:26:29 +01:00
_stq = window . _stq || [];
_stq . push ([ 'view' , {{ $data_stats_array }} ]);
_stq . push ([ 'clickTrackerInit' , '{$data[' blog ']}' , '{$data[' post ']}' ]);
</ script >
END ;
2021-04-27 08:32:47 +02:00
// phpcs:enable
print $stats_footer ; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2019-11-15 23:26:29 +01:00
}
2021-04-27 08:32:47 +02:00
/**
* Render the stats footer for AMP output .
*
2022-06-16 14:01:47 +02:00
* @ param array $data Array of data for the AMP pixel tracker .
2021-04-27 08:32:47 +02:00
*/
2019-11-15 23:26:29 +01:00
function stats_render_amp_footer ( $data ) {
$data [ 'host' ] = isset ( $_SERVER [ 'HTTP_HOST' ] ) ? sanitize_text_field ( wp_unslash ( $_SERVER [ 'HTTP_HOST' ] ) ) : '' ; // input var ok.
$data [ 'rand' ] = 'RANDOM' ; // AMP placeholder.
$data [ 'ref' ] = 'DOCUMENT_REFERRER' ; // AMP placeholder.
$data = array_map ( 'rawurlencode' , $data );
$pixel_url = add_query_arg ( $data , 'https://pixel.wp.com/g.gif' );
?>
< amp - pixel src = " <?php echo esc_url( $pixel_url ); ?> " ></ amp - pixel >
< ? php
}
/**
* Stats Get Options .
*
* @ access public
* @ return array .
*/
function stats_get_options () {
$options = get_option ( 'stats_options' );
if ( ! isset ( $options [ 'version' ] ) || $options [ 'version' ] < STATS_VERSION ) {
$options = stats_upgrade_options ( $options );
}
return $options ;
}
/**
* Get Stats Options .
*
* @ access public
* @ param mixed $option Option .
* @ return mixed | null .
*/
function stats_get_option ( $option ) {
$options = stats_get_options ();
if ( 'blog_id' === $option ) {
return Jetpack_Options :: get_option ( 'id' );
}
if ( isset ( $options [ $option ] ) ) {
return $options [ $option ];
}
return null ;
}
/**
* Stats Set Options .
*
* @ access public
* @ param mixed $option Option .
* @ param mixed $value Value .
* @ return bool .
*/
function stats_set_option ( $option , $value ) {
$options = stats_get_options ();
$options [ $option ] = $value ;
return stats_set_options ( $options );
}
/**
* Stats Set Options .
*
* @ access public
* @ param mixed $options Options .
* @ return bool
*/
function stats_set_options ( $options ) {
return update_option ( 'stats_options' , $options );
}
/**
* Stats Upgrade Options .
*
* @ access public
* @ param mixed $options Options .
* @ return array | bool
*/
function stats_upgrade_options ( $options ) {
$defaults = array (
'admin_bar' => true ,
'roles' => array ( 'administrator' ),
'count_roles' => array (),
'blog_id' => Jetpack_Options :: get_option ( 'id' ),
'do_not_track' => true , // @todo
);
if ( isset ( $options [ 'reg_users' ] ) ) {
if ( ! function_exists ( 'get_editable_roles' ) ) {
require_once ABSPATH . 'wp-admin/includes/user.php' ;
}
if ( $options [ 'reg_users' ] ) {
$options [ 'count_roles' ] = array_keys ( get_editable_roles () );
}
unset ( $options [ 'reg_users' ] );
}
if ( is_array ( $options ) && ! empty ( $options ) ) {
$new_options = array_merge ( $defaults , $options );
2021-04-27 08:32:47 +02:00
} else {
$new_options = $defaults ;
2019-11-15 23:26:29 +01:00
}
$new_options [ 'version' ] = STATS_VERSION ;
if ( ! stats_set_options ( $new_options ) ) {
return false ;
}
return $new_options ;
}
/**
2021-04-27 08:32:47 +02:00
* Creates the " array " string used as part of the JS tracker .
2019-11-15 23:26:29 +01:00
*
* @ access public
2021-04-27 08:32:47 +02:00
* @ param array $kvs KVS .
* @ return string
2019-11-15 23:26:29 +01:00
*/
function stats_array ( $kvs ) {
/**
* Filter the options added to the JavaScript Stats tracking code .
*
* @ module stats
*
* @ since 1.1 . 0
*
* @ param array $kvs Array of options about the site and page you ' re on .
*/
2021-04-27 08:32:47 +02:00
$kvs = ( array ) apply_filters ( 'stats_array' , $kvs );
$kvs = array_map ( 'addslashes' , $kvs );
$jskvs = array ();
2019-11-15 23:26:29 +01:00
foreach ( $kvs as $k => $v ) {
$jskvs [] = " $k :' $v ' " ;
}
return join ( ',' , $jskvs );
}
/**
* Admin Pages .
*
* @ access public
* @ return void
*/
function stats_admin_menu () {
global $pagenow ;
// If we're at an old Stats URL, redirect to the new one.
// Don't even bother with caps, menu_page_url(), etc. Just do it.
2021-04-27 08:32:47 +02:00
if ( 'index.php' === $pagenow && isset ( $_GET [ 'page' ] ) && 'stats' === $_GET [ 'page' ] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2022-06-16 14:01:47 +02:00
$redirect_url = str_replace ( array ( '/wp-admin/index.php?' , '/wp-admin/?' ), '/wp-admin/admin.php?' , isset ( $_SERVER [ 'REQUEST_URI' ] ) ? filter_var ( wp_unslash ( $_SERVER [ 'REQUEST_URI' ] ) ) : null );
2019-11-15 23:26:29 +01:00
$relative_pos = strpos ( $redirect_url , '/wp-admin/' );
if ( false !== $relative_pos ) {
wp_safe_redirect ( admin_url ( substr ( $redirect_url , $relative_pos + 10 ) ) );
exit ;
}
}
$hook = add_submenu_page ( 'jetpack' , __ ( 'Site Stats' , 'jetpack' ), __ ( 'Site Stats' , 'jetpack' ), 'view_stats' , 'stats' , 'jetpack_admin_ui_stats_report_page_wrapper' );
add_action ( " load- $hook " , 'stats_reports_load' );
}
/**
* Stats Admin Path .
*
* @ access public
* @ return string
*/
function stats_admin_path () {
return Jetpack :: module_configuration_url ( __FILE__ );
}
/**
* Stats Reports Load .
*
* @ access public
* @ return void
*/
function stats_reports_load () {
2021-08-17 08:33:07 +02:00
require_once __DIR__ . '/stats/class-jetpack-stats-upgrade-nudges.php' ;
Jetpack_Stats_Upgrade_Nudges :: init ();
2019-11-15 23:26:29 +01:00
wp_enqueue_script ( 'jquery' );
wp_enqueue_script ( 'postbox' );
wp_enqueue_script ( 'underscore' );
Jetpack_Admin_Page :: load_wrapper_styles ();
add_action ( 'admin_print_styles' , 'stats_reports_css' );
2022-06-16 14:01:47 +02:00
if ( ! empty ( $_GET [ 'nojs' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2019-11-15 23:26:29 +01:00
$parsed = wp_parse_url ( admin_url () );
// Remember user doesn't want JS.
2022-06-16 14:01:47 +02:00
setcookie ( 'stnojs' , '1' , time () + 172800 , $parsed [ 'path' ], COOKIE_DOMAIN , is_ssl (), true ); // 2 days.
2019-11-15 23:26:29 +01:00
}
2022-06-16 14:01:47 +02:00
if ( ! empty ( $_COOKIE [ 'stnojs' ] ) ) {
2019-11-15 23:26:29 +01:00
// Detect if JS is on. If so, remove cookie so next page load is via JS.
add_action ( 'admin_print_footer_scripts' , 'stats_js_remove_stnojs_cookie' );
2021-04-27 08:32:47 +02:00
} elseif ( ! isset ( $_GET [ 'noheader' ] ) && empty ( $_GET [ 'nojs' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2019-11-15 23:26:29 +01:00
// Normal page load. Load page content via JS.
add_action ( 'admin_print_footer_scripts' , 'stats_js_load_page_via_ajax' );
}
}
/**
* Stats Reports CSS .
*
* @ access public
* @ return void
*/
function stats_reports_css () {
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< style type = " text/css " >
2021-08-17 08:33:07 +02:00
#jp-stats-wrap, #jp-stats-report-bottom {
2019-11-15 23:26:29 +01:00
max - width : 1040 px ;
margin : 0 auto ;
overflow : hidden ;
}
#stats-loading-wrap p {
text - align : center ;
font - size : 2 em ;
margin : 7.5 em 15 px 0 0 ;
height : 64 px ;
line - height : 64 px ;
}
</ style >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
}
/**
* Detect if JS is on . If so , remove cookie so next page load is via JS .
*
* @ access public
* @ return void
*/
function stats_js_remove_stnojs_cookie () {
$parsed = wp_parse_url ( admin_url () );
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< script type = " text/javascript " >
/* <![CDATA[ */
document . cookie = 'stnojs=0; expires=Wed, 9 Mar 2011 16:55:50 UTC; path=<?php echo esc_js( $parsed[' path '] ); ?>' ;
/* ]]> */
</ script >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
}
/**
* Normal page load . Load page content via JS .
*
* @ access public
* @ return void
*/
function stats_js_load_page_via_ajax () {
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< script type = " text/javascript " >
/* <![CDATA[ */
if ( - 1 == document . location . href . indexOf ( 'noheader' ) ) {
jQuery ( function ( $ ) {
$ . get ( document . location . href + '&noheader' , function ( responseText ) {
$ ( '#stats-loading-wrap' ) . replaceWith ( responseText );
2021-09-07 21:40:48 +02:00
$ ( '#jp-stats-wrap' )[ 0 ] . dispatchEvent ( new Event ( 'stats-loaded' ) );
2019-11-15 23:26:29 +01:00
} );
} );
}
/* ]]> */
</ script >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
}
2021-04-27 08:32:47 +02:00
/**
* Jetpack Admin Page Wrapper .
*/
function jetpack_admin_ui_stats_report_page_wrapper () {
if ( ! isset ( $_GET [ 'noheader' ] ) && empty ( $_GET [ 'nojs' ] ) && empty ( $_COOKIE [ 'stnojs' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2019-11-15 23:26:29 +01:00
Jetpack_Admin_Page :: wrap_ui ( 'stats_reports_page' , array ( 'is-wide' => true ) );
} else {
stats_reports_page ();
}
}
/**
* Stats Report Page .
*
* @ access public
* @ param bool $main_chart_only ( default : false ) Main Chart Only .
*/
function stats_reports_page ( $main_chart_only = false ) {
2021-04-27 08:32:47 +02:00
if ( isset ( $_GET [ 'dashboard' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2019-11-15 23:26:29 +01:00
return stats_dashboard_widget_content ();
}
2020-05-06 17:20:49 +02:00
$blog_id = stats_get_option ( 'blog_id' );
$stats_url = Redirect :: get_url ( 'calypso-stats' );
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
if ( ! $main_chart_only && ! isset ( $_GET [ 'noheader' ] ) && empty ( $_GET [ 'nojs' ] ) && empty ( $_COOKIE [ 'stnojs' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2019-11-15 23:26:29 +01:00
$nojs_url = add_query_arg ( 'nojs' , '1' );
2021-04-27 08:32:47 +02:00
$http = is_ssl () ? 'https' : 'http' ;
2019-11-15 23:26:29 +01:00
// Loading message. No JS fallback message.
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< div id = " jp-stats-wrap " >
< div class = " wrap " >
< h2 >< ? php esc_html_e ( 'Site Stats' , 'jetpack' ); ?>
< ? php
2021-04-27 08:32:47 +02:00
if ( current_user_can ( 'jetpack_manage_modules' ) ) :
$i18n_headers = jetpack_get_module_i18n ( 'stats' );
?>
2019-11-15 23:26:29 +01:00
< a
style = " font-size:13px; "
href = " <?php echo esc_url( admin_url( 'admin.php?page=jetpack#/settings?term=' . rawurlencode( $i18n_headers['name'] ) ) ); ?> "
>
2021-04-27 08:32:47 +02:00
< ? php esc_html_e ( 'Configure' , 'jetpack' ); ?>
2019-11-15 23:26:29 +01:00
</ a >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
endif ;
2021-04-27 08:32:47 +02:00
/**
* Sets external resource URL .
*
* @ module stats
*
* @ since 1.4 . 0
* @ todo Clean up various uses of this filter . It ' s seemingly filtering different types of images in different places .
*
* @ param string $args URL of external resource .
*/
$static_url = apply_filters ( 'jetpack_static_url' , " { $http } ://en.wordpress.com/i/loading/loading-64.gif " );
2019-11-15 23:26:29 +01:00
?>
</ h2 >
</ div >
< div id = " stats-loading-wrap " class = " wrap " >
2021-04-27 08:32:47 +02:00
< p class = " hide-if-no-js " >< img width = " 32 " height = " 32 " alt = " <?php esc_attr_e( 'Loading…', 'jetpack' ); ?> " src = " <?php echo esc_url( $static_url ); ?> " /></ p >
2020-05-06 17:20:49 +02:00
< p style = " font-size: 11pt; margin: 0; " >< a href = " <?php echo esc_url( $stats_url ); ?> " rel = " noopener noreferrer " target = " _blank " >< ? php esc_html_e ( 'View stats on WordPress.com right now' , 'jetpack' ); ?> </a></p>
2019-11-15 23:26:29 +01:00
< p class = " hide-if-js " >< ? php esc_html_e ( 'Your Site Stats work better with JavaScript enabled.' , 'jetpack' ); ?> <br />
< a href = " <?php echo esc_url( $nojs_url ); ?> " >< ? php esc_html_e ( 'View Site Stats without JavaScript' , 'jetpack' ); ?> </a>.</p>
</ div >
</ div >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
return ;
}
2022-06-16 14:01:47 +02:00
$day = isset ( $_GET [ 'day' ] ) && preg_match ( '/^\d{4}-\d{2}-\d{2}$/' , $_GET [ 'day' ] ) ? $_GET [ 'day' ] : false ; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
2021-04-27 08:32:47 +02:00
$q = array (
2019-11-15 23:26:29 +01:00
'noheader' => 'true' ,
2021-04-27 08:32:47 +02:00
'proxy' => '' ,
'page' => 'stats' ,
'day' => $day ,
'blog' => $blog_id ,
'charset' => get_option ( 'blog_charset' ),
'color' => get_user_option ( 'admin_color' ),
'ssl' => is_ssl (),
'j' => sprintf ( '%s:%s' , JETPACK__API_VERSION , JETPACK__VERSION ),
2019-11-15 23:26:29 +01:00
);
if ( get_locale () !== 'en_US' ) {
$q [ 'jp_lang' ] = get_locale ();
}
// Only show the main chart, without extra header data, or metaboxes.
$q [ 'main_chart_only' ] = $main_chart_only ;
2021-04-27 08:32:47 +02:00
$args = array (
'view' => array ( 'referrers' , 'postviews' , 'searchterms' , 'clicks' , 'post' , 'table' ),
'numdays' => 'int' ,
'day' => 'date' ,
'unit' => array ( '1' , '7' , '31' , 'human' ),
'humanize' => array ( 'true' ),
'num' => 'int' ,
'summarize' => null ,
'post' => 'int' ,
'width' => 'int' ,
'height' => 'int' ,
'data' => 'data' ,
'blog_subscribers' => 'int' ,
2019-11-15 23:26:29 +01:00
'comment_subscribers' => null ,
2021-04-27 08:32:47 +02:00
'type' => array ( 'wpcom' , 'email' , 'pending' ),
'pagenum' => 'int' ,
2022-04-02 10:26:41 +02:00
'masterbar' => null ,
2019-11-15 23:26:29 +01:00
);
foreach ( $args as $var => $vals ) {
2021-04-27 08:32:47 +02:00
if ( ! isset ( $_REQUEST [ $var ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2019-11-15 23:26:29 +01:00
continue ;
2021-04-27 08:32:47 +02:00
}
2022-06-16 14:01:47 +02:00
$val = wp_unslash ( $_REQUEST [ $var ] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2019-11-15 23:26:29 +01:00
if ( is_array ( $vals ) ) {
2022-06-16 14:01:47 +02:00
if ( in_array ( $val , $vals , true ) ) {
$q [ $var ] = $val ;
2021-04-27 08:32:47 +02:00
}
2019-11-15 23:26:29 +01:00
} elseif ( 'int' === $vals ) {
2022-06-16 14:01:47 +02:00
$q [ $var ] = ( int ) $val ;
2019-11-15 23:26:29 +01:00
} elseif ( 'date' === $vals ) {
2022-06-16 14:01:47 +02:00
if ( preg_match ( '/^\d{4}-\d{2}-\d{2}$/' , $val ) ) {
$q [ $var ] = $val ;
2021-04-27 08:32:47 +02:00
}
2019-11-15 23:26:29 +01:00
} elseif ( null === $vals ) {
2021-04-27 08:32:47 +02:00
$q [ $var ] = '' ;
2019-11-15 23:26:29 +01:00
} elseif ( 'data' === $vals ) {
2022-06-16 14:01:47 +02:00
if ( 'index.php' === substr ( $val , 0 , 9 ) ) {
$q [ $var ] = $val ;
2021-04-27 08:32:47 +02:00
}
2019-11-15 23:26:29 +01:00
}
}
2021-04-27 08:32:47 +02:00
if ( isset ( $_GET [ 'chart' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2022-06-16 14:01:47 +02:00
if ( preg_match ( '/^[a-z0-9-]+$/' , $_GET [ 'chart' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
$chart = sanitize_title ( $_GET [ 'chart' ] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
2021-04-27 08:32:47 +02:00
$url = 'https://' . STATS_DASHBOARD_SERVER . " /wp-includes/charts/ { $chart } .php " ;
2019-11-15 23:26:29 +01:00
}
} else {
2021-04-27 08:32:47 +02:00
$url = 'https://' . STATS_DASHBOARD_SERVER . '/wp-admin/index.php' ;
2019-11-15 23:26:29 +01:00
}
2021-04-27 08:32:47 +02:00
$url = add_query_arg ( $q , $url );
$method = 'GET' ;
2019-11-15 23:26:29 +01:00
$timeout = 90 ;
2020-09-15 14:30:05 +02:00
$user_id = 0 ; // Means use the blog token.
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
$get = Client :: remote_request ( compact ( 'url' , 'method' , 'timeout' , 'user_id' ) );
2019-11-15 23:26:29 +01:00
$get_code = wp_remote_retrieve_response_code ( $get );
2020-11-18 09:10:44 +01:00
if ( is_wp_error ( $get ) || ( 2 !== ( int ) ( $get_code / 100 ) && 304 !== $get_code ) || empty ( $get [ 'body' ] ) ) {
2019-11-15 23:26:29 +01:00
stats_print_wp_remote_error ( $get , $url );
} else {
if ( ! empty ( $get [ 'headers' ][ 'content-type' ] ) ) {
$type = $get [ 'headers' ][ 'content-type' ];
if ( substr ( $type , 0 , 5 ) === 'image' ) {
$img = $get [ 'body' ];
header ( 'Content-Type: ' . $type );
header ( 'Content-Length: ' . strlen ( $img ) );
2021-04-27 08:32:47 +02:00
echo $img ; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2019-11-15 23:26:29 +01:00
die ();
}
}
$body = stats_convert_post_titles ( $get [ 'body' ] );
$body = stats_convert_chart_urls ( $body );
$body = stats_convert_image_urls ( $body );
$body = stats_convert_admin_urls ( $body );
2021-04-27 08:32:47 +02:00
echo $body ; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
2019-11-15 23:26:29 +01:00
}
2021-04-27 08:32:47 +02:00
if ( isset ( $_GET [ 'page' ] ) && 'stats' === $_GET [ 'page' ] && ! isset ( $_GET [ 'chart' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2019-11-15 23:26:29 +01:00
$tracking = new Tracking ();
2021-04-27 08:32:47 +02:00
$tracking -> record_user_event ( 'wpa_page_view' , array ( 'path' => 'old_stats' ) );
2019-11-15 23:26:29 +01:00
}
2021-04-27 08:32:47 +02:00
if ( isset ( $_GET [ 'noheader' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2019-11-15 23:26:29 +01:00
die ;
}
}
/**
* Stats Convert Admin Urls .
*
* @ access public
* @ param mixed $html HTML .
* @ return string
*/
function stats_convert_admin_urls ( $html ) {
return str_replace ( 'index.php?page=stats' , 'admin.php?page=stats' , $html );
}
/**
* Stats Convert Image URLs .
*
* @ access public
* @ param mixed $html HTML .
* @ return string
*/
function stats_convert_image_urls ( $html ) {
2021-04-27 08:32:47 +02:00
$url = set_url_scheme ( 'https://' . STATS_DASHBOARD_SERVER );
2019-11-15 23:26:29 +01:00
$html = preg_replace ( '|(["\'])(/i/stats.+)\\1|' , '$1' . $url . '$2$1' , $html );
return $html ;
}
/**
* Callback for preg_replace_callback used in stats_convert_chart_urls ()
*
* @ since 5.6 . 0
*
2021-04-27 08:32:47 +02:00
* @ param array $matches The matches resulting from the preg_replace_callback call .
2019-11-15 23:26:29 +01:00
* @ return string The admin url for the chart .
*/
function jetpack_stats_convert_chart_urls_callback ( $matches ) {
// If there is a query string, change the beginning '?' to a '&' so it fits into the middle of this query string.
return 'admin.php?page=stats&noheader&chart=' . $matches [ 1 ] . str_replace ( '?' , '&' , $matches [ 2 ] );
}
/**
* Stats Convert Chart URLs .
*
* @ access public
* @ param mixed $html HTML .
* @ return string
*/
function stats_convert_chart_urls ( $html ) {
$html = preg_replace_callback (
'|https?://[-.a-z0-9]+/wp-includes/charts/([-.a-z0-9]+).php(\??)|' ,
'jetpack_stats_convert_chart_urls_callback' ,
$html
);
return $html ;
}
/**
* Stats Convert Post Title HTML
*
* @ access public
* @ param mixed $html HTML .
* @ return string
*/
function stats_convert_post_titles ( $html ) {
global $stats_posts ;
$pattern = " <span class='post-( \ d+)-link'>.*?</span> " ;
if ( ! preg_match_all ( " ! $pattern ! " , $html , $matches ) ) {
return $html ;
}
$posts = get_posts (
array (
2021-04-27 08:32:47 +02:00
'include' => implode ( ',' , $matches [ 1 ] ),
'post_type' => 'any' ,
'post_status' => 'any' ,
'numberposts' => - 1 ,
2019-11-15 23:26:29 +01:00
'suppress_filters' => false ,
)
);
foreach ( $posts as $post ) {
$stats_posts [ $post -> ID ] = $post ;
}
$html = preg_replace_callback ( " ! $pattern ! " , 'stats_convert_post_title' , $html );
return $html ;
}
/**
* Stats Convert Post Title Matches .
*
* @ access public
* @ param mixed $matches Matches .
* @ return string
*/
function stats_convert_post_title ( $matches ) {
global $stats_posts ;
$post_id = $matches [ 1 ];
2021-04-27 08:32:47 +02:00
if ( isset ( $stats_posts [ $post_id ] ) ) {
2019-11-15 23:26:29 +01:00
return '<a href="' . get_permalink ( $post_id ) . '" target="_blank">' . get_the_title ( $post_id ) . '</a>' ;
2021-04-27 08:32:47 +02:00
}
2019-11-15 23:26:29 +01:00
return $matches [ 0 ];
}
/**
2022-04-02 10:26:41 +02:00
* CSS to hide the tracking pixel smiley .
* It is now hidden for everyone ( used to be visible if you had set the hide_smile option ) .
2019-11-15 23:26:29 +01:00
*
* @ access public
* @ return void
*/
function stats_hide_smile_css () {
2022-04-02 10:26:41 +02:00
?>
2022-06-16 14:01:47 +02:00
< style > img #wpstats{display:none}</style>
2022-04-02 10:26:41 +02:00
< ? php
2019-11-15 23:26:29 +01:00
}
/**
* Stats Admin Bar Head .
*
* @ access public
* @ return void
*/
function stats_admin_bar_head () {
2021-04-27 08:32:47 +02:00
if ( ! stats_get_option ( 'admin_bar' ) ) {
2019-11-15 23:26:29 +01:00
return ;
2021-04-27 08:32:47 +02:00
}
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
if ( ! current_user_can ( 'view_stats' ) ) {
2019-11-15 23:26:29 +01:00
return ;
2021-04-27 08:32:47 +02:00
}
2019-11-15 23:26:29 +01:00
if ( ! is_admin_bar_showing () ) {
return ;
}
add_action ( 'admin_bar_menu' , 'stats_admin_bar_menu' , 100 );
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< style data - ampdevmode type = 'text/css' >
#wpadminbar .quicklinks li#wp-admin-bar-stats {
height : 32 px ;
}
#wpadminbar .quicklinks li#wp-admin-bar-stats a {
height : 32 px ;
padding : 0 ;
}
#wpadminbar .quicklinks li#wp-admin-bar-stats a div {
height : 32 px ;
width : 95 px ;
overflow : hidden ;
margin : 0 10 px ;
}
#wpadminbar .quicklinks li#wp-admin-bar-stats a:hover div {
width : auto ;
margin : 0 8 px 0 10 px ;
}
#wpadminbar .quicklinks li#wp-admin-bar-stats a img {
height : 24 px ;
margin : 4 px 0 ;
max - width : none ;
border : none ;
}
</ style >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
}
/**
2022-04-02 10:26:41 +02:00
* Gets the image source of the given stats chart .
2019-11-15 23:26:29 +01:00
*
2022-04-02 10:26:41 +02:00
* @ param string $chart Name of the chart .
* @ param array $args Extra list of argument to use in the image source .
* @ return string An image source .
2019-11-15 23:26:29 +01:00
*/
2022-04-02 10:26:41 +02:00
function stats_get_image_chart_src ( $chart , $args = array () ) {
$url = add_query_arg ( 'page' , 'stats' , admin_url ( 'admin.php' ) );
2019-11-15 23:26:29 +01:00
2022-04-02 10:26:41 +02:00
return add_query_arg (
array_merge (
2021-04-27 08:32:47 +02:00
array (
'noheader' => '' ,
'proxy' => '' ,
2022-04-02 10:26:41 +02:00
'chart' => $chart ,
2021-04-27 08:32:47 +02:00
),
2022-04-02 10:26:41 +02:00
$args
),
$url
2021-04-27 08:32:47 +02:00
);
2022-04-02 10:26:41 +02:00
}
2019-11-15 23:26:29 +01:00
2022-04-02 10:26:41 +02:00
/**
* Stats AdminBar .
*
* @ access public
* @ param mixed $wp_admin_bar WPAdminBar .
* @ return void
*/
function stats_admin_bar_menu ( & $wp_admin_bar ) {
$img_src = esc_attr ( stats_get_image_chart_src ( 'admin-bar-hours-scale' ) );
$img_src_2x = esc_attr ( stats_get_image_chart_src ( 'admin-bar-hours-scale-2x' ) );
$alt = esc_attr ( __ ( 'Stats' , 'jetpack' ) );
$title = esc_attr ( __ ( 'Views over 48 hours. Click for more Site Stats.' , 'jetpack' ) );
2019-11-15 23:26:29 +01:00
$menu = array (
'id' => 'stats' ,
2022-04-02 10:26:41 +02:00
'href' => add_query_arg ( 'page' , 'stats' , admin_url ( 'admin.php' ) ), // no menu_page_url() blog-side.
2019-11-15 23:26:29 +01:00
'title' => " <div><img src=' $img_src ' srcset=' $img_src 1x, $img_src_2x 2x' width='112' height='24' alt=' $alt ' title=' $title '></div> " ,
);
$wp_admin_bar -> add_menu ( $menu );
}
/**
2022-04-02 10:26:41 +02:00
*
* Deprecated . The stats module should not update blog details . This is handled by Sync .
*
2019-11-15 23:26:29 +01:00
* Stats Update Blog .
*
* @ access public
* @ return void
2022-04-02 10:26:41 +02:00
*
* @ deprecated since 10.3 .
2019-11-15 23:26:29 +01:00
*/
function stats_update_blog () {
2022-04-02 10:26:41 +02:00
deprecated_function ( __METHOD__ , 'jetpack-10.3' );
2020-09-15 14:30:05 +02:00
XMLRPC_Async_Call :: add_call ( 'jetpack.updateBlog' , 0 , stats_get_blog () );
2019-11-15 23:26:29 +01:00
}
/**
* Stats Get Blog .
*
* @ access public
* @ return string
*/
function stats_get_blog () {
$home = wp_parse_url ( trailingslashit ( get_option ( 'home' ) ) );
$blog = array (
'host' => $home [ 'host' ],
'path' => $home [ 'path' ],
'blogname' => get_option ( 'blogname' ),
'blogdescription' => get_option ( 'blogdescription' ),
'siteurl' => get_option ( 'siteurl' ),
'gmt_offset' => get_option ( 'gmt_offset' ),
'timezone_string' => get_option ( 'timezone_string' ),
'stats_version' => STATS_VERSION ,
'stats_api' => 'jetpack' ,
'page_on_front' => get_option ( 'page_on_front' ),
'permalink_structure' => get_option ( 'permalink_structure' ),
'category_base' => get_option ( 'category_base' ),
'tag_base' => get_option ( 'tag_base' ),
);
$blog = array_merge ( stats_get_options (), $blog );
unset ( $blog [ 'roles' ], $blog [ 'blog_id' ] );
return stats_esc_html_deep ( $blog );
}
/**
* Modified from stripslashes_deep ()
*
* @ access public
* @ param mixed $value Value .
* @ return string
*/
function stats_esc_html_deep ( $value ) {
if ( is_array ( $value ) ) {
$value = array_map ( 'stats_esc_html_deep' , $value );
} elseif ( is_object ( $value ) ) {
$vars = get_object_vars ( $value );
foreach ( $vars as $key => $data ) {
$value -> { $key } = stats_esc_html_deep ( $data );
}
} elseif ( is_string ( $value ) ) {
$value = esc_html ( $value );
}
return $value ;
}
/**
* Stats xmlrpc_methods function .
*
* @ access public
* @ param mixed $methods Methods .
* @ return array
*/
function stats_xmlrpc_methods ( $methods ) {
$my_methods = array (
'jetpack.getBlog' => 'stats_get_blog' ,
);
return array_merge ( $methods , $my_methods );
}
/**
* Stats Dashboard Widget Options .
*
* @ access public
* @ return array
*/
function stats_dashboard_widget_options () {
2021-04-27 08:32:47 +02:00
$defaults = array (
'chart' => 1 ,
'top' => 1 ,
'search' => 7 ,
);
$options = get_option ( 'stats_dashboard_widget' );
if ( ( ! $options ) || ! is_array ( $options ) ) {
2019-11-15 23:26:29 +01:00
$options = array ();
}
// Ignore obsolete option values.
$intervals = array ( 1 , 7 , 31 , 90 , 365 );
foreach ( array ( 'top' , 'search' ) as $key ) {
2021-04-27 08:32:47 +02:00
if ( isset ( $options [ $key ] ) && ! in_array ( ( int ) $options [ $key ], $intervals , true ) ) {
2019-11-15 23:26:29 +01:00
unset ( $options [ $key ] );
}
}
return array_merge ( $defaults , $options );
}
/**
* Stats Dashboard Widget Control .
*
* @ access public
* @ return void
*/
function stats_dashboard_widget_control () {
$periods = array (
2021-04-27 08:32:47 +02:00
'1' => __ ( 'day' , 'jetpack' ),
'7' => __ ( 'week' , 'jetpack' ),
2019-11-15 23:26:29 +01:00
'31' => __ ( 'month' , 'jetpack' ),
);
$intervals = array (
2021-04-27 08:32:47 +02:00
'1' => __ ( 'the past day' , 'jetpack' ),
'7' => __ ( 'the past week' , 'jetpack' ),
'31' => __ ( 'the past month' , 'jetpack' ),
'90' => __ ( 'the past quarter' , 'jetpack' ),
2019-11-15 23:26:29 +01:00
'365' => __ ( 'the past year' , 'jetpack' ),
);
2021-04-27 08:32:47 +02:00
$defaults = array (
'top' => 1 ,
2019-11-15 23:26:29 +01:00
'search' => 7 ,
);
$options = stats_dashboard_widget_options ();
2022-06-16 14:01:47 +02:00
if ( isset ( $_SERVER [ 'REQUEST_METHOD' ] ) && 'post' === strtolower ( filter_var ( wp_unslash ( $_SERVER [ 'REQUEST_METHOD' ] ) ) ) && isset ( $_POST [ 'widget_id' ] ) && 'dashboard_stats' === $_POST [ 'widget_id' ] ) { // phpcs:ignore WordPress.Security.NonceVerification
2021-04-27 08:32:47 +02:00
if ( isset ( $periods [ $_POST [ 'chart' ] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
2022-06-16 14:01:47 +02:00
$options [ 'chart' ] = filter_var ( wp_unslash ( $_POST [ 'chart' ] ) ); // phpcs:ignore WordPress.Security.NonceVerification
2019-11-15 23:26:29 +01:00
}
foreach ( array ( 'top' , 'search' ) as $key ) {
2021-04-27 08:32:47 +02:00
if ( isset ( $intervals [ $_POST [ $key ] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
2022-06-16 14:01:47 +02:00
$options [ $key ] = filter_var ( wp_unslash ( $_POST [ $key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification
2021-04-27 08:32:47 +02:00
} else {
$options [ $key ] = $defaults [ $key ];
2019-11-15 23:26:29 +01:00
}
}
update_option ( 'stats_dashboard_widget' , $options );
}
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< p >
2021-04-27 08:32:47 +02:00
< label for = " chart " >< ? php esc_html_e ( 'Chart stats by' , 'jetpack' ); ?> </label>
2019-11-15 23:26:29 +01:00
< select id = " chart " name = " chart " >
< ? php
foreach ( $periods as $val => $label ) {
2021-04-27 08:32:47 +02:00
?>
< option value = " <?php echo esc_attr( $val ); ?> " < ? php selected ( $val , $options [ 'chart' ] ); ?> ><?php echo esc_html( $label ); ?></option>
2019-11-15 23:26:29 +01:00
< ? php
}
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
</ select >.
</ p >
< p >
< label for = " top " >< ? php esc_html_e ( 'Show top posts over' , 'jetpack' ); ?> </label>
< select id = " top " name = " top " >
< ? php
foreach ( $intervals as $val => $label ) {
2021-04-27 08:32:47 +02:00
?>
< option value = " <?php echo esc_attr( $val ); ?> " < ? php selected ( $val , $options [ 'top' ] ); ?> ><?php echo esc_html( $label ); ?></option>
2019-11-15 23:26:29 +01:00
< ? php
}
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
</ select >.
</ p >
< p >
< label for = " search " >< ? php esc_html_e ( 'Show top search terms over' , 'jetpack' ); ?> </label>
< select id = " search " name = " search " >
< ? php
foreach ( $intervals as $val => $label ) {
2021-04-27 08:32:47 +02:00
?>
< option value = " <?php echo esc_attr( $val ); ?> " < ? php selected ( $val , $options [ 'search' ] ); ?> ><?php echo esc_html( $label ); ?></option>
2019-11-15 23:26:29 +01:00
< ? php
}
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
</ select >.
</ p >
< ? php
}
/**
* Jetpack Stats Dashboard Widget .
*
* @ access public
* @ return void
*/
function stats_jetpack_dashboard_widget () {
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< form id = " stats_dashboard_widget_control " action = " <?php echo esc_url( admin_url() ); ?> " method = " post " >
< ? php stats_dashboard_widget_control (); ?>
< ? php wp_nonce_field ( 'edit-dashboard-widget_dashboard_stats' , 'dashboard-widget-nonce' ); ?>
< input type = " hidden " name = " widget_id " value = " dashboard_stats " />
< ? php submit_button ( __ ( 'Submit' , 'jetpack' ) ); ?>
</ form >
2021-04-27 08:32:47 +02:00
< button type = " button " class = " handlediv js-toggle-stats_dashboard_widget_control " aria - expanded = " true " >
< span class = " screen-reader-text " >< ? php esc_html_e ( 'Configure' , 'jetpack' ); ?> </span>
< span class = " toggle-indicator " aria - hidden = " true " ></ span >
</ button >
2019-11-15 23:26:29 +01:00
< div id = " dashboard_stats " >
< div class = " inside " >
< div style = " height: 250px; " ></ div >
</ div >
</ div >
< ? php
}
/**
* JavaScript and CSS for dashboard widget .
*
* @ access public
* @ return void
*/
2021-04-27 08:32:47 +02:00
function stats_dashboard_head () {
?>
2019-11-15 23:26:29 +01:00
< script type = " text/javascript " >
/* <![CDATA[ */
jQuery ( function ( $ ) {
var dashStats = jQuery ( '#dashboard_stats div.inside' );
if ( dashStats . find ( '.dashboard-widget-control-form' ) . length ) {
return ;
}
if ( ! dashStats . length ) {
dashStats = jQuery ( '#dashboard_stats div.dashboard-widget-content' );
var h = parseInt ( dashStats . parent () . height () ) - parseInt ( dashStats . prev () . height () );
var args = 'width=' + dashStats . width () + '&height=' + h . toString ();
} else {
if ( jQuery ( '#dashboard_stats' ) . hasClass ( 'postbox' ) ) {
var args = 'width=' + ( dashStats . prev () . width () * 2 ) . toString ();
} else {
var args = 'width=' + ( dashStats . width () * 2 ) . toString ();
}
}
dashStats
. not ( '.dashboard-widget-control' )
. load ( 'admin.php?page=stats&noheader&dashboard&' + args );
jQuery ( window ) . one ( 'resize' , function () {
jQuery ( '#stat-chart' ) . css ( 'width' , 'auto' );
} );
2021-04-27 08:32:47 +02:00
// Widget settings toggle container.
var toggle = $ ( '.js-toggle-stats_dashboard_widget_control' );
// Move the toggle in the widget header.
toggle . appendTo ( '#jetpack_summary_widget .handle-actions' );
// Toggle settings when clicking on it.
toggle . show () . click ( function ( e ) {
e . preventDefault ();
e . stopImmediatePropagation ();
$ ( this ) . parent () . toggleClass ( 'controlVisible' );
$ ( '#stats_dashboard_widget_control' ) . slideToggle ();
} );
2019-11-15 23:26:29 +01:00
} );
/* ]]> */
</ script >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
}
/**
* Stats Dashboard Widget Content .
*
* @ access public
* @ return void
*/
function stats_dashboard_widget_content () {
2022-06-16 14:01:47 +02:00
$width = isset ( $_GET [ 'width' ] ) ? intval ( $_GET [ 'width' ] ) / 2 : null ; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$height = isset ( $_GET [ 'height' ] ) ? intval ( $_GET [ 'height' ] ) - 36 : null ; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
2021-04-27 08:32:47 +02:00
if ( ! $width || $width < 250 ) {
2019-11-15 23:26:29 +01:00
$width = 370 ;
}
2021-04-27 08:32:47 +02:00
if ( ! $height || $height < 230 ) {
2019-11-15 23:26:29 +01:00
$height = 180 ;
}
2021-04-27 08:32:47 +02:00
$_width = $width - 5 ;
2022-04-02 10:26:41 +02:00
$_height = $height - 5 ;
2019-11-15 23:26:29 +01:00
$options = stats_dashboard_widget_options ();
$blog_id = Jetpack_Options :: get_option ( 'id' );
$q = array (
'noheader' => 'true' ,
2021-04-27 08:32:47 +02:00
'proxy' => '' ,
'blog' => $blog_id ,
'page' => 'stats' ,
'chart' => '' ,
'unit' => $options [ 'chart' ],
'color' => get_user_option ( 'admin_color' ),
'width' => $_width ,
'height' => $_height ,
'ssl' => is_ssl (),
'j' => sprintf ( '%s:%s' , JETPACK__API_VERSION , JETPACK__VERSION ),
2019-11-15 23:26:29 +01:00
);
2021-04-27 08:32:47 +02:00
$url = 'https://' . STATS_DASHBOARD_SERVER . '/wp-admin/index.php' ;
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
$url = add_query_arg ( $q , $url );
$method = 'GET' ;
2019-11-15 23:26:29 +01:00
$timeout = 90 ;
2020-09-15 14:30:05 +02:00
$user_id = 0 ; // Means use the blog token.
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
$get = Client :: remote_request ( compact ( 'url' , 'method' , 'timeout' , 'user_id' ) );
2019-11-15 23:26:29 +01:00
$get_code = wp_remote_retrieve_response_code ( $get );
2020-11-18 09:10:44 +01:00
if ( is_wp_error ( $get ) || ( 2 !== ( int ) ( $get_code / 100 ) && 304 !== $get_code ) || empty ( $get [ 'body' ] ) ) {
2019-11-15 23:26:29 +01:00
stats_print_wp_remote_error ( $get , $url );
} else {
$body = stats_convert_post_titles ( $get [ 'body' ] );
$body = stats_convert_chart_urls ( $body );
$body = stats_convert_image_urls ( $body );
2021-04-27 08:32:47 +02:00
echo $body ; // phpcs:ignore WordPress.Security.EscapeOutput
2019-11-15 23:26:29 +01:00
}
$post_ids = array ();
2021-07-23 11:58:50 +02:00
$csv_end_date = current_time ( 'Y-m-d' );
2021-04-27 08:32:47 +02:00
$csv_args = array (
'top' => " &limit=8&end= $csv_end_date " ,
'search' => " &limit=5&end= $csv_end_date " ,
);
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
$top_posts = stats_get_csv ( 'postviews' , " days= $options[top] $csv_args[top] " );
foreach ( $top_posts as $i => $post ) {
2019-11-15 23:26:29 +01:00
if ( 0 === $post [ 'post_id' ] ) {
2021-04-27 08:32:47 +02:00
unset ( $top_posts [ $i ] );
2019-11-15 23:26:29 +01:00
continue ;
}
$post_ids [] = $post [ 'post_id' ];
}
// Cache.
get_posts ( array ( 'include' => join ( ',' , array_unique ( $post_ids ) ) ) );
2021-04-27 08:32:47 +02:00
$searches = array ();
$search_terms = stats_get_csv ( 'searchterms' , " days= $options[search] $csv_args[search] " );
foreach ( $search_terms as $search_term ) {
2019-11-15 23:26:29 +01:00
if ( 'encrypted_search_terms' === $search_term [ 'searchterm' ] ) {
continue ;
}
$searches [] = esc_html ( $search_term [ 'searchterm' ] );
}
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< div id = " stats-info " >
< div id = " top-posts " class = 'stats-section' >
< div class = " stats-section-inner " >
2021-04-27 08:32:47 +02:00
< h3 class = " heading " >< ? php esc_html_e ( 'Top Posts' , 'jetpack' ); ?> </h3>
2019-11-15 23:26:29 +01:00
< ? php
2021-04-27 08:32:47 +02:00
if ( empty ( $top_posts ) ) {
?>
< p class = " nothing " >< ? php esc_html_e ( 'Sorry, nothing to report.' , 'jetpack' ); ?> </p>
2019-11-15 23:26:29 +01:00
< ? php
2021-04-27 08:32:47 +02:00
} else {
foreach ( $top_posts as $post ) {
if ( ! get_post ( $post [ 'post_id' ] ) ) {
continue ;
}
?>
< p >
< ? php
printf (
2021-09-07 21:40:48 +02:00
esc_html (
/* Translators: Stats dashboard widget Post list with view count: "Post Title 1 View (or Views if plural)". */
_n ( '%1$s %2$s View' , '%1$s %2$s Views' , $post [ 'views' ], 'jetpack' )
),
2021-04-27 08:32:47 +02:00
'<a href="' . esc_url ( get_permalink ( $post [ 'post_id' ] ) ) . '">' . esc_html ( get_the_title ( $post [ 'post_id' ] ) ) . '</a>' ,
esc_html ( number_format_i18n ( $post [ 'views' ] ) )
);
?>
</ p >
2019-11-15 23:26:29 +01:00
< ? php
2021-04-27 08:32:47 +02:00
}
2019-11-15 23:26:29 +01:00
}
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
</ div >
</ div >
< div id = " top-search " class = 'stats-section' >
< div class = " stats-section-inner " >
2021-04-27 08:32:47 +02:00
< h3 class = " heading " >< ? php esc_html_e ( 'Top Searches' , 'jetpack' ); ?> </h3>
2019-11-15 23:26:29 +01:00
< ? php
2021-04-27 08:32:47 +02:00
if ( empty ( $searches ) ) {
?>
< p class = " nothing " >< ? php esc_html_e ( 'Sorry, nothing to report.' , 'jetpack' ); ?> </p>
2019-11-15 23:26:29 +01:00
< ? php
2021-04-27 08:32:47 +02:00
} else {
foreach ( $searches as $search_term_item ) {
printf (
'<p>%s</p>' ,
esc_html ( $search_term_item )
);
}
2019-11-15 23:26:29 +01:00
}
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
</ div >
</ div >
</ div >
< div class = " clear " ></ div >
< div class = " stats-view-all " >
2021-04-27 08:32:47 +02:00
< ? php
2020-05-06 17:20:49 +02:00
$stats_day_url = Redirect :: get_url ( 'calypso-stats-day' );
2019-11-15 23:26:29 +01:00
printf (
'<a class="button" target="_blank" rel="noopener noreferrer" href="%1$s">%2$s</a>' ,
2020-05-06 17:20:49 +02:00
esc_url ( $stats_day_url ),
2019-11-15 23:26:29 +01:00
esc_html__ ( 'View all stats' , 'jetpack' )
);
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
</ div >
< div class = " clear " ></ div >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
exit ;
}
/**
* Stats Print WP Remote Error .
*
* @ access public
* @ param mixed $get Get .
* @ param mixed $url URL .
* @ return void
*/
function stats_print_wp_remote_error ( $get , $url ) {
2021-04-27 08:32:47 +02:00
$state_name = 'stats_remote_error_' . substr ( md5 ( $url ), 0 , 8 );
2019-11-15 23:26:29 +01:00
$previous_error = Jetpack :: state ( $state_name );
2021-04-27 08:32:47 +02:00
$error = md5 ( wp_json_encode ( compact ( 'get' , 'url' ) ) );
2019-11-15 23:26:29 +01:00
Jetpack :: state ( $state_name , $error );
if ( $error !== $previous_error ) {
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< div class = " wrap " >
< p >< ? php esc_html_e ( 'We were unable to get your stats just now. Please reload this page to try again.' , 'jetpack' ); ?> </p>
</ div >
2021-04-27 08:32:47 +02:00
< ? php
2019-11-15 23:26:29 +01:00
return ;
}
2021-04-27 08:32:47 +02:00
?>
2019-11-15 23:26:29 +01:00
< div class = " wrap " >
2021-04-27 08:32:47 +02:00
< p >
< ? php
printf (
/* translators: placeholder is an a href for a support site. */
esc_html__ ( 'We were unable to get your stats just now. Please reload this page to try again. If this error persists, please contact %1$s. In your report, please include the information below.' , 'jetpack' ),
sprintf (
'<a href="https://support.wordpress.com/contact/?jetpack=needs-service">%s</a>' ,
esc_html__ ( 'Jetpack Support' , 'jetpack' )
)
);
?>
</ p >
2019-11-15 23:26:29 +01:00
< pre >
2022-06-16 14:01:47 +02:00
User Agent : " <?php echo isset( $_SERVER['HTTP_USER_AGENT'] ) ? esc_html( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?> "
Page URL : " http<?php echo ( is_ssl() ? 's' : '' ) . '://' . esc_html( ( isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : '' ) . ( isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '' ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized ?> "
2019-11-15 23:26:29 +01:00
API URL : " <?php echo esc_url( $url ); ?> "
2021-04-27 08:32:47 +02:00
< ? php
if ( is_wp_error ( $get ) ) {
foreach ( $get -> get_error_codes () as $code ) {
foreach ( $get -> get_error_messages ( $code ) as $message ) {
?>
< ? php print esc_html ( $code ) . ': "' . esc_html ( $message ) . '"' ; ?>
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
< ? php
}
2019-11-15 23:26:29 +01:00
}
2021-04-27 08:32:47 +02:00
} else {
$get_code = wp_remote_retrieve_response_code ( $get );
$content_length = strlen ( wp_remote_retrieve_body ( $get ) );
?>
Response code : " <?php print esc_html( $get_code ); ?> "
Content length : " <?php print esc_html( $content_length ); ?> "
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
< ? php
}
?>
</ pre >
2019-11-15 23:26:29 +01:00
</ div >
< ? php
}
/**
* Get stats from WordPress . com
*
* @ param string $table The stats which you want to retrieve : postviews , or searchterms .
* @ param array $args {
* An associative array of arguments .
*
* @ type bool $end The last day of the desired time frame . Format is 'Y-m-d' ( e . g . 2007 - 05 - 01 )
* and default timezone is UTC date . Default value is Now .
* @ type string $days The length of the desired time frame . Default is 30. Maximum 90 days .
* @ type int $limit The maximum number of records to return . Default is 10. Maximum 100.
* @ type int $post_id The ID of the post to retrieve stats data for
* @ type string $summarize If present , summarizes all matching records . Default Null .
*
* }
*
* @ return array {
* An array of post view data , each post as an array
*
* array {
* The post view data for a single post
*
* @ type string $post_id The ID of the post
* @ type string $post_title The title of the post
* @ type string $post_permalink The permalink for the post
* @ type string $views The number of views for the post within the $num_days specified
* }
* }
*/
function stats_get_csv ( $table , $args = null ) {
2021-04-27 08:32:47 +02:00
$defaults = array (
'end' => false ,
'days' => false ,
'limit' => 3 ,
'post_id' => false ,
'summarize' => '' ,
);
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
$args = wp_parse_args ( $args , $defaults );
$args [ 'table' ] = $table ;
2019-11-15 23:26:29 +01:00
$args [ 'blog_id' ] = Jetpack_Options :: get_option ( 'id' );
$stats_csv_url = add_query_arg ( $args , 'https://stats.wordpress.com/csv.php' );
$key = md5 ( $stats_csv_url );
// Get cache.
$stats_cache = get_option ( 'stats_cache' );
if ( ! $stats_cache || ! is_array ( $stats_cache ) ) {
$stats_cache = array ();
}
// Return or expire this key.
if ( isset ( $stats_cache [ $key ] ) ) {
$time = key ( $stats_cache [ $key ] );
if ( time () - $time < 300 ) {
return $stats_cache [ $key ][ $time ];
}
unset ( $stats_cache [ $key ] );
}
$stats_rows = array ();
do {
2021-04-27 08:32:47 +02:00
$stats = stats_get_remote_csv ( $stats_csv_url );
if ( ! $stats ) {
2019-11-15 23:26:29 +01:00
break ;
}
$labels = array_shift ( $stats );
if ( 0 === stripos ( $labels [ 0 ], 'error' ) ) {
break ;
}
$stats_rows = array ();
for ( $s = 0 ; isset ( $stats [ $s ] ); $s ++ ) {
$row = array ();
foreach ( $labels as $col => $label ) {
$row [ $label ] = $stats [ $s ][ $col ];
}
$stats_rows [] = $row ;
}
} while ( 0 );
// Expire old keys.
foreach ( $stats_cache as $k => $cache ) {
if ( ! is_array ( $cache ) || 300 < time () - key ( $cache ) ) {
unset ( $stats_cache [ $k ] );
}
}
// Set cache.
$stats_cache [ $key ] = array ( time () => $stats_rows );
update_option ( 'stats_cache' , $stats_cache );
return $stats_rows ;
}
/**
* Stats get remote CSV .
*
* @ access public
* @ param mixed $url URL .
* @ return array
*/
function stats_get_remote_csv ( $url ) {
2021-04-27 08:32:47 +02:00
$method = 'GET' ;
2019-11-15 23:26:29 +01:00
$timeout = 90 ;
2020-09-15 14:30:05 +02:00
$user_id = 0 ; // Blog token.
2019-11-15 23:26:29 +01:00
2021-04-27 08:32:47 +02:00
$get = Client :: remote_request ( compact ( 'url' , 'method' , 'timeout' , 'user_id' ) );
2019-11-15 23:26:29 +01:00
$get_code = wp_remote_retrieve_response_code ( $get );
2020-11-18 09:10:44 +01:00
if ( is_wp_error ( $get ) || ( 2 !== ( int ) ( $get_code / 100 ) && 304 !== $get_code ) || empty ( $get [ 'body' ] ) ) {
2019-11-15 23:26:29 +01:00
return array (); // @todo: return an error?
} else {
return stats_str_getcsv ( $get [ 'body' ] );
}
}
/**
2021-04-27 08:32:47 +02:00
* Recursively run str_getcsv on the stats csv .
*
* @ since 9.7 . 0 Remove custom handling since str_getcsv is available on all servers running this now .
2019-11-15 23:26:29 +01:00
*
* @ param mixed $csv CSV .
* @ return array .
*/
function stats_str_getcsv ( $csv ) {
2021-04-27 08:32:47 +02:00
$lines = str_getcsv ( $csv , " \n " );
return array_map ( 'str_getcsv' , $lines );
2019-11-15 23:26:29 +01:00
}
/**
* Abstract out building the rest api stats path .
*
* @ param string $resource Resource .
* @ return string
*/
function jetpack_stats_api_path ( $resource = '' ) {
$resource = ltrim ( $resource , '/' );
return sprintf ( '/sites/%d/stats/%s' , stats_get_option ( 'blog_id' ), $resource );
}
/**
* Fetches stats data from the REST API . Caches locally for 5 minutes .
*
* @ link : https :// developer . wordpress . com / docs / api / 1.1 / get / sites /% 24 site / stats /
* @ access public
* @ param array $args ( default : array ()) The args that are passed to the endpoint .
* @ param string $resource ( default : '' ) Optional sub - endpoint following / stats /.
* @ return array | WP_Error .
*/
function stats_get_from_restapi ( $args = array (), $resource = '' ) {
$endpoint = jetpack_stats_api_path ( $resource );
$api_version = '1.1' ;
$args = wp_parse_args ( $args , array () );
2021-04-27 08:32:47 +02:00
$cache_key = md5 ( implode ( '|' , array ( $endpoint , $api_version , wp_json_encode ( $args ) ) ) );
2019-11-15 23:26:29 +01:00
$transient_name = " jetpack_restapi_stats_cache_ { $cache_key } " ;
$stats_cache = get_transient ( $transient_name );
// Return or expire this key.
if ( $stats_cache ) {
$time = key ( $stats_cache );
2021-04-27 08:32:47 +02:00
$data = $stats_cache [ $time ]; // WP_Error or string (JSON encoded object).
2019-11-15 23:26:29 +01:00
if ( is_wp_error ( $data ) ) {
return $data ;
}
return ( object ) array_merge ( array ( 'cached_at' => $time ), ( array ) json_decode ( $data ) );
}
// Do the dirty work.
$response = Client :: wpcom_json_api_request_as_blog ( $endpoint , $api_version , $args );
if ( 200 !== wp_remote_retrieve_response_code ( $response ) ) {
2021-04-27 08:32:47 +02:00
// WP_Error.
2019-11-15 23:26:29 +01:00
$data = is_wp_error ( $response ) ? $response : new WP_Error ( 'stats_error' );
2021-04-27 08:32:47 +02:00
// WP_Error.
2019-11-15 23:26:29 +01:00
$return = $data ;
} else {
2021-04-27 08:32:47 +02:00
// string (JSON encoded object).
2019-11-15 23:26:29 +01:00
$data = wp_remote_retrieve_body ( $response );
2021-04-27 08:32:47 +02:00
// object (rare: null on JSON failure).
2019-11-15 23:26:29 +01:00
$return = json_decode ( $data );
}
// To reduce size in storage: store with time as key, store JSON encoded data (unless error).
set_transient ( $transient_name , array ( time () => $data ), 5 * MINUTE_IN_SECONDS );
return $return ;
}
/**
* Load CSS needed for Stats column width in WP - Admin area .
*
* @ since 4.7 . 0
*/
function jetpack_stats_load_admin_css () {
?>
< style type = " text/css " >
. fixed . column - stats {
width : 5 em ;
}
</ style >
< ? php
}
/**
* Set header for column that allows to go to WordPress . com to see an entry ' s stats .
*
* @ param array $columns An array of column names .
*
* @ since 4.7 . 0
*
* @ return mixed
*/
2021-04-27 08:32:47 +02:00
function jetpack_stats_post_table ( $columns ) {
// Adds a stats link on the edit posts page.
if ( ! current_user_can ( 'view_stats' ) || ! ( new Connection_Manager ( 'jetpack' ) ) -> is_user_connected () ) {
2019-11-15 23:26:29 +01:00
return $columns ;
}
2022-06-16 14:01:47 +02:00
2021-04-27 08:32:47 +02:00
// Array-Fu to add before comments.
$pos = array_search ( 'comments' , array_keys ( $columns ), true );
2022-06-16 14:01:47 +02:00
// Fallback to the last position if the post type does not support comments.
if ( ! is_int ( $pos ) ) {
$pos = count ( $columns );
}
// Final fallback, if the array was malformed by another plugin for example.
2019-11-15 23:26:29 +01:00
if ( ! is_int ( $pos ) ) {
return $columns ;
}
2022-06-16 14:01:47 +02:00
2019-11-15 23:26:29 +01:00
$chunks = array_chunk ( $columns , $pos , true );
$chunks [ 0 ][ 'stats' ] = esc_html__ ( 'Stats' , 'jetpack' );
return call_user_func_array ( 'array_merge' , $chunks );
}
/**
* Set content for cell with link to an entry ' s stats in WordPress . com .
*
* @ param string $column The name of the column to display .
* @ param int $post_id The current post ID .
*
* @ since 4.7 . 0
*
* @ return mixed
*/
function jetpack_stats_post_table_cell ( $column , $post_id ) {
2021-04-27 08:32:47 +02:00
if ( 'stats' === $column ) {
if ( 'publish' !== get_post_status ( $post_id ) ) {
2019-11-15 23:26:29 +01:00
printf (
'<span aria-hidden="true">—</span><span class="screen-reader-text">%s</span>' ,
esc_html__ ( 'No stats' , 'jetpack' )
);
} else {
2020-05-06 17:20:49 +02:00
$stats_post_url = Redirect :: get_url (
'calypso-stats-post' ,
array (
'path' => $post_id ,
)
);
2019-11-15 23:26:29 +01:00
printf (
'<a href="%s" title="%s" class="dashicons dashicons-chart-bar" target="_blank"></a>' ,
2020-05-06 17:20:49 +02:00
esc_url ( $stats_post_url ),
2019-11-15 23:26:29 +01:00
esc_html__ ( 'View stats for this post in WordPress.com' , 'jetpack' )
);
}
}
}