PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.0.1
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.0.1
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 / notes / heartbeat.php

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

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