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 / living-tree / snapshot.php

snapshot.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.9.7, at includes/living-tree/snapshot.php

156 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Desktop Mode — Living Tree: REST snapshot endpoint.
4 *
5 * One route: `GET desktop-mode/v1/living-tree/snapshot`. Returns the
6 * compact site DNA (`TreeSnapshot` in the JS types) — aggregate counts
7 * and branch hints — never the full post list. The client turns this
8 * into hormones and never sees rows.
9 *
10 * `siteUrl` + `siteName` + `installEpoch` together form the determinism
11 * seed. The site NAME is deliberately part of it: two different blogs can
12 * share a URL shape (two installs on localhost, staging clones), and
13 * their trees must still be individuals.
14 *
15 * The response is cached in a transient (TTL 6h) and invalidated whenever
16 * content changes (`save_post` / `deleted_post` / `comment_post`).
17 *
18 * @package WPDesktopMode
19 * @since 0.9.4
20 */
21
22 defined( 'ABSPATH' ) || exit;
23
24 /** Transient key the built snapshot is cached under. */
25 const DESKTOP_MODE_LIVING_TREE_CACHE_KEY = 'desktop_mode_living_tree_snapshot';
26
27 /** Cache lifetime for the snapshot. */
28 const DESKTOP_MODE_LIVING_TREE_CACHE_TTL = 6 * HOUR_IN_SECONDS;
29
30 /**
31 * Whether the current user may read the Living Tree snapshot.
32 *
33 * Defaults to `read` — anyone who can see the admin can see the wallpaper
34 * of their own site. Filterable so a site can widen or restrict it.
35 *
36 * @since 0.9.4
37 *
38 * @return bool
39 */
40 function desktop_mode_living_tree_user_can_use() {
41 $can = current_user_can( 'read' );
42
43 /**
44 * Filter whether the current user can read the Living Tree snapshot.
45 *
46 * @since 0.9.4
47 *
48 * @param bool $can Default: the `read` capability.
49 */
50 return (bool) apply_filters( 'desktop_mode_living_tree_user_can_use', $can );
51 }
52
53 /**
54 * Register the snapshot route.
55 *
56 * @since 0.9.4
57 */
58 function desktop_mode_living_tree_register_routes() {
59 register_rest_route(
60 'desktop-mode/v1',
61 '/living-tree/snapshot',
62 array(
63 'methods' => WP_REST_Server::READABLE,
64 'callback' => 'desktop_mode_living_tree_rest_snapshot',
65 'permission_callback' => 'desktop_mode_living_tree_user_can_use',
66 )
67 );
68 }
69 add_action( 'rest_api_init', 'desktop_mode_living_tree_register_routes' );
70
71 /**
72 * GET /living-tree/snapshot — cached snapshot response.
73 *
74 * @since 0.9.4
75 *
76 * @return WP_REST_Response
77 */
78 function desktop_mode_living_tree_rest_snapshot() {
79 $cached = get_transient( DESKTOP_MODE_LIVING_TREE_CACHE_KEY );
80 if ( is_array( $cached ) ) {
81 return rest_ensure_response( $cached );
82 }
83
84 $snapshot = desktop_mode_living_tree_build_snapshot();
85 set_transient(
86 DESKTOP_MODE_LIVING_TREE_CACHE_KEY,
87 $snapshot,
88 DESKTOP_MODE_LIVING_TREE_CACHE_TTL
89 );
90
91 return rest_ensure_response( $snapshot );
92 }
93
94 /**
95 * Invalidate the cached snapshot. Wired to the content-mutation hooks so
96 * the tree re-DNAs on the next load after the site changes.
97 *
98 * @since 0.9.4
99 */
100 function desktop_mode_living_tree_flush_cache() {
101 delete_transient( DESKTOP_MODE_LIVING_TREE_CACHE_KEY );
102 }
103 add_action( 'save_post', 'desktop_mode_living_tree_flush_cache' );
104 add_action( 'deleted_post', 'desktop_mode_living_tree_flush_cache' );
105 add_action( 'comment_post', 'desktop_mode_living_tree_flush_cache' );
106
107 /**
108 * Build the compact site DNA snapshot.
109 *
110 * Aggregates only. Every metric is capped / normalised so any topology
111 * yields a well-formed snapshot — the golden rule (WordPress emits
112 * hormones, never geometry) lives here: this function must never leak a
113 * per-post coordinate or identity into the payload.
114 *
115 * @since 0.9.4
116 *
117 * @return array The snapshot, matching the JS `TreeSnapshot` shape.
118 */
119 function desktop_mode_living_tree_build_snapshot() {
120 $posts = wp_count_posts( 'post' );
121 $pages = wp_count_posts( 'page' );
122 $comments = wp_count_comments();
123
124 $categories = wp_count_terms( array( 'taxonomy' => 'category' ) );
125 $tags = wp_count_terms( array( 'taxonomy' => 'post_tag' ) );
126
127 $snapshot = array(
128 'siteUrl' => (string) home_url(),
129 'siteName' => (string) get_bloginfo( 'name' ),
130 'installEpoch' => desktop_mode_living_tree_install_epoch(),
131 'siteAgeDays' => desktop_mode_living_tree_site_age_days(),
132 'totalPosts' => isset( $posts->publish ) ? (int) $posts->publish : 0,
133 'totalPages' => isset( $pages->publish ) ? (int) $pages->publish : 0,
134 'totalCategories' => is_wp_error( $categories ) ? 0 : (int) $categories,
135 'totalTags' => is_wp_error( $tags ) ? 0 : (int) $tags,
136 'totalComments' => isset( $comments->approved ) ? (int) $comments->approved : 0,
137 'activeUsers' => desktop_mode_living_tree_active_users(),
138 'traffic' => desktop_mode_living_tree_traffic(),
139 'seoHealth' => desktop_mode_living_tree_seo_health(),
140 'performance' => desktop_mode_living_tree_performance(),
141 'branches' => desktop_mode_living_tree_branch_dna(),
142 );
143
144 /**
145 * Filter the Living Tree snapshot before it is cached and served.
146 * Keep the shape intact — the JS client validates nothing; it trusts
147 * this contract. Aggregates only: never add per-post identities or
148 * coordinates (the golden rule).
149 *
150 * @since 0.9.4
151 *
152 * @param array $snapshot The compact site DNA.
153 */
154 return apply_filters( 'desktop_mode_living_tree_snapshot', $snapshot );
155 }
156