PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.11
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.11
1.1.11 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 All 35 releases
← All changes | includes/desktop-themes/rest.php +73 -36 0.9.8 → 1.1.11 View file →
@@ -1,34 +1,41 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — Desktop-theme REST routes.
3 + * OpenStation — Desktop-theme REST routes.
4 4 *
5 + * GET /desktop-mode/v1/desktop-themes full entries
5 6 * POST /desktop-mode/v1/desktop-themes multipart `file`
6 7 * DELETE /desktop-mode/v1/desktop-themes/<slug>
7 8 *
8 - * There is deliberately no GET: the library rides the shell payload
9 - * (`serverDesktopThemes`), so a separate read route would be a
10 - * second source of truth to keep in sync for no gain.
9 + * The GET exists for the boot-payload diet, and it is NOT a second
10 + * source of truth: it returns exactly
11 + * `openstation_build_desktop_themes_payload()` — the same builder,
12 + * the same `openstation_desktop_themes` filter — with the FULL
13 + * entries. The boot payload ships the library slimmed (no `cssText`,
14 + * no `tokens`; `cssDeferred: true` marks the gap) because the active
15 + * theme's stylesheet is server-delivered at boot and an inactive
16 + * theme's ~20 KB of compiled CSS is only needed at the moment the
17 + * user picks it — which is when the shell calls this route.
11 18 *
12 - * @package WPDesktopMode
19 + * @package OpenStation
13 20 */
14 21
15 22 defined( 'ABSPATH' ) || exit;
16 23
17 24 /**
18 - * Permission gate: the standard desktop-mode REST gate plus the
25 + * Permission gate: the standard openstation REST gate plus the
19 26 * theme-management capability.
20 27 *
21 28 * @return true|WP_Error
22 29 */
23 -function desktop_mode_desktop_themes_rest_permission() {
24 - $base = desktop_mode_rest_require_enabled();
30 +function openstation_desktop_themes_rest_permission() {
31 + $base = openstation_rest_require_enabled();
25 32 if ( is_wp_error( $base ) ) {
26 33 return $base;
27 34 }
28 - if ( ! current_user_can( desktop_mode_desktop_theme_upload_capability() ) ) {
35 + if ( ! current_user_can( openstation_desktop_theme_upload_capability() ) ) {
29 36 return new WP_Error(
30 - 'desktop_mode_desktop_theme_cannot_manage',
37 + 'openstation_desktop_theme_cannot_manage',
31 38 __( 'You are not allowed to manage desktop themes.', 'desktop-mode' ),
32 39 array( 'status' => 403 )
33 40 );
34 41 }
@@ -37,17 +44,28 @@
37 44
38 45 /**
39 46 * Register the routes.
40 47 */
41 -function desktop_mode_register_desktop_themes_rest_routes() {
48 +function openstation_register_desktop_themes_rest_routes() {
42 49 register_rest_route(
43 50 'desktop-mode/v1',
44 51 '/desktop-themes',
45 52 array(
46 - // POST only — PHP populates `$_FILES` for real POSTs only.
47 - 'methods' => WP_REST_Server::CREATABLE,
48 - 'permission_callback' => 'desktop_mode_desktop_themes_rest_permission',
49 - 'callback' => 'desktop_mode_rest_upload_desktop_theme',
53 + array(
54 + // Read gate is the shell's own, NOT the manage
55 + // capability: the same full entries used to ride the
56 + // boot payload to every desktop user, so the route
57 + // exposes nothing the payload didn't.
58 + 'methods' => WP_REST_Server::READABLE,
59 + 'permission_callback' => 'openstation_rest_require_enabled',
60 + 'callback' => 'openstation_rest_list_desktop_themes',
61 + ),
62 + array(
63 + // POST only — PHP populates `$_FILES` for real POSTs only.
64 + 'methods' => WP_REST_Server::CREATABLE,
65 + 'permission_callback' => 'openstation_desktop_themes_rest_permission',
66 + 'callback' => 'openstation_rest_upload_desktop_theme',
67 + ),
50 68 )
51 69 );
52 70
53 71 register_rest_route(
@@ -54,10 +72,10 @@
54 72 'desktop-mode/v1',
55 73 '/desktop-themes/(?P<slug>[a-z0-9_-]+)',
56 74 array(
57 75 'methods' => WP_REST_Server::DELETABLE,
58 - 'permission_callback' => 'desktop_mode_desktop_themes_rest_permission',
59 - 'callback' => 'desktop_mode_rest_delete_desktop_theme',
76 + 'permission_callback' => 'openstation_desktop_themes_rest_permission',
77 + 'callback' => 'openstation_rest_delete_desktop_theme',
60 78 'args' => array(
61 79 'slug' => array(
62 80 'type' => 'string',
63 81 'required' => true,
@@ -65,17 +83,36 @@
65 83 ),
66 84 )
67 85 );
68 86 }
69 -add_action( 'rest_api_init', 'desktop_mode_register_desktop_themes_rest_routes' );
87 +add_action( 'rest_api_init', 'openstation_register_desktop_themes_rest_routes' );
70 88
71 89 /**
90 + * GET /desktop-themes — the full theme library.
91 + *
92 + * The on-demand counterpart of the slimmed boot payload: same
93 + * builder, same filter, full `cssText` / `tokens`. The shell calls
94 + * it from `ensureFullDesktopThemes()` the first time a deferred
95 + * entry's stylesheet is actually needed (the user picks a theme in
96 + * Preferences → Themes).
97 + *
98 + * @return WP_REST_Response
99 + */
100 +function openstation_rest_list_desktop_themes() {
101 + return rest_ensure_response(
102 + array(
103 + 'themes' => openstation_build_desktop_themes_payload(),
104 + )
105 + );
106 +}
107 +
108 +/**
72 109 * POST /desktop-mode/v1/desktop-themes
73 110 *
74 111 * @param WP_REST_Request $request Request.
75 112 * @return WP_REST_Response|WP_Error The payload-shaped entry.
76 113 */
77 -function desktop_mode_rest_upload_desktop_theme( WP_REST_Request $request ) {
114 +function openstation_rest_upload_desktop_theme( WP_REST_Request $request ) {
78 115 $files = $request->get_file_params();
79 116
80 117 // A body over `post_max_size` reaches PHP with $_POST and $_FILES
81 118 // both empty while CONTENT_LENGTH says bytes were sent. Answer a
@@ -84,15 +121,15 @@
84 121 if ( empty( $files ) ) {
85 122 $content_length = isset( $_SERVER['CONTENT_LENGTH'] ) ? (int) $_SERVER['CONTENT_LENGTH'] : 0;
86 123 if ( $content_length > 0 ) {
87 124 return new WP_Error(
88 - 'desktop_mode_desktop_theme_too_large',
125 + 'openstation_desktop_theme_too_large',
89 126 __( 'That theme archive is larger than this server accepts.', 'desktop-mode' ),
90 127 array( 'status' => 413 )
91 128 );
92 129 }
93 130 return new WP_Error(
94 - 'desktop_mode_desktop_theme_no_file',
131 + 'openstation_desktop_theme_no_file',
95 132 __( 'No theme archive was uploaded.', 'desktop-mode' ),
96 133 array( 'status' => 400 )
97 134 );
98 135 }
@@ -97,9 +134,9 @@
97 134 );
98 135 }
99 136 if ( empty( $files['file'] ) || ! is_array( $files['file'] ) ) {
100 137 return new WP_Error(
101 - 'desktop_mode_desktop_theme_no_file',
138 + 'openstation_desktop_theme_no_file',
102 139 __( 'No theme archive was uploaded.', 'desktop-mode' ),
103 140 array( 'status' => 400 )
104 141 );
105 142 }
@@ -113,9 +150,9 @@
113 150 $segments = explode( '.', strtolower( $name ) );
114 151 $last = array_pop( $segments );
115 152 if ( 'zip' !== $last ) {
116 153 return new WP_Error(
117 - 'desktop_mode_desktop_theme_not_zip',
154 + 'openstation_desktop_theme_not_zip',
118 155 __( 'A desktop theme must be uploaded as a .zip archive.', 'desktop-mode' ),
119 156 array( 'status' => 400 )
120 157 );
121 158 }
@@ -123,9 +160,9 @@
123 160 array_shift( $segments ); // First segment is the base name.
124 161 foreach ( $segments as $segment ) {
125 162 if ( in_array( $segment, $denied, true ) ) {
126 163 return new WP_Error(
127 - 'desktop_mode_desktop_theme_not_zip',
164 + 'openstation_desktop_theme_not_zip',
128 165 __( 'That file name is not allowed.', 'desktop-mode' ),
129 166 array( 'status' => 400 )
130 167 );
131 168 }
@@ -133,9 +170,9 @@
133 170
134 171 $max = (int) wp_max_upload_size();
135 172 if ( $max > 0 && isset( $file['size'] ) && (int) $file['size'] > $max ) {
136 173 return new WP_Error(
137 - 'desktop_mode_desktop_theme_too_large',
174 + 'openstation_desktop_theme_too_large',
138 175 sprintf(
139 176 /* translators: %s: formatted maximum file size. */
140 177 __( 'That theme archive is larger than the allowed maximum of %s.', 'desktop-mode' ),
141 178 size_format( $max )
@@ -146,23 +183,23 @@
146 183
147 184 $tmp = isset( $file['tmp_name'] ) ? (string) $file['tmp_name'] : '';
148 185 if ( '' === $tmp || ! file_exists( $tmp ) ) {
149 186 return new WP_Error(
150 - 'desktop_mode_desktop_theme_no_file',
187 + 'openstation_desktop_theme_no_file',
151 188 __( 'The uploaded archive could not be read.', 'desktop-mode' ),
152 189 array( 'status' => 400 )
153 190 );
154 191 }
155 192
156 - $entry = desktop_mode_desktop_theme_install_from_zip( $tmp );
193 + $entry = openstation_desktop_theme_install_from_zip( $tmp );
157 194 if ( is_wp_error( $entry ) ) {
158 195 return $entry;
159 196 }
160 197
161 - $shaped = desktop_mode_shape_desktop_theme_payload_entry( $entry, 'upload' );
198 + $shaped = openstation_shape_desktop_theme_payload_entry( $entry, 'upload' );
162 199 if ( ! $shaped ) {
163 200 return new WP_Error(
164 - 'desktop_mode_desktop_theme_install_failed',
201 + 'openstation_desktop_theme_install_failed',
165 202 __( 'The theme installed but could not be described back to the shell.', 'desktop-mode' ),
166 203 array( 'status' => 500 )
167 204 );
168 205 }
@@ -168,9 +205,9 @@
168 205 }
169 206
170 207 // Wallpapers the theme brought with it.
171 208 //
172 - // `desktop_mode_register_desktop_theme_wallpapers()` already ran on
209 + // `openstation_register_desktop_theme_wallpapers()` already ran on
173 210 // `init` for THIS request — before the upload existed — so the new
174 211 // theme's wallpapers are not in the registry yet. Re-running it now
175 212 // picks them up (registration is idempotent: same ids, same store),
176 213 // and the shell applies the rebuilt list without a reload. Without
@@ -176,10 +213,10 @@
176 213 // and the shell applies the rebuilt list without a reload. Without
177 214 // this the wallpapers only appeared on the next page load, which is
178 215 // exactly the kind of "it works after F5" seam this payload channel
179 216 // exists to remove.
180 - desktop_mode_register_desktop_theme_wallpapers();
181 - $shaped['serverWallpapers'] = desktop_mode_build_desktop_wallpapers_payload();
217 + openstation_register_desktop_theme_wallpapers();
218 + $shaped['serverWallpapers'] = openstation_build_desktop_wallpapers_payload();
182 219
183 220 return rest_ensure_response( $shaped );
184 221 }
185 222
@@ -188,11 +225,11 @@
188 225 *
189 226 * @param WP_REST_Request $request Request.
190 227 * @return WP_REST_Response|WP_Error
191 228 */
192 -function desktop_mode_rest_delete_desktop_theme( WP_REST_Request $request ) {
229 +function openstation_rest_delete_desktop_theme( WP_REST_Request $request ) {
193 230 $slug = sanitize_key( (string) $request['slug'] );
194 - $deleted = desktop_mode_desktop_theme_delete( $slug );
231 + $deleted = openstation_desktop_theme_delete( $slug );
195 232 if ( is_wp_error( $deleted ) ) {
196 233 return $deleted;
197 234 }
198 235 // The deleted theme's wallpapers were registered on `init`, into a
@@ -199,11 +236,11 @@
199 236 // per-request static store we have no unregister API for. Filtering
200 237 // them out of the response is enough and avoids inventing one: the
201 238 // store dies with the request, and the next one never registers
202 239 // them because the theme is gone.
203 - $prefix = DESKTOP_MODE_DESKTOP_THEME_WALLPAPER_PREFIX . $slug . '/';
240 + $prefix = OPENSTATION_DESKTOP_THEME_WALLPAPER_PREFIX . $slug . '/';
204 241 $wallpapers = array();
205 - foreach ( desktop_mode_build_desktop_wallpapers_payload() as $wallpaper ) {
242 + foreach ( openstation_build_desktop_wallpapers_payload() as $wallpaper ) {
206 243 $id = isset( $wallpaper['id'] ) ? (string) $wallpaper['id'] : '';
207 244 if ( '' !== $id && 0 === strpos( $id, $prefix ) ) {
208 245 continue;
209 246 }