PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.10
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.10
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
← All changes | includes/my-wordpress/window.php +61 -175 1.1.31.1.10 View file →
@@ -1,31 +1,27 @@
1 1 <?php
2 2 /**
3 - * OpenStation — My WordPress: window + pinned icon registration.
3 + * OpenStation — My WordPress: the explorer's identity + shared helpers.
4 4 *
5 - * Native window with id `desktop-mode-my-wordpress`, opened from a
6 - * pinned desktop icon that always sits in the top-left of the grid
7 - * (`pinned: true`, `position: -1`). The bundle renders a two-pane
8 - * file-explorer UI with breadcrumb navigation: root shows Posts,
9 - * Pages, Users, and Media folder tiles, and clicking one drills into
10 - * an infinite-scroll list of entities with a per-kind preview pane.
5 + * The app people open is `apps/my-wordpress/` — WP Explorer, rebuilt
6 + * on the App Framework. This module keeps what the port shares: the
7 + * name and the folder-mark icon (the app reads both from the helpers
8 + * here), the capability gate, and the inert entities compatibility
9 + * surface (see the note at the end of the file).
11 10 *
12 11 * **The app is called WP Explorer; the module is called my-wordpress.**
13 - * The display name is the only thing that changed — the window id, the
14 - * icon id, the script and style handles, the function prefix and every
15 - * `openstation_my_wordpress_*` filter are the names plugins and stored
16 - * desktop layouts already reference, so they stay put. See the frozen-
17 - * values rule in AGENTS.md; renaming any of them here would orphan a
18 - * user's pinned tile rather than move it.
12 + * The function prefix and every `openstation_my_wordpress_*` filter
13 + * are names plugins already reference — the frozen-values rule in
14 + * AGENTS.md keeps them put.
19 15 *
20 - * Filterable surface (mirrors the recycle-bin / posts-window modules):
16 + * Filterable surface:
21 17 *
22 - * - `openstation_my_wordpress_window_args`
23 - * - `openstation_my_wordpress_icon_args`
24 18 * - `openstation_my_wordpress_user_can_use`
25 - * - `openstation_my_wordpress_entities`
26 - * - `openstation_my_wordpress_template_html`
19 + * - `openstation_my_wordpress_entities` (inert — see the end note)
27 20 *
21 + * (`openstation_my_wordpress_icon_args`, `_window_args` and
22 + * `_template_html` went with the legacy window they configured.)
23 + *
28 24 * @package OpenStation
29 25 */
30 26
31 27 defined( 'ABSPATH' ) || exit;
@@ -95,8 +91,37 @@
95 91 *
96 92 * Mirrors the recycle-bin gate — anyone who can edit posts can
97 93 * browse posts and pages.
98 94 *
95 + * This is the module's one capability gate, and it is a **server-side
96 + * authorization** gate, not just a visibility one. It decides:
97 + *
98 + * - The non-REST post-type bridge: whether
99 + * `desktop-mode/v1/post-type/<slug>` routes register at all
100 + * (`rest-post-type.php`).
101 + * - The per-comment dossier route
102 + * `desktop-mode/v1/comment-stats/<id>` (`comment-stats.php`).
103 + * - The user and term dossier routes
104 + * `desktop-mode/v1/user-stats/<id>`,
105 + * `desktop-mode/v1/user-footprint/<id>` and
106 + * `desktop-mode/v1/term-stats/<taxonomy>/<id>` (`user-stats.php`,
107 + * `user-footprint.php`, `term-stats.php`), which then scope their
108 + * payloads to what the caller may read.
109 + * - Whether the WooCommerce integration's boot config ships, so the
110 + * client can reach the order / customer / product surfaces at all
111 + * — those routes still enforce their own Woo capabilities on top
112 + * (`integrations/woocommerce.php`).
113 + * - Whether preview-action scripts registered by plugins are
114 + * enqueued (`preview-actions.php`).
115 + * - Whether Station Home offers the "WP Explorer" quick action
116 + * (`apps/station-home/parts/snapshot.php`).
117 + *
118 + * It does **not** gate the app's own window or pinned launcher: WP
119 + * Explorer is an App Framework app and declares
120 + * `->capabilities( 'edit_posts' )` itself (`apps/my-wordpress/`).
121 + * Returning `true` here opens the surfaces above without opening the
122 + * window; to move the window too, filter the app's manifest.
123 + *
99 124 * @return bool
100 125 */
101 126 function openstation_my_wordpress_user_can_use() {
102 127 $can = current_user_can( 'edit_posts' );
@@ -101,10 +126,10 @@
101 126 function openstation_my_wordpress_user_can_use() {
102 127 $can = current_user_can( 'edit_posts' );
103 128
104 129 /**
105 - * Filter whether the current user can see the My WordPress
106 - * pinned icon and window.
130 + * Filter whether the current user can reach the My WordPress
131 + * module's surfaces — its REST routes included.
107 132 *
108 133 * @param bool $can Default: edit_posts capability.
109 134 */
110 135 return (bool) apply_filters( 'openstation_my_wordpress_user_can_use', $can );
@@ -199,161 +224,22 @@
199 224 $filtered = apply_filters( 'openstation_my_wordpress_entities', $entities );
200 225 return is_array( $filtered ) ? array_values( $filtered ) : $entities;
201 226 }
202 227
203 -/**
204 - * Render the My WordPress window's static template body. The bundle
205 - * mounts its UI into `[data-os-my-wordpress-root]`.
206 - */
207 -function openstation_my_wordpress_render_template() {
208 - ob_start();
209 - ?>
210 - <div class="desktop-mode-my-wordpress" data-os-my-wordpress-root>
211 - <header data-os-my-wordpress-breadcrumbs></header>
212 - <div class="os-my-wordpress__body" data-os-my-wordpress-body>
213 - <div class="os-my-wordpress__loading" data-os-my-wordpress-loading hidden>
214 - <os-spinner></os-spinner>
215 - </div>
216 - </div>
217 - <div class="os-folder-status-bar" data-os-my-wordpress-status></div>
218 - </div>
219 - <?php
220 - $html = (string) ob_get_clean();
221 -
222 - /**
223 - * Filter the My WordPress window's template HTML.
224 - *
225 - * @param string $html Default template HTML.
226 - */
227 - $filtered = (string) apply_filters( 'openstation_my_wordpress_template_html', $html );
228 -
229 - $allowed_html = function_exists( 'openstation_native_window_allowed_html' )
230 - ? openstation_native_window_allowed_html()
231 - : wp_kses_allowed_html( 'post' );
232 -
233 - echo wp_kses( $filtered, $allowed_html );
234 -}
235 -
236 -/**
237 - * Register the native window + the pinned wallpaper icon on `init`,
238 - * priority 99 — after `components.php` boots the registry, and late
239 - * enough that every plugin's `register_post_type()` call has already
240 - * run. The entity list is frozen into the window config here and only
241 - * emitted later on `admin_enqueue_scripts`, so a CPT registered after
242 - * this point would never reach the bundle. `previewActions` is the
243 - * exception: it is re-collected at emit time via
244 - * `openstation_my_wordpress_refresh_window_config()` below, so the
245 - * value snapshotted here is only the fallback.
246 - */
247 -function openstation_my_wordpress_register_window() {
248 - if ( ! openstation_my_wordpress_user_can_use() ) {
249 - return;
250 - }
251 -
252 - $site_title = openstation_site_title();
253 - $app_title = openstation_my_wordpress_app_title();
254 - $icon_uri = 'data:image/svg+xml;base64,' . base64_encode( openstation_my_wordpress_icon_svg() );
255 -
256 - $entities = openstation_my_wordpress_entities();
257 -
258 - $window_args = array(
259 - 'title' => $app_title,
260 - 'icon' => $icon_uri,
261 - 'template' => 'openstation_my_wordpress_render_template',
262 - 'script' => 'desktop-mode-my-wordpress',
263 - // `styles` (companion), not `style`: loads on first open
264 - // rather than at every shell boot. Declared FIRST so the
265 - // WooCommerce integration's sheet — appended to this array by
266 - // `openstation_my_wordpress_woo_window_args()` — lands after
267 - // it in the head and keeps winning their equal-specificity
268 - // overrides by source order.
269 - 'styles' => array( 'desktop-mode-my-wordpress' ),
270 - 'width' => 960,
271 - 'height' => 640,
272 - 'min_width' => 640,
273 - 'min_height' => 420,
274 - 'placement' => 'none',
275 - 'config' => array(
276 - 'restRoot' => esc_url_raw( rest_url() ),
277 - 'restNonce' => wp_create_nonce( 'wp_rest' ),
278 - 'editPostUrlBase' => esc_url_raw( admin_url( 'post.php' ) ),
279 - 'editUserUrlBase' => esc_url_raw( admin_url( 'user-edit.php' ) ),
280 - 'siteName' => $site_title,
281 - 'entities' => $entities,
282 - 'groups' => function_exists( 'openstation_my_wordpress_collect_groups' )
283 - ? openstation_my_wordpress_collect_groups( $entities )
284 - : array(),
285 - 'perPage' => 24,
286 - 'mediaPerPage' => 48,
287 - 'previewActions' => function_exists( 'openstation_my_wordpress_collect_preview_actions' )
288 - ? openstation_my_wordpress_collect_preview_actions()
289 - : array(),
290 - ),
291 - );
292 -
293 - /**
294 - * Filter the args used to register the My WordPress native window.
295 - *
296 - * @param array $window_args Args passed to `openstation_register_window()`.
297 - */
298 - $window_args = (array) apply_filters( 'openstation_my_wordpress_window_args', $window_args );
299 -
300 - $registered = openstation_register_window( 'desktop-mode-my-wordpress', $window_args );
301 - if ( is_wp_error( $registered ) ) {
302 - // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
303 - error_log( '[openstation] My WordPress window registration failed: ' . $registered->get_error_message() );
304 - return;
305 - }
306 -
307 - $icon_args = array(
308 - 'title' => $app_title,
309 - 'icon' => $icon_uri,
310 - 'window' => 'desktop-mode-my-wordpress',
311 - 'pinned' => true,
312 - 'position' => -1,
313 - );
314 -
315 - /**
316 - * Filter the args used to register the My WordPress pinned icon.
317 - *
318 - * Removing `pinned` here lets the icon participate in normal
319 - * sort order — useful for sites that want the shortcut to feel
320 - * like any other plugin icon.
321 - *
322 - * @param array $icon_args Args passed to `openstation_register_icon()`.
323 - */
324 - $icon_args = (array) apply_filters( 'openstation_my_wordpress_icon_args', $icon_args );
325 -
326 - openstation_register_icon( 'desktop-mode-my-wordpress', $icon_args );
327 -}
328 -add_action( 'init', 'openstation_my_wordpress_register_window', 99 );
329 -
330 -/**
331 - * Re-collect the preview-action descriptors when the window config is
332 - * serialized for the browser, replacing the `init` 99 snapshot taken
333 - * at registration time.
228 +/*
229 + * No window, no template, no launcher. The explorer people open is
230 + * the `my-wordpress` APP (`apps/my-wordpress/`), which reclaimed the
231 + * "WP Explorer" name and the folder mark from this module's helpers
232 + * above. The legacy native window, its bundle and its pinned icon are
233 + * gone; every deep surface it used to host moved with the port — the
234 + * detail dossiers and the activity footprint render inside the app,
235 + * "open this object" travels through the shared stores in
236 + * `src/open-targets/explorer-open.ts` / `footprint-target.ts`, and
237 + * the Recycle Bin trashes dropped rows by their payload's `restPath`.
334 238 *
335 - * The action SCRIPTS were always collected late (`admin_enqueue_scripts`
336 - * 40, `openstation_my_wordpress_enqueue_preview_action_scripts()`), so
337 - * a plugin registering its `openstation_my_wordpress_preview_actions`
338 - * callback after `init` 99 used to get its JS delivered with no
339 - * descriptor to attach to — the button simply never rendered. Emitting
340 - * both legs from the same late collection closes that trap: any
341 - * registration during a normal bootstrap now ships both.
342 - *
343 - * The entity list deliberately stays frozen at `init` 99 — see the
344 - * registration docblock above.
345 - *
346 - * @param array $config Window config blob about to be emitted.
347 - * @param string $window_id Native window id.
348 - * @return array Config with fresh `previewActions` for our window.
239 + * `openstation_my_wordpress_entities()` and its filter remain as an
240 + * inert compatibility surface: subscribers registered against them
241 + * (WooCommerce's own among them) still run, and the pure helpers are
242 + * still what the tests pin — but nothing consumes the list to build a
243 + * window any more. The `openstation_my_wordpress_window_args` /
244 + * `openstation_my_wordpress_template_html` filters no longer fire.
349 245 */
350 -function openstation_my_wordpress_refresh_window_config( $config, $window_id ) {
351 - if ( 'desktop-mode-my-wordpress' !== $window_id || ! is_array( $config ) ) {
352 - return $config;
353 - }
354 - if ( function_exists( 'openstation_my_wordpress_collect_preview_actions' ) ) {
355 - $config['previewActions'] = openstation_my_wordpress_collect_preview_actions();
356 - }
357 - return $config;
358 -}
359 -add_filter( 'openstation_native_window_config', 'openstation_my_wordpress_refresh_window_config', 10, 2 );