PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.8.7
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.8.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 / my-wordpress / user-list-fields.php

user-list-fields.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.8.7, at includes/my-wordpress/user-list-fields.php

151 lines 4.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Desktop Mode — My WordPress: per-user REST fields for the
4 * Users-folder list view.
5 *
6 * Surfaces a small "summary" payload on every `/wp/v2/users` row so
7 * the My WordPress folder window can paint a rich tile (avatar +
8 * name + role chip + post count + member-since) without firing
9 * N+1 dossier requests as the user scrolls.
10 *
11 * Fields:
12 *
13 * - `desktop_mode_summary.postCount` int count of non-trash posts authored
14 * - `desktop_mode_summary.roleLabels` array translated role labels (gated on `list_users` OR self)
15 * - `desktop_mode_summary.registered` string ISO-8601 registered date (gated on `list_users` OR self)
16 * - `desktop_mode_summary.lastActive` string ISO-8601 of latest published post, or '' when unknown
17 *
18 * Each field is independently capability-gated so a viewer without
19 * `list_users` still sees `postCount` (public counts) and a public
20 * `lastActive` derived from publish dates, but doesn't see
21 * `roleLabels` or `registered` (private).
22 *
23 * @package WPDesktopMode
24 * @since 0.20.0
25 */
26
27 defined( 'ABSPATH' ) || exit;
28
29 /**
30 * Compute the summary payload for one user. Cheap enough to call
31 * per-row (each branch is one indexed query); WP's object cache
32 * absorbs repeats inside a single request.
33 *
34 * @since 0.20.0
35 *
36 * @param int $user_id User id.
37 * @return array{postCount:int,roleLabels:array<int,string>,registered:string,lastActive:string}
38 */
39 function desktop_mode_my_wordpress_user_summary_payload( $user_id ) {
40 $user_id = (int) $user_id;
41 if ( $user_id <= 0 ) {
42 return array(
43 'postCount' => 0,
44 'roleLabels' => array(),
45 'registered' => '',
46 'lastActive' => '',
47 );
48 }
49
50 $user = get_userdata( $user_id );
51 if ( ! $user ) {
52 return array(
53 'postCount' => 0,
54 'roleLabels' => array(),
55 'registered' => '',
56 'lastActive' => '',
57 );
58 }
59
60 $can_see_private = current_user_can( 'list_users' )
61 || ( get_current_user_id() === $user_id );
62
63 // `count_user_posts` accepts an array of post types since 4.5; we
64 // limit to public ones the dossier already counts so the tile and
65 // the dossier agree.
66 $post_count = (int) count_user_posts( $user_id, array( 'post', 'page' ), true );
67
68 $role_labels = array();
69 if ( $can_see_private && function_exists( 'wp_roles' ) ) {
70 $wp_roles = wp_roles();
71 foreach ( (array) $user->roles as $slug ) {
72 $role_labels[] = isset( $wp_roles->role_names[ $slug ] )
73 ? translate_user_role( $wp_roles->role_names[ $slug ] )
74 : $slug;
75 }
76 }
77
78 $registered = '';
79 if ( $can_see_private && '' !== $user->user_registered ) {
80 $registered = mysql2date( 'c', $user->user_registered, false );
81 }
82
83 // Latest published post — useful at-a-glance "active recently?"
84 // signal for the tile. Drawn from `post_date_gmt` so timezone
85 // drift can't shift the displayed date.
86 global $wpdb;
87 $last_active_raw = $wpdb->get_var(
88 $wpdb->prepare(
89 "SELECT MAX(post_date_gmt) FROM {$wpdb->posts}
90 WHERE post_author = %d
91 AND post_status = 'publish'
92 AND post_type IN ( 'post', 'page' )",
93 $user_id
94 )
95 );
96 $last_active = $last_active_raw ? mysql2date( 'c', $last_active_raw, false ) : '';
97
98 return array(
99 'postCount' => $post_count,
100 'roleLabels' => $role_labels,
101 'registered' => (string) $registered,
102 'lastActive' => (string) $last_active,
103 );
104 }
105
106 /**
107 * Register the field on the `user` REST resource. The field is
108 * read-only (no `update_callback`); `get_callback` receives the
109 * user response array, from which we read `id`.
110 *
111 * @since 0.20.0
112 */
113 function desktop_mode_my_wordpress_register_user_summary_field() {
114 register_rest_field(
115 'user',
116 'desktop_mode_summary',
117 array(
118 'get_callback' => static function ( $user ) {
119 $id = isset( $user['id'] ) ? (int) $user['id'] : 0;
120 return desktop_mode_my_wordpress_user_summary_payload( $id );
121 },
122 'schema' => array(
123 'description' => __( 'Compact user summary for My WordPress.', 'desktop-mode' ),
124 'type' => 'object',
125 'context' => array( 'view', 'edit', 'embed' ),
126 'readonly' => true,
127 'properties' => array(
128 'postCount' => array(
129 'type' => 'integer',
130 'description' => __( 'Count of posts and pages authored by this user.', 'desktop-mode' ),
131 ),
132 'roleLabels' => array(
133 'type' => 'array',
134 'description' => __( 'Translated role labels visible to viewers with list_users.', 'desktop-mode' ),
135 'items' => array( 'type' => 'string' ),
136 ),
137 'registered' => array(
138 'type' => 'string',
139 'description' => __( 'ISO-8601 registration date (gated on list_users).', 'desktop-mode' ),
140 ),
141 'lastActive' => array(
142 'type' => 'string',
143 'description' => __( 'ISO-8601 of latest publish; empty when the user has none.', 'desktop-mode' ),
144 ),
145 ),
146 ),
147 )
148 );
149 }
150 add_action( 'rest_api_init', 'desktop_mode_my_wordpress_register_user_summary_field' );
151