PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.5
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.5
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 / plugins-window / window.php

window.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 1.1.5, at includes/plugins-window/window.php

203 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OpenStation — Native Plugins Window: registration + template.
4 *
5 * Native window registered with `placement: 'none'` — the entry
6 * point is the existing Plugins dock tile (built from WordPress's
7 * `$menu`), which the JS-side URL remap rewrites to open this window
8 * when `nativePluginsEnabled` is on.
9 *
10 * The shell wraps the template echoed by
11 * `openstation_plugins_window_render_template()` in
12 * `<template id="os-native-window-desktop-mode-plugins">`
13 * and clones it into the window body BEFORE the JS render callback
14 * fires. The `data-os-plugins-*` hooks below are the
15 * contract the JS relies on — keep them intact (or rename via the
16 * filter) when customizing the layout.
17 *
18 * @package OpenStation
19 */
20
21 defined( 'ABSPATH' ) || exit;
22
23 /**
24 * Echoes the native Plugins window's template body.
25 */
26 function openstation_plugins_window_render_template() {
27 $caps = openstation_plugins_window_caps();
28
29 ob_start();
30 ?>
31 <div class="desktop-mode-plugins" data-os-plugins-root>
32 <os-tabs value="installed" class="os-plugins__tabs" data-os-plugins-tabs>
33 <os-tab value="installed"><?php esc_html_e( 'Installed', 'desktop-mode' ); ?></os-tab>
34 <?php if ( ! empty( $caps['install'] ) ) : ?>
35 <os-tab value="browse"><?php esc_html_e( 'Add Plugin', 'desktop-mode' ); ?></os-tab>
36 <os-tab value="featured"><?php esc_html_e( 'OpenStation plugins', 'desktop-mode' ); ?></os-tab>
37 <?php endif; ?>
38 </os-tabs>
39
40 <os-tabpanel for="installed" class="os-plugins__panel">
41 <div class="os-plugins__installed" data-os-plugins-installed-host>
42 <?php
43 /*
44 * JS bundle paints the toolbar + <os-table> here.
45 * Empty host — first-frame shows the table's own
46 * loading skeleton.
47 */
48 ?>
49 </div>
50 </os-tabpanel>
51
52 <?php if ( ! empty( $caps['install'] ) ) : ?>
53 <os-tabpanel for="browse" class="os-plugins__panel">
54 <div class="os-plugins__browse" data-os-plugins-browse-host>
55 <?php
56 /*
57 * JS bundle paints the search + segmented filter
58 * + Upload button + <os-grid> of cards here.
59 */
60 ?>
61 </div>
62 </os-tabpanel>
63 <os-tabpanel for="featured" class="os-plugins__panel">
64 <div class="os-plugins__featured" data-os-plugins-featured-host>
65 <?php
66 /*
67 * JS bundle paints an intro blurb + gallery of
68 * plugins that integrate with OpenStation here.
69 */
70 ?>
71 </div>
72 </os-tabpanel>
73 <?php endif; ?>
74
75 <?php
76 /*
77 * Detail flyout — populated lazily when a card is clicked.
78 * Lives at the root of the template so it can slide over the
79 * full window body, not just one tab panel.
80 */
81 ?>
82 <os-flyout
83 placement="end"
84 data-os-plugins-flyout
85 aria-label="<?php esc_attr_e( 'Plugin details', 'desktop-mode' ); ?>"
86 ></os-flyout>
87 </div>
88 <?php
89 $html = (string) ob_get_clean();
90
91 /**
92 * Filter the native Plugins window's template HTML.
93 *
94 * Keep the `data-os-plugins-*` hooks intact so the JS
95 * render callback can find its mount points, or rename them and
96 * update the matching constants in `src/plugins-window/index.ts`.
97 *
98 * @param string $html Default template HTML.
99 */
100 $filtered = (string) apply_filters( 'openstation_plugins_window_template_html', $html );
101
102 if ( function_exists( 'openstation_kses_native_window_template' ) ) {
103 echo openstation_kses_native_window_template( $filtered ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- helper kses-escapes.
104 } else {
105 echo wp_kses( $filtered, wp_kses_allowed_html( 'post' ) );
106 }
107 }
108
109 /**
110 * Register the native Plugins window on `init` (priority 20, after
111 * `components.php` has bootstrapped the registry).
112 *
113 * Cap-only gate so that flipping the opt-in mid-session doesn't
114 * require an F5. The opt-in is a runtime check on the JS-side remap
115 * (`enabled: ( s ) => s.nativePluginsEnabled === true` in
116 * `src/desktop.ts`).
117 */
118 function openstation_plugins_window_register_window() {
119 if ( ! openstation_plugins_window_user_can_register() ) {
120 return;
121 }
122
123 $caps = openstation_plugins_window_caps();
124
125 $window_args = array(
126 'title' => __( 'Plugins', 'desktop-mode' ),
127 'icon' => 'dashicons-admin-plugins',
128 'template' => 'openstation_plugins_window_render_template',
129 'script' => 'os-plugins-window',
130 'styles' => array( 'os-plugins-window' ),
131 'width' => 1180,
132 'height' => 760,
133 'min_width' => 760,
134 'min_height' => 480,
135 // `'none'` — no dock or wallpaper tile from this registration.
136 // The Plugins dock tile lives in WordPress's `$menu` and the
137 // JS-side URL remap routes its click to `openById` here when
138 // the opt-in is on. A separate tile would be a duplicate
139 // entry point.
140 'placement' => 'none',
141 'config' => array(
142 'restRoot' => esc_url_raw( rest_url() ),
143 'restNonce' => wp_create_nonce( 'wp_rest' ),
144 // Core's REST controller for installed plugins.
145 'pluginsUrl' => esc_url_raw( rest_url( 'wp/v2/plugins' ) ),
146 // `admin-ajax.php` is the canonical home for our
147 // install/upload/browse/info/reviews handlers — Plugin Check
148 // rejects calls to admin-only classes from REST callbacks.
149 'ajaxUrl' => esc_url_raw( admin_url( 'admin-ajax.php' ) ),
150 'ajaxNonce' => wp_create_nonce( 'desktop-mode-plugins' ),
151 // Core's `wp_ajax_install_plugin` (and friends) verify
152 // against the `'updates'` nonce action — same string Core's
153 // wp.updates client passes. We reuse it verbatim so we go
154 // through Core's existing handler, no reimplementation.
155 'updatesNonce' => wp_create_nonce( 'updates' ),
156 'caps' => $caps,
157 // Global "Automatic Updates" column gate — same shape Core's
158 // `WP_Plugins_List_Table::$show_autoupdates` uses (true only
159 // when the auto-update subsystem is enabled AND the viewer
160 // can update plugins). Per-row state still lives on the REST
161 // field `openstation_auto_update` so the JS knows whether
162 // each individual row is enabled / forced / supported.
163 'autoUpdatesEnabled' => openstation_plugins_window_auto_updates_enabled(),
164 'currentUserId' => (int) get_current_user_id(),
165 // The plugin file path WordPress uses to identify the
166 // OpenStation plugin itself in REST mutations
167 // (`/wp/v2/plugins/{plugin}`). The JS uses this to detect
168 // "user just deactivated/deleted us" and reload the page
169 // out of the now-stale desktop shell before they hit any
170 // dead UI.
171 //
172 // Stripped of `.php` to match Core's REST representation —
173 // the `/wp/v2/plugins` controller returns `plugin` as
174 // `substr( $file, 0, -4 )` (see
175 // `wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php`).
176 // Comparing the raw `plugin_basename()` against the REST
177 // field always missed by exactly four characters, which
178 // silently skipped the self-deactivate reload.
179 'selfPluginFile' => substr( plugin_basename( OPENSTATION_FILE ), 0, -4 ),
180 // The wp-admin root URL — the JS navigates here after a
181 // self-deactivate so the user lands on the classic
182 // Dashboard rather than reloading their current URL
183 // (which might be a deactivated plugin's `?page=…` route
184 // that now 403s).
185 'adminUrl' => esc_url_raw( admin_url() ),
186 ),
187 );
188
189 /**
190 * Filter the args used to register the native Plugins window.
191 *
192 * @param array $window_args Args passed to `openstation_register_window()`.
193 */
194 $window_args = (array) apply_filters( 'openstation_plugins_window_args', $window_args );
195
196 $registered = openstation_register_window( 'desktop-mode-plugins', $window_args );
197 if ( is_wp_error( $registered ) ) {
198 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
199 error_log( '[openstation] Native Plugins window registration failed: ' . $registered->get_error_message() );
200 }
201 }
202 add_action( 'init', 'openstation_plugins_window_register_window', 20 );
203