PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.7
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.7
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
desktop-mode / includes / widgets / widget-site-views.php

widget-site-views.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.9.7, at includes/widgets/widget-site-views.php

167 lines 4.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Desktop Mode — Site Views Widget.
4 *
5 * Sparkline graph of page views over the last 7 days with
6 * week-over-week delta. Tries Jetpack Stats first, falls back
7 * to a _post_views_YYYY-MM-DD meta-key aggregator.
8 *
9 * Refresh: every 10 minutes.
10 * Requires: Desktop Mode 0.18.0+ (desktop_mode_register_widget).
11 *
12 * @package WPDesktopMode
13 * @since 0.26.0
14 */
15
16 defined( 'ABSPATH' ) || exit;
17
18 /**
19 * Register the REST endpoint that aggregates per-post view counts
20 * from the _post_views_YYYY-MM-DD meta key (plain-WP fallback).
21 *
22 * Route: GET /desktop-mode/v1/site-views-meta
23 * Permission: edit_posts.
24 *
25 * @since 0.26.0
26 */
27 function desktop_mode_register_site_views_rest_route() {
28 register_rest_route(
29 'desktop-mode/v1',
30 '/site-views-meta',
31 array(
32 'methods' => WP_REST_Server::READABLE,
33 'callback' => 'desktop_mode_site_views_meta_callback',
34 'permission_callback' => static function () {
35 return current_user_can( 'edit_posts' );
36 },
37 )
38 );
39 }
40 add_action( 'rest_api_init', 'desktop_mode_register_site_views_rest_route' );
41
42 /**
43 * Aggregate _post_views_YYYY-MM-DD meta across all posts for 14 days.
44 *
45 * The result is cached in a 5-minute transient: the aggregation runs
46 * 14 SUM() queries over postmeta, the widget only refreshes every
47 * 10 minutes, and the data is site-wide (not per-user) — so every
48 * concurrent viewer can share one computation. View counts accrue
49 * continuously, so a short TTL is the invalidation strategy; no
50 * event-based purge is needed.
51 *
52 * @param WP_REST_Request $request REST request.
53 * @return array
54 */
55 function desktop_mode_site_views_meta_callback( $request ) {
56 global $wpdb;
57
58 $cached = get_transient( 'desktop_mode_site_views_meta' );
59 if ( is_array( $cached ) ) {
60 return $cached;
61 }
62
63 $rows = array();
64 $today = current_time( 'Y-m-d' );
65
66 for ( $i = 0; $i < 14; $i++ ) {
67 $date = gmdate( 'Y-m-d', strtotime( $today . ' -' . $i . ' days' ) );
68 $meta_key = '_post_views_' . $date;
69 $total = (int) $wpdb->get_var(
70 $wpdb->prepare(
71 "SELECT COALESCE( SUM( CAST( meta_value AS UNSIGNED ) ), 0 )
72 FROM {$wpdb->postmeta}
73 WHERE meta_key = %s",
74 $meta_key
75 )
76 );
77 $rows[] = array(
78 'date' => $date,
79 'views' => $total,
80 );
81 }
82
83 $has_data = array_sum( array_column( $rows, 'views' ) ) > 0;
84
85 $result = array(
86 'source' => 'post-meta',
87 'has_data' => $has_data,
88 'days' => array_reverse( $rows ),
89 );
90
91 set_transient( 'desktop_mode_site_views_meta', $result, 5 * MINUTE_IN_SECONDS );
92
93 return $result;
94 }
95
96 /**
97 * Register the JS + CSS assets.
98 *
99 * @since 0.26.0
100 */
101 function desktop_mode_register_site_views_widget_assets() {
102 $suffix = desktop_mode_asset_suffix();
103 $version = defined( 'DESKTOP_MODE_VERSION' ) ? DESKTOP_MODE_VERSION : '0';
104
105 $js_path = DESKTOP_MODE_DIR . 'assets/js/widget-site-views' . $suffix . '.js';
106 $css_path = DESKTOP_MODE_DIR . 'assets/js/widget-site-views' . $suffix . '.css';
107
108 wp_register_style(
109 'desktop-mode-site-views-widget',
110 DESKTOP_MODE_URL . 'assets/js/widget-site-views' . $suffix . '.css',
111 array(),
112 file_exists( $css_path ) ? (string) filemtime( $css_path ) : $version
113 );
114
115 wp_register_script(
116 'desktop-mode-site-views-widget',
117 DESKTOP_MODE_URL . 'assets/js/widget-site-views' . $suffix . '.js',
118 array( 'wp-api-fetch' ),
119 file_exists( $js_path ) ? (string) filemtime( $js_path ) : $version,
120 true
121 );
122 }
123 add_action( 'init', 'desktop_mode_register_site_views_widget_assets', 5 );
124
125 /**
126 * Eagerly enqueue the CSS on shell pages.
127 *
128 * @since 0.26.0
129 */
130 function desktop_mode_enqueue_site_views_widget_styles() {
131 if ( function_exists( 'desktop_mode_is_enabled' ) && ! desktop_mode_is_enabled() ) {
132 return;
133 }
134 if ( function_exists( 'desktop_mode_is_chromeless_request' ) && desktop_mode_is_chromeless_request() ) {
135 return;
136 }
137 wp_enqueue_style( 'desktop-mode-site-views-widget' );
138 }
139 add_action( 'admin_enqueue_scripts', 'desktop_mode_enqueue_site_views_widget_styles', 20 );
140
141 /**
142 * Register the widget definition.
143 *
144 * @since 0.26.0
145 */
146 function desktop_mode_register_site_views_widget() {
147 if ( ! function_exists( 'desktop_mode_register_widget' ) ) {
148 return;
149 }
150 desktop_mode_register_widget(
151 'desktop-mode/site-views',
152 array(
153 'label' => __( 'Site Views', 'desktop-mode' ),
154 'description' => __( 'Sparkline of page views over the last 7 days with week-over-week delta.', 'desktop-mode' ),
155 'icon' => 'dashicons-chart-area',
156 'script' => 'desktop-mode-site-views-widget',
157 'movable' => true,
158 'resizable' => true,
159 'min_width' => 240,
160 'min_height' => 160,
161 'default_width' => 300,
162 'default_height' => 200,
163 )
164 );
165 }
166 add_action( 'init', 'desktop_mode_register_site_views_widget', 6 );
167