PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.0
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.0
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 / settings-tabs.php

settings-tabs.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.9.0, at includes/settings-tabs.php

319 lines 9.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Desktop OS Settings tab registration APIs.
4 *
5 * Two entry points, mirroring the command-palette surface
6 * ({@see includes/commands.php}):
7 *
8 * - `desktop_mode_register_settings_tab_script( $handle )` — primary,
9 * minimum-ceremony opt-in. Tells the shell: "this enqueued script
10 * registers OS Settings tabs; include it in the plugins-changed
11 * payload so it gets injected mid-session without a full reload."
12 *
13 * - `desktop_mode_register_settings_tab( $args )` — optional. Declares
14 * tab metadata server-side so the shell can live-unregister tabs on
15 * plugin deactivation without the JS having to tag every
16 * `registerSettingsTab()` with an `owner`.
17 *
18 * Both APIs feed `desktop_mode_build_desktop_settings_tab_scripts_payload()`
19 * and `desktop_mode_build_desktop_settings_tabs_payload()`, which contribute
20 * `serverSettingsTabScripts` and `serverSettingsTabs` to the shell
21 * payload in `desktop_mode_build_menu_payload()`.
22 *
23 * The tab's `render` callback lives JS-side — the PHP layer only
24 * ferries identity and metadata.
25 *
26 * @since 0.17.0
27 * @package WPDesktopMode
28 */
29
30 defined( 'ABSPATH' ) || exit;
31
32 /**
33 * Declare a WP-registered script handle as an OS Settings tab provider.
34 *
35 * Example:
36 *
37 * ```php
38 * add_action( 'admin_enqueue_scripts', function () {
39 * wp_register_script(
40 * 'my-plugin-settings',
41 * plugins_url( 'js/settings.js', __FILE__ ),
42 * array( 'desktop-mode' ),
43 * '1.0.0',
44 * true
45 * );
46 * wp_enqueue_script( 'my-plugin-settings' );
47 * } );
48 * desktop_mode_register_settings_tab_script( 'my-plugin-settings' );
49 * ```
50 *
51 * @since 0.17.0
52 *
53 * @param string $handle WP-registered script handle.
54 * @return true|WP_Error `true` on success; `WP_Error` on validation failure.
55 */
56 function desktop_mode_register_settings_tab_script( $handle ) {
57 $handle = (string) $handle;
58 if ( '' === $handle ) {
59 return desktop_mode_registration_error(
60 'desktop_mode_missing_handle',
61 __( 'Settings tab script registration requires a non-empty script handle.', 'desktop-mode' )
62 );
63 }
64
65 desktop_mode_desktop_settings_tab_script_registry( $handle, true );
66
67 /**
68 * Fires after a desktop settings-tab script handle is registered.
69 *
70 * @since 0.17.0
71 *
72 * @param string $handle The registered script handle.
73 */
74 do_action( 'desktop_mode_settings_tab_script_registered', $handle );
75
76 return true;
77 }
78
79 /**
80 * Declare an OS Settings tab server-side. Optional companion to
81 * `desktop_mode_register_settings_tab_script()` — plugins that declare
82 * their tab here get live-unregister-on-deactivate for free; plugins
83 * that don't can still set `owner` on their JS `registerSettingsTab()`
84 * call, or accept "tab stays until next reload" as graceful fallback.
85 *
86 * Example:
87 *
88 * ```php
89 * desktop_mode_register_settings_tab( array(
90 * 'id' => 'my-plugin',
91 * 'label' => __( 'My Plugin', 'my-plugin' ),
92 * 'capability' => 'manage_options',
93 * 'order' => 50,
94 * 'script' => 'my-plugin-settings',
95 * ) );
96 * ```
97 *
98 * Implicitly registers the `script` handle via
99 * `desktop_mode_register_settings_tab_script()` when provided.
100 *
101 * @since 0.17.0
102 *
103 * @param array $args {
104 * @type string $id Unique tab id, `[a-z0-9_-]+`. Required.
105 * @type string $label Human-readable tab label. Required.
106 * @type string $capability Required capability to see the tab.
107 * Shell today maps this to `isAdmin` gating
108 * (`manage_options` → admin-only; anything
109 * else → visible to everyone). Default empty.
110 * @type int $order Sort order relative to built-in tabs
111 * (appearance=10, ai=20, extended=30,
112 * help=40). Default 100 (appended).
113 * @type string $script WP script handle providing the
114 * `registerSettingsTab()` call.
115 * Registered implicitly when present.
116 * Default empty.
117 * }
118 * @return true|WP_Error `true` on success; `WP_Error` on validation failure.
119 */
120 function desktop_mode_register_settings_tab( $args = array() ) {
121 $defaults = array(
122 'id' => '',
123 'label' => '',
124 'capability' => '',
125 'order' => 100,
126 'script' => '',
127 );
128 $args = wp_parse_args( $args, $defaults );
129
130 $id = (string) $args['id'];
131 if ( '' === $id || ! preg_match( '/^[a-z0-9_\-]+$/', $id ) ) {
132 return desktop_mode_registration_error(
133 'desktop_mode_invalid_id',
134 __( 'Settings tab registration requires a non-empty `id` matching [a-z0-9_-]+.', 'desktop-mode' ),
135 array( 'id' => $id )
136 );
137 }
138 if ( '' === (string) $args['label'] ) {
139 return desktop_mode_registration_error(
140 'desktop_mode_missing_label',
141 __( 'Settings tab registration requires a non-empty `label`.', 'desktop-mode' ),
142 array( 'id' => $id )
143 );
144 }
145
146 $entry = array(
147 'id' => $id,
148 'label' => (string) $args['label'],
149 'capability' => (string) $args['capability'],
150 'order' => (int) $args['order'],
151 'script' => (string) $args['script'],
152 );
153 desktop_mode_desktop_settings_tab_registry( $id, $entry );
154
155 if ( '' !== $entry['script'] ) {
156 desktop_mode_desktop_settings_tab_script_registry( $entry['script'], true );
157 }
158
159 /**
160 * Fires after a desktop settings tab is successfully registered.
161 *
162 * @since 0.17.0
163 *
164 * @param string $id The tab id.
165 * @param array $entry The stored registry entry.
166 */
167 do_action( 'desktop_mode_settings_tab_registered', $id, $entry );
168
169 return true;
170 }
171
172 /**
173 * Internal module-level registry for settings-tab script handles
174 * declared via {@see desktop_mode_register_settings_tab_script()}.
175 *
176 * @since 0.17.0
177 * @internal
178 *
179 * @param string $handle Script handle to read or write.
180 * @param bool|null $value Pass `true` to register; `null` to read only.
181 * @return array|bool When called with no args returns the full store.
182 */
183 function desktop_mode_desktop_settings_tab_script_registry( $handle = '', $value = null ) {
184 static $store = array();
185
186 if ( '__flush__' === (string) $handle ) {
187 $store = array();
188 return array();
189 }
190 if ( '' === (string) $handle ) {
191 return $store;
192 }
193 if ( null !== $value ) {
194 $store[ (string) $handle ] = (bool) $value;
195 }
196 return isset( $store[ (string) $handle ] ) ? $store[ (string) $handle ] : false;
197 }
198
199 /**
200 * Test-only: clear the registry between PHPUnit cases. See
201 * {@see desktop_mode_flush_script_handle_registries()}.
202 *
203 * @since 0.18.0
204 */
205 function desktop_mode_flush_desktop_settings_tab_script_registry() {
206 desktop_mode_desktop_settings_tab_script_registry( '__flush__' );
207 }
208
209 /**
210 * Internal module-level registry for tabs declared via
211 * {@see desktop_mode_register_settings_tab()}.
212 *
213 * @since 0.17.0
214 * @internal
215 *
216 * @param string $id Tab id to read or write.
217 * @param array|null $entry Entry to store, or `null` to read.
218 * @return array|null
219 */
220 function desktop_mode_desktop_settings_tab_registry( $id = '', $entry = null ) {
221 static $store = array();
222
223 if ( '' === (string) $id ) {
224 return $store;
225 }
226 if ( null !== $entry ) {
227 $store[ (string) $id ] = $entry;
228 }
229 return isset( $store[ (string) $id ] ) ? $store[ (string) $id ] : null;
230 }
231
232 /**
233 * Build the script-handle payload fed to the shell. Handles that
234 * aren't currently enqueued resolve to an empty URL and are dropped —
235 * matches the command-scripts payload builder.
236 *
237 * @since 0.17.0
238 *
239 * @return array[] List of `{ handle, scriptUrl }` entries.
240 */
241 function desktop_mode_build_desktop_settings_tab_scripts_payload() {
242 $registry = desktop_mode_desktop_settings_tab_script_registry();
243 if ( ! is_array( $registry ) || empty( $registry ) ) {
244 return array();
245 }
246
247 $out = array();
248 $seen = array();
249 foreach ( $registry as $handle => $active ) {
250 if ( ! $active || isset( $seen[ $handle ] ) ) {
251 continue;
252 }
253 $payload = desktop_mode_resolve_script_payload( $handle );
254 if ( '' === $payload['url'] ) {
255 desktop_mode_warn_unresolvable_script_handle(
256 'desktop_mode_register_settings_tab_script',
257 'Settings-tab',
258 (string) $handle
259 );
260 continue;
261 }
262 $out[] = array(
263 'handle' => (string) $handle,
264 'scriptUrl' => $payload['url'],
265 'scriptBefore' => $payload['before'],
266 'scriptAfter' => $payload['after'],
267 'scriptL10n' => $payload['l10n'],
268 'scriptTranslations' => $payload['translations'],
269 );
270 $seen[ $handle ] = true;
271 }
272 return $out;
273 }
274
275 /**
276 * Build the metadata payload for tabs declared via
277 * {@see desktop_mode_register_settings_tab()}. Each entry carries the
278 * resolved `scriptUrl` alongside metadata so the shell's sync can
279 * unregister tabs attributable to a script handle that just left the
280 * `serverSettingsTabScripts` payload.
281 *
282 * @since 0.17.0
283 *
284 * @return array[]
285 */
286 function desktop_mode_build_desktop_settings_tabs_payload() {
287 $registry = desktop_mode_desktop_settings_tab_registry();
288 if ( ! is_array( $registry ) || empty( $registry ) ) {
289 return array();
290 }
291
292 $out = array();
293 foreach ( $registry as $entry ) {
294 $handle = (string) $entry['script'];
295 $payload = '' !== $handle
296 ? desktop_mode_resolve_script_payload( $handle )
297 : array(
298 'url' => '',
299 'before' => array(),
300 'after' => array(),
301 'l10n' => array(),
302 'translations' => '',
303 );
304 $out[] = array(
305 'id' => (string) $entry['id'],
306 'label' => (string) $entry['label'],
307 'capability' => (string) $entry['capability'],
308 'order' => (int) $entry['order'],
309 'scriptUrl' => $payload['url'],
310 'scriptHandle' => $handle,
311 'scriptBefore' => $payload['before'],
312 'scriptAfter' => $payload['after'],
313 'scriptL10n' => $payload['l10n'],
314 'scriptTranslations' => $payload['translations'],
315 );
316 }
317 return $out;
318 }
319