PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.8
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.8
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 0.8.6 All 33 releases
desktop-mode / includes / settings-tabs.php

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

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