PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / trunk
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin vtrunk
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 0.8.6 All 33 releases
desktop-mode / includes / notes / heartbeat.php

heartbeat.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin trunk, at includes/notes/heartbeat.php

173 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OpenStation — Pinned notes Heartbeat sync.
4 *
5 * Delta model: the client subscribes with the note ids it already
6 * renders plus a high-water modified timestamp; the server responds
7 * with notes changed since then and with removals (trashed, deleted,
8 * or made private by their owner).
9 *
10 * Visibility mirrors the REST list: the viewer's own notes (private +
11 * publish) plus every other user's public notes.
12 *
13 * @package OpenStation
14 */
15
16 defined( 'ABSPATH' ) || exit;
17
18 /**
19 * Add pinned-note deltas to the Heartbeat response.
20 *
21 * @param array $response Pre-filtered response.
22 * @param array $data Client-sent payload.
23 * @return array
24 */
25 function openstation_notes_heartbeat_received( $response, $data ) {
26 if ( ! is_array( $response ) ) {
27 $response = array();
28 }
29 if ( empty( $data['openstation_notes_subscribe'] ) || ! is_array( $data['openstation_notes_subscribe'] ) ) {
30 return $response;
31 }
32 if ( ! function_exists( 'openstation_is_enabled' ) || ! openstation_is_enabled() ) {
33 return $response;
34 }
35
36 $sub = $data['openstation_notes_subscribe'];
37 $known_ids = isset( $sub['knownIds'] ) && is_array( $sub['knownIds'] )
38 ? array_values( array_unique( array_filter( array_map( 'absint', $sub['knownIds'] ) ) ) )
39 : array();
40 $known_ids = array_slice( $known_ids, 0, 500 );
41 $since_ms = isset( $sub['sinceMs'] ) ? max( 0, (int) $sub['sinceMs'] ) : 0;
42
43 $response['openstation_notes'] = openstation_notes_compute_heartbeat_delta( $known_ids, $since_ms, 100 );
44
45 return $response;
46 }
47 add_filter( 'heartbeat_received', 'openstation_notes_heartbeat_received', 5, 2 );
48
49 /**
50 * Compute pinned-note Heartbeat deltas for the current user.
51 *
52 * @param int[] $known_ids Note ids currently rendered by the client.
53 * @param int $since_ms Last-seen modified timestamp in milliseconds.
54 * @param int $cap Maximum notes to send in one tick.
55 * @return array
56 */
57 function openstation_notes_compute_heartbeat_delta( $known_ids, $since_ms, $cap ) {
58 $cap = max( 1, (int) $cap );
59 $query_ids = openstation_notes_query_changed_ids( $since_ms, $cap + 1 );
60 $truncated = count( $query_ids ) > $cap;
61 if ( $truncated ) {
62 $query_ids = array_slice( $query_ids, 0, $cap );
63 }
64
65 $notes = array();
66 foreach ( $query_ids as $post_id ) {
67 $post = get_post( $post_id );
68 if ( $post instanceof WP_Post ) {
69 $notes[] = openstation_notes_prepare( $post );
70 }
71 }
72
73 $alive_ids = openstation_notes_alive_known_ids( $known_ids );
74 $removed = array_values( array_diff( array_map( 'intval', $known_ids ), $alive_ids ) );
75
76 return array(
77 'notes' => $notes,
78 'removed' => $removed,
79 'serverTimeMs' => (int) floor( microtime( true ) * 1000 ),
80 'truncated' => $truncated,
81 );
82 }
83
84 /**
85 * The `WP_Query` visibility clause shared by the delta queries: the
86 * viewer's own notes in any live status, or anyone's public notes.
87 *
88 * Expressed as two queries merged in PHP (like the REST list) rather
89 * than a hand-built OR — keeps every callsite on standard WP_Query.
90 *
91 * @param array $extra Extra WP_Query args merged into both halves.
92 * @return int[] Matching post ids, own notes first.
93 */
94 function openstation_notes_query_visible_ids( $extra ) {
95 $user_id = get_current_user_id();
96 $base = array(
97 'post_type' => OPENSTATION_NOTES_POST_TYPE,
98 'fields' => 'ids',
99 'no_found_rows' => true,
100 );
101
102 $own = new WP_Query(
103 array_merge(
104 $base,
105 $extra,
106 array(
107 'post_status' => array( 'private', 'publish' ),
108 'author' => $user_id,
109 )
110 )
111 );
112
113 $public = new WP_Query(
114 array_merge(
115 $base,
116 $extra,
117 array(
118 'post_status' => 'publish',
119 'author__not_in' => array( $user_id ),
120 )
121 )
122 );
123
124 $ids = array_map( 'intval', array_merge( (array) $own->posts, (array) $public->posts ) );
125 wp_reset_postdata();
126
127 return array_values( array_unique( $ids ) );
128 }
129
130 /**
131 * Query visible note ids modified since the client's high-water mark.
132 *
133 * @param int $since_ms Last-seen modified timestamp in milliseconds.
134 * @param int $limit Max ids to return (per visibility half).
135 * @return int[]
136 */
137 function openstation_notes_query_changed_ids( $since_ms, $limit ) {
138 $extra = array(
139 'posts_per_page' => max( 1, (int) $limit ),
140 'orderby' => 'modified',
141 'order' => 'ASC',
142 );
143 if ( $since_ms > 0 ) {
144 $extra['date_query'] = array(
145 array(
146 'column' => 'post_modified_gmt',
147 'after' => gmdate( 'Y-m-d H:i:s', (int) floor( $since_ms / 1000 ) ),
148 'inclusive' => true,
149 ),
150 );
151 }
152 return openstation_notes_query_visible_ids( $extra );
153 }
154
155 /**
156 * Return the subset of known ids still visible to the viewer.
157 *
158 * @param int[] $known_ids Client-known note ids.
159 * @return int[]
160 */
161 function openstation_notes_alive_known_ids( $known_ids ) {
162 $known_ids = array_values( array_unique( array_filter( array_map( 'absint', (array) $known_ids ) ) ) );
163 if ( empty( $known_ids ) ) {
164 return array();
165 }
166 return openstation_notes_query_visible_ids(
167 array(
168 'post__in' => $known_ids,
169 'posts_per_page' => count( $known_ids ),
170 )
171 );
172 }
173