PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.12
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.12
1.1.12 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 All 36 releases
← All changes | includes/registries/wallpapers.php +103 -82 0.9.2 → 1.1.12 View file →
@@ -1,11 +1,11 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — Wallpapers registry.
3 + * OpenStation — Wallpapers registry.
4 4 *
5 5 * Server-side registration API + payload builder + asset enqueue
6 6 * for the desktop wallpaper picker. Wallpaper definitions live
7 - * on `window.desktopModeWallpapers[ id ]` (set by the plugin's
7 + * on `window.openStationWallpapers[ id ]` (set by the plugin's
8 8 * own JS); this module is the PHP side that announces them to
9 9 * the shell and ships their script handles into the boot
10 10 * payload.
11 11 *
@@ -12,10 +12,9 @@
12 12 * Extracted from `components.php` during the architecture-0.8.1
13 13 * PHP slicing (phase 6). Behaviour, function names, filter
14 14 * contracts, and error codes all unchanged.
15 15 *
16 - * @package Desktop_Mode
17 - * @since 0.8.1
16 + * @package OpenStation
18 17 */
19 18
20 19 defined( 'ABSPATH' ) || exit;
21 20
@@ -20,12 +19,12 @@
20 19 defined( 'ABSPATH' ) || exit;
21 20
22 21 /**
23 22 * Register a server-side desktop wallpaper. Symmetrical to
24 - * {@see desktop_mode_register_widget()}. The plugin's JS side
23 + * {@see openstation_register_widget()}. The plugin's JS side
25 24 * publishes the full `WallpaperDef` (with mount / resolveValue /
26 25 * renderEditor callbacks as appropriate) on
27 - * `window.desktopModeWallpapers[ <id> ]`; the shell loads the
26 + * `window.openStationWallpapers[ <id> ]`; the shell loads the
28 27 * declared script, reads that global, and registers the def via
29 28 * the normal wallpaper registry. Deactivation unregisters the
30 29 * def and re-applies the current selection (which falls back to
31 30 * a built-in if the user's active wallpaper was the one leaving).
@@ -32,9 +31,9 @@
32 31 *
33 32 * Example:
34 33 *
35 34 * ```php
36 - * desktop_mode_register_wallpaper( 'myplugin/snow', array(
35 + * openstation_register_wallpaper( 'myplugin/snow', array(
37 36 * 'label' => __( 'Snow', 'my-plugin' ),
38 37 * 'preview' => 'linear-gradient(#fff, #ddd)',
39 38 * 'type' => 'canvas',
40 39 * 'script' => 'my-plugin-snow-wallpaper',
@@ -42,10 +41,10 @@
42 41 * ```
43 42 *
44 43 * ```js
45 44 * // Inside my-plugin-snow-wallpaper.js
46 - * window.desktopModeWallpapers = window.desktopModeWallpapers || {};
47 - * window.desktopModeWallpapers[ 'myplugin/snow' ] = {
45 + * window.openStationWallpapers = window.openStationWallpapers || {};
46 + * window.openStationWallpapers[ 'myplugin/snow' ] = {
48 47 * id: 'myplugin/snow',
49 48 * label: 'Snow',
50 49 * type: 'canvas',
51 50 * preview: 'linear-gradient(#fff, #ddd)',
@@ -53,15 +52,10 @@
53 52 * mount: function ( container, ctx ) { return function () {}; },
54 53 * };
55 54 * ```
56 55 *
57 - * @since 0.10.0
58 - * @since 0.11.0 Returns `WP_Error` on validation failure instead of
59 - * silent `false`. Legacy `if ( $result )` callers remain
60 - * correct because `WP_Error` is truthy.
61 - *
62 56 * @param string $id Wallpaper id. For canvas wallpapers this must
63 - * match the `window.desktopModeWallpapers[<id>]`
57 + * match the `window.openStationWallpapers[<id>]`
64 58 * key the plugin's JS publishes.
65 59 * @param array $args {
66 60 * @type string $label Picker label. Required.
67 61 * @type string $preview CSS value rendered in the picker
@@ -78,19 +72,31 @@
78 72 * @type string $script Enqueued script handle that
79 73 * publishes the def on the global.
80 74 * Required for `canvas` type;
81 75 * optional for `css`.
76 + * @type string $description Plain-text description shown in OS
77 + * Settings when the wallpaper is the
78 + * active selection — what it is, where
79 + * its data comes from, the story behind
80 + * it. Optional.
81 + * @type string $tone 'light' | 'dark'. Whether the desk
82 + * paints its icons and labels in
83 + * Starlight or in Void. Optional;
84 + * unset reads as 'dark'. Declare
85 + * 'light' if a user would call your
86 + * surface pale. See
87 + * docs/desktop-themes.md.
82 88 * @type string[] $capabilities Gate: ALL caps must match. Any
83 89 * missed cap returns
84 - * `WP_Error desktop_mode_capability_denied`.
90 + * `WP_Error openstation_capability_denied`.
85 91 * }
86 92 * @return true|WP_Error `true` on success; `WP_Error` otherwise.
87 93 */
88 -function desktop_mode_register_wallpaper( $id, $args = array() ) {
94 +function openstation_register_wallpaper( $id, $args = array() ) {
89 95 $id = (string) $id;
90 96 if ( '' === $id ) {
91 - return desktop_mode_registration_error(
92 - 'desktop_mode_missing_id',
97 + return openstation_registration_error(
98 + 'openstation_missing_id',
93 99 __( 'Wallpaper id is required.', 'desktop-mode' )
94 100 );
95 101 }
96 102
@@ -99,28 +105,33 @@
99 105 'preview' => '',
100 106 'type' => 'canvas',
101 107 'value' => '',
102 108 'script' => '',
109 + 'description' => '',
110 + 'tone' => '',
103 111 'capabilities' => array(),
104 112 );
105 - $args = wp_parse_args( $args, $defaults );
113 + $args = wp_parse_args( $args, $defaults );
106 114
107 115 foreach ( (array) $args['capabilities'] as $cap ) {
108 116 if ( ! current_user_can( (string) $cap ) ) {
109 - return desktop_mode_registration_error(
110 - 'desktop_mode_capability_denied',
117 + return openstation_registration_error(
118 + 'openstation_capability_denied',
111 119 sprintf(
112 120 /* translators: %s: capability slug. */
113 121 __( 'Current user lacks the %s capability required to register this wallpaper.', 'desktop-mode' ),
114 122 (string) $cap
115 123 ),
116 - array( 'capability' => (string) $cap, 'id' => $id )
124 + array(
125 + 'capability' => (string) $cap,
126 + 'id' => $id,
127 + )
117 128 );
118 129 }
119 130 }
120 131 if ( '' === (string) $args['label'] ) {
121 - return desktop_mode_registration_error(
122 - 'desktop_mode_missing_label',
132 + return openstation_registration_error(
133 + 'openstation_missing_label',
123 134 __( 'Wallpaper registration requires a non-empty `label`.', 'desktop-mode' ),
124 135 array( 'id' => $id )
125 136 );
126 137 }
@@ -131,10 +142,10 @@
131 142 // `mount` callback is published on the JS global by that
132 143 // script). CSS wallpapers can skip the script — the shell can
133 144 // render from the `value` / `preview` string alone.
134 145 if ( 'canvas' === $type && '' === (string) $args['script'] ) {
135 - return desktop_mode_registration_error(
136 - 'desktop_mode_missing_script',
146 + return openstation_registration_error(
147 + 'openstation_missing_script',
137 148 __( 'Canvas wallpaper registration requires a `script` handle that publishes the def.', 'desktop-mode' ),
138 149 array( 'id' => $id )
139 150 );
140 151 }
@@ -148,29 +159,43 @@
148 159 $value = (string) $args['preview'];
149 160 }
150 161
151 162 $entry = array(
152 - 'id' => $id,
153 - 'label' => (string) $args['label'],
154 - 'preview' => (string) $args['preview'],
155 - 'type' => $type,
156 - 'value' => $value,
157 - 'script' => (string) $args['script'],
163 + 'id' => $id,
164 + // Plain text by contract, same as `description` below. The
165 + // shell paints labels through the `html` tagged template, whose
166 + // text slots build DOM with `createTextNode()` — never
167 + // `innerHTML` — so a label cannot become markup downstream.
168 + //
169 + // Note this STRIPS rather than ESCAPES, and that distinction is
170 + // load-bearing: `esc_html()` here would encode `&` in a
171 + // perfectly ordinary label ("Black & White") and the text node
172 + // would then render the entity literally as `&amp;`. Escaping
173 + // belongs at an HTML boundary; there isn't one on this path.
174 + 'label' => sanitize_text_field( (string) $args['label'] ),
175 + 'preview' => (string) $args['preview'],
176 + 'type' => $type,
177 + 'value' => $value,
178 + 'script' => (string) $args['script'],
179 + // Plain text by contract — the shell renders it as text, never
180 + // as HTML, so strip tags here rather than trusting every caller.
181 + 'description' => sanitize_textarea_field( (string) $args['description'] ),
182 + // Anything else stores empty and reads as 'dark', so a typo
183 + // lands on the old look rather than on invisible icons.
184 + 'tone' => in_array( $args['tone'], array( 'light', 'dark' ), true ) ? (string) $args['tone'] : '',
158 185 );
159 - desktop_mode_desktop_wallpaper_registry( $id, $entry );
186 + openstation_desktop_wallpaper_registry( $id, $entry );
160 187
161 188 /**
162 189 * Fires after a desktop wallpaper is successfully registered.
163 190 *
164 - * Does NOT fire when `desktop_mode_register_wallpaper()` returns a
191 + * Does NOT fire when `openstation_register_wallpaper()` returns a
165 192 * `WP_Error`.
166 193 *
167 - * @since 0.11.0
168 - *
169 194 * @param string $id The wallpaper id.
170 195 * @param array $entry The stored registry entry.
171 196 */
172 - do_action( 'desktop_mode_wallpaper_registered', $id, $entry );
197 + do_action( 'openstation_wallpaper_registered', $id, $entry );
173 198
174 199 return true;
175 200 }
176 201
@@ -175,15 +200,14 @@
175 200 }
176 201
177 202 /**
178 203 * Internal module-level registry for wallpapers registered via
179 - * {@see desktop_mode_register_wallpaper()}. Same static-store
204 + * {@see openstation_register_wallpaper()}. Same static-store
180 205 * pattern as the widget + native-window registries.
181 206 *
182 - * @since 0.10.0
183 207 * @internal
184 208 */
185 -function desktop_mode_desktop_wallpaper_registry( $id = '', $entry = null ) {
209 +function openstation_desktop_wallpaper_registry( $id = '', $entry = null ) {
186 210 static $store = array();
187 211
188 212 if ( '' === (string) $id ) {
189 213 return $store;
@@ -198,28 +222,24 @@
198 222 * Build the wallpaper list for the shell payload. Only metadata +
199 223 * the resolved script URL cross the wire; the plugin's mount
200 224 * callback is announced via the JS global the script sets up.
201 225 *
202 - * @since 0.10.0
203 - *
204 226 * @return array[]
205 227 */
206 -function desktop_mode_build_desktop_wallpapers_payload() {
207 - $registry = desktop_mode_desktop_wallpaper_registry();
228 +function openstation_build_desktop_wallpapers_payload() {
229 + $registry = openstation_desktop_wallpaper_registry();
208 230 if ( ! is_array( $registry ) || empty( $registry ) ) {
209 231 return array();
210 232 }
211 233 /**
212 234 * Filters the server-declared wallpaper list before it ships to
213 - * the shell. Mirrors the JS-side `desktop-mode.wallpapers` filter
235 + * the shell. Mirrors the JS-side `os.wallpapers` filter
214 236 * so plugins can rearrange, hide, or override entries at boot
215 237 * without round-tripping through the JS registry.
216 238 *
217 - * @since 0.11.0
218 - *
219 239 * @param array[] $registry The registered wallpaper entries.
220 240 */
221 - $registry = apply_filters( 'desktop_mode_wallpapers', $registry );
241 + $registry = apply_filters( 'openstation_wallpapers', $registry );
222 242 if ( ! is_array( $registry ) ) {
223 243 return array();
224 244 }
225 245 $out = array();
@@ -227,21 +247,26 @@
227 247 if ( ! is_array( $entry ) || empty( $entry['id'] ) ) {
228 248 continue;
229 249 }
230 250 $handle = isset( $entry['script'] ) ? (string) $entry['script'] : '';
231 - $payload = desktop_mode_resolve_script_payload( $handle );
232 - $out[] = array(
233 - 'id' => (string) $entry['id'],
234 - 'label' => isset( $entry['label'] ) ? (string) $entry['label'] : '',
235 - 'preview' => isset( $entry['preview'] ) ? (string) $entry['preview'] : '',
236 - 'type' => isset( $entry['type'] ) ? (string) $entry['type'] : 'canvas',
237 - 'value' => isset( $entry['value'] ) ? (string) $entry['value'] : '',
238 - 'scriptUrl' => $payload['url'],
239 - 'scriptHandle' => $handle,
240 - 'scriptBefore' => $payload['before'],
241 - 'scriptAfter' => $payload['after'],
242 - 'scriptL10n' => $payload['l10n'],
251 + $payload = openstation_resolve_script_payload( $handle );
252 + $out[] = array(
253 + 'id' => (string) $entry['id'],
254 + 'label' => isset( $entry['label'] ) ? (string) $entry['label'] : '',
255 + 'preview' => isset( $entry['preview'] ) ? (string) $entry['preview'] : '',
256 + 'type' => isset( $entry['type'] ) ? (string) $entry['type'] : 'canvas',
257 + 'value' => isset( $entry['value'] ) ? (string) $entry['value'] : '',
258 + 'description' => isset( $entry['description'] ) ? (string) $entry['description'] : '',
259 + 'tone' => isset( $entry['tone'] ) ? (string) $entry['tone'] : '',
260 + 'scriptUrl' => $payload['url'],
261 + 'scriptHandle' => $handle,
262 + 'scriptBefore' => $payload['before'],
263 + 'scriptAfter' => $payload['after'],
264 + 'scriptL10n' => $payload['l10n'],
243 265 'scriptTranslations' => $payload['translations'],
266 + // The handle's dependency closure, replayed before the bundle
267 + // on its lazy load — see `openstation_resolve_script_dependencies()`.
268 + 'scriptDeps' => openstation_resolve_script_dependencies( $handle ),
244 269 );
245 270 }
246 271 return $out;
247 272 }
@@ -246,27 +271,23 @@
246 271 return $out;
247 272 }
248 273
249 274
250 -/**
251 - * Enqueue plugin-registered wallpaper scripts on the shell page
252 - * so wallpapers active at boot time have their defs available
253 - * without any dynamic-load roundtrip.
275 +/*
276 + * Wallpaper scripts are NOT enqueued here, and that is deliberate.
254 277 *
255 - * @since 0.10.0
278 + * A canvas wallpaper's bundle IS the wallpaper — Living Tree is 58 KB
279 + * of PixiJS scene, Snow is 42 KB — and this file used to
280 + * `wp_enqueue_script()` every registered one on every admin page, so
281 + * that every user downloaded and parsed every wallpaper in the
282 + * install including the ones they were not wearing. The metadata in
283 + * the boot payload (label, preview swatch, description) is enough for
284 + * the shell to register a stub and paint a picker tile without any of
285 + * it.
286 + *
287 + * The bundle arrives when something needs the callbacks: the shell
288 + * hydrates the user's ACTIVE wallpaper during the boot sync, and the
289 + * wallpaper picker hydrates the rest when it opens. See
290 + * `src/wallpapers/lazy.ts`. `scriptUrl` in the payload (built above)
291 + * is what makes that possible; nothing else on the PHP side is
292 + * involved.
256 293 */
257 -function desktop_mode_enqueue_desktop_wallpaper_scripts() {
258 - if ( ! desktop_mode_is_enabled() || desktop_mode_is_chromeless_request() || desktop_mode_is_classic_request() ) {
259 - return;
260 - }
261 - $registry = desktop_mode_desktop_wallpaper_registry();
262 - if ( ! is_array( $registry ) ) {
263 - return;
264 - }
265 - foreach ( $registry as $entry ) {
266 - if ( ! empty( $entry['script'] ) ) {
267 - wp_enqueue_script( $entry['script'] );
268 - }
269 - }
270 -}
271 -add_action( 'admin_enqueue_scripts', 'desktop_mode_enqueue_desktop_wallpaper_scripts', 20 );
272 -