| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | - * Desktop Mode — My WordPress: post-lock REST field. | |
| 3 | + * OpenStation — My WordPress: post-lock REST field. | |
| 4 | 4 | * |
| 5 | 5 | * Surfaces "is this post currently being edited by someone else?" |
| 6 | 6 | * on every post / page / opt-in CPT REST response so the My WordPress |
| 7 | 7 | * file-explorer can show a lock icon + the locking user's name on |
| @@ -14,16 +14,15 @@ | ||
| 14 | 14 | * We expose the same intelligence as a structured field, gated on |
| 15 | 15 | * `edit_post` so users who can't edit the post never see who else is |
| 16 | 16 | * editing it. |
| 17 | 17 | * |
| 18 | - * The field name is `desktop_mode_lock`; shape: | |
| 18 | + * The field name is `openstation_lock`; shape: | |
| 19 | 19 | * |
| 20 | 20 | * - `null` — not locked, OR the requester lacks edit caps. |
| 21 | 21 | * - `{ userId, userName, userAvatarUrl, time }` — locked by another |
| 22 | 22 | * user. `time` is the ISO-8601 timestamp of the lock heartbeat. |
| 23 | 23 | * |
| 24 | - * @package WPDesktopMode | |
| 25 | - * @since 0.8.0 | |
| 24 | + * @package OpenStation | |
| 26 | 25 | */ |
| 27 | 26 | |
| 28 | 27 | defined( 'ABSPATH' ) || exit; |
| 29 | 28 | |
| @@ -34,14 +33,12 @@ | ||
| 34 | 33 | * - The post isn't locked. |
| 35 | 34 | * - The current user is the lock holder (no point flagging yourself). |
| 36 | 35 | * - The current user can't edit the post (don't leak who's editing). |
| 37 | 36 | * |
| 38 | - * @since 0.8.0 | |
| 39 | - * | |
| 40 | 37 | * @param int $post_id Post id. |
| 41 | 38 | * @return array{userId:int,userName:string,userAvatarUrl:string,time:string}|null |
| 42 | 39 | */ |
| 43 | -function desktop_mode_my_wordpress_post_lock_payload( $post_id ) { | |
| 40 | +function openstation_my_wordpress_post_lock_payload( $post_id ) { | |
| 44 | 41 | $post_id = (int) $post_id; |
| 45 | 42 | if ( $post_id <= 0 ) { |
| 46 | 43 | return null; |
| 47 | 44 | } |
| @@ -88,28 +85,40 @@ | ||
| 88 | 85 | * |
| 89 | 86 | * Sources, merged in order: |
| 90 | 87 | * 1. Co-Authors Plus, when installed — `get_coauthors()` returns |
| 91 | 88 | * user objects (or guest authors with a different shape). |
| 92 | - * 2. Anything plugins return from the | |
| 93 | - * `desktop_mode_my_wordpress_post_contributors` filter, which | |
| 89 | + * 2. Revision authors — everyone who has saved the post leaves a | |
| 90 | + * revision row stamped with their user id. | |
| 91 | + * 3. The `_edit_last` post meta — who saved the post most | |
| 92 | + * recently; the only signal on installs with revisions | |
| 93 | + * disabled. | |
| 94 | + * 4. Anything plugins return from the | |
| 95 | + * `openstation_my_wordpress_post_contributors` filter, which | |
| 94 | 96 | * receives the post id + the running user-id list. Filter |
| 95 | 97 | * contract is plain int[] for ergonomics; we expand each id |
| 96 | 98 | * into the structured shape afterwards. |
| 97 | 99 | * |
| 100 | + * Gated on `edit_post`, same as the lock payload above — returns an | |
| 101 | + * empty array for users who can't edit the post, so revision-author | |
| 102 | + * identities never leak to read-only viewers. | |
| 103 | + * | |
| 98 | 104 | * The post's `post_author` is intentionally NOT included here — |
| 99 | 105 | * it's already surfaced by the canonical "Author" sub-folder. |
| 100 | 106 | * Contributors is the *additional* people surface. |
| 101 | 107 | * |
| 102 | - * @since 0.8.0 | |
| 103 | - * | |
| 104 | 108 | * @param int $post_id Post id. |
| 105 | 109 | * @return array<int,array{userId:int,userName:string,userAvatarUrl:string}> |
| 106 | 110 | */ |
| 107 | -function desktop_mode_my_wordpress_post_contributors_payload( $post_id ) { | |
| 111 | +function openstation_my_wordpress_post_contributors_payload( $post_id ) { | |
| 108 | 112 | $post_id = (int) $post_id; |
| 109 | 113 | if ( $post_id <= 0 ) { |
| 110 | 114 | return array(); |
| 111 | 115 | } |
| 116 | + | |
| 117 | + if ( ! current_user_can( 'edit_post', $post_id ) ) { | |
| 118 | + return array(); | |
| 119 | + } | |
| 120 | + | |
| 112 | 121 | $post = get_post( $post_id ); |
| 113 | 122 | if ( ! $post ) { |
| 114 | 123 | return array(); |
| 115 | 124 | } |
| @@ -178,9 +187,9 @@ | ||
| 178 | 187 | * Examples: |
| 179 | 188 | * |
| 180 | 189 | * ```php |
| 181 | 190 | * // ACF user-list field "post_contributors": |
| 182 | - * add_filter( 'desktop_mode_my_wordpress_post_contributors', | |
| 191 | + * add_filter( 'openstation_my_wordpress_post_contributors', | |
| 183 | 192 | * function ( $ids, $post_id ) { |
| 184 | 193 | * $extra = (array) get_field( 'post_contributors', $post_id ); |
| 185 | 194 | * foreach ( $extra as $u ) { |
| 186 | 195 | * if ( $u instanceof WP_User ) { |
| @@ -192,15 +201,13 @@ | ||
| 192 | 201 | * return $ids; |
| 193 | 202 | * }, 10, 2 ); |
| 194 | 203 | * ``` |
| 195 | 204 | * |
| 196 | - * @since 0.8.0 | |
| 197 | - * | |
| 198 | 205 | * @param int[] $ids Contributor user ids gathered so far |
| 199 | 206 | * (from Co-Authors Plus, etc.). |
| 200 | 207 | * @param int $post_id Post id. |
| 201 | 208 | */ |
| 202 | - $ids = (array) apply_filters( 'desktop_mode_my_wordpress_post_contributors', $ids, $post_id ); | |
| 209 | + $ids = (array) apply_filters( 'openstation_my_wordpress_post_contributors', $ids, $post_id ); | |
| 203 | 210 | |
| 204 | 211 | // De-duplicate, drop the primary author so the Contributors |
| 205 | 212 | // sub-folder only carries *additional* people, drop empty/0, |
| 206 | 213 | // and resolve to user records. |
| @@ -232,36 +239,29 @@ | ||
| 232 | 239 | return $out; |
| 233 | 240 | } |
| 234 | 241 | |
| 235 | 242 | /** |
| 236 | - * Register the REST fields on every public post type that runs | |
| 237 | - * through the standard `/wp/v2/<type>` endpoint. Posts and pages | |
| 238 | - * cover the Phase 1 surface; CPTs come along for free. | |
| 243 | + * Register the REST fields on every post type the site window can | |
| 244 | + * browse — public REST-exposed types plus the ones bridged under | |
| 245 | + * `desktop-mode/v1`. Posts and pages cover the Phase 1 surface; CPTs | |
| 246 | + * come along for free. | |
| 239 | 247 | * |
| 240 | 248 | * Two fields: |
| 241 | - * - `desktop_mode_lock` — active edit-lock holder. | |
| 242 | - * - `desktop_mode_contributors` — additional contributor users | |
| 249 | + * - `openstation_lock` — active edit-lock holder. | |
| 250 | + * - `openstation_contributors` — additional contributor users | |
| 243 | 251 | * beyond the primary author. |
| 244 | - * | |
| 245 | - * @since 0.8.0 | |
| 246 | 252 | */ |
| 247 | -function desktop_mode_my_wordpress_register_lock_field() { | |
| 248 | - $types = get_post_types( | |
| 249 | - array( | |
| 250 | - 'show_in_rest' => true, | |
| 251 | - 'public' => true, | |
| 252 | - ), | |
| 253 | - 'names' | |
| 254 | - ); | |
| 253 | +function openstation_my_wordpress_register_lock_field() { | |
| 254 | + $types = openstation_my_wordpress_rest_field_post_types(); | |
| 255 | 255 | |
| 256 | 256 | foreach ( $types as $type ) { |
| 257 | 257 | register_rest_field( |
| 258 | 258 | $type, |
| 259 | - 'desktop_mode_lock', | |
| 259 | + 'openstation_lock', | |
| 260 | 260 | array( |
| 261 | 261 | 'get_callback' => static function ( $post ) { |
| 262 | 262 | $post_id = isset( $post['id'] ) ? (int) $post['id'] : 0; |
| 263 | - return desktop_mode_my_wordpress_post_lock_payload( $post_id ); | |
| 263 | + return openstation_my_wordpress_post_lock_payload( $post_id ); | |
| 264 | 264 | }, |
| 265 | 265 | 'schema' => array( |
| 266 | 266 | 'description' => __( 'Active edit-lock holder, or null when the post is not locked.', 'desktop-mode' ), |
| 267 | 267 | 'type' => array( 'object', 'null' ), |
| @@ -278,16 +278,16 @@ | ||
| 278 | 278 | ); |
| 279 | 279 | |
| 280 | 280 | register_rest_field( |
| 281 | 281 | $type, |
| 282 | - 'desktop_mode_contributors', | |
| 282 | + 'openstation_contributors', | |
| 283 | 283 | array( |
| 284 | 284 | 'get_callback' => static function ( $post ) { |
| 285 | 285 | $post_id = isset( $post['id'] ) ? (int) $post['id'] : 0; |
| 286 | - return desktop_mode_my_wordpress_post_contributors_payload( $post_id ); | |
| 286 | + return openstation_my_wordpress_post_contributors_payload( $post_id ); | |
| 287 | 287 | }, |
| 288 | 288 | 'schema' => array( |
| 289 | - 'description' => __( 'Additional contributor users beyond the primary author. Sourced from Co-Authors Plus when present, plus anything plugins return via `desktop_mode_my_wordpress_post_contributors`.', 'desktop-mode' ), | |
| 289 | + 'description' => __( 'Additional contributor users beyond the primary author. Sourced from Co-Authors Plus when present, revision authors, the `_edit_last` meta, plus anything plugins return via `openstation_my_wordpress_post_contributors`. Empty for requesters who cannot edit the post.', 'desktop-mode' ), | |
| 290 | 290 | 'type' => 'array', |
| 291 | 291 | 'context' => array( 'view', 'edit' ), |
| 292 | 292 | 'readonly' => true, |
| 293 | 293 | 'items' => array( |
| @@ -302,5 +302,5 @@ | ||
| 302 | 302 | ) |
| 303 | 303 | ); |
| 304 | 304 | } |
| 305 | 305 | } |
| 306 | -add_action( 'rest_api_init', 'desktop_mode_my_wordpress_register_lock_field' ); | |
| 306 | +add_action( 'rest_api_init', 'openstation_my_wordpress_register_lock_field' ); | |