`
* and clones it into the window body BEFORE the JS render callback
* fires. The `data-os-plugins-*` hooks below are the
* contract the JS relies on — keep them intact (or rename via the
* filter) when customizing the layout.
*
* @package OpenStation
*/
defined( 'ABSPATH' ) || exit;
/**
* Echoes the native Plugins window's template body.
*/
function openstation_plugins_window_render_template() {
$caps = openstation_plugins_window_caps();
ob_start();
?>
here.
* Empty host — first-frame shows the table's own
* loading skeleton.
*/
?>
of cards here.
*/
?>
s.nativePluginsEnabled === true` in
* `src/desktop.ts`).
*/
function openstation_plugins_window_register_window() {
if ( ! openstation_plugins_window_user_can_register() ) {
return;
}
$caps = openstation_plugins_window_caps();
$window_args = array(
'title' => __( 'Plugins', 'desktop-mode' ),
'icon' => 'dashicons-admin-plugins',
'template' => 'openstation_plugins_window_render_template',
'script' => 'os-plugins-window',
'styles' => array( 'os-plugins-window' ),
'width' => 1180,
'height' => 760,
'min_width' => 760,
'min_height' => 480,
// `'none'` — no dock or wallpaper tile from this registration.
// The Plugins dock tile lives in WordPress's `$menu` and the
// JS-side URL remap routes its click to `openById` here when
// the opt-in is on. A separate tile would be a duplicate
// entry point.
'placement' => 'none',
'config' => array(
'restRoot' => esc_url_raw( rest_url() ),
'restNonce' => wp_create_nonce( 'wp_rest' ),
// Core's REST controller for installed plugins.
'pluginsUrl' => esc_url_raw( rest_url( 'wp/v2/plugins' ) ),
// `admin-ajax.php` is the canonical home for our
// install/upload/browse/info/reviews handlers — Plugin Check
// rejects calls to admin-only classes from REST callbacks.
'ajaxUrl' => esc_url_raw( admin_url( 'admin-ajax.php' ) ),
'ajaxNonce' => wp_create_nonce( 'desktop-mode-plugins' ),
// Core's `wp_ajax_install_plugin` (and friends) verify
// against the `'updates'` nonce action — same string Core's
// wp.updates client passes. We reuse it verbatim so we go
// through Core's existing handler, no reimplementation.
'updatesNonce' => wp_create_nonce( 'updates' ),
'caps' => $caps,
// Global "Automatic Updates" column gate — same shape Core's
// `WP_Plugins_List_Table::$show_autoupdates` uses (true only
// when the auto-update subsystem is enabled AND the viewer
// can update plugins). Per-row state still lives on the REST
// field `openstation_auto_update` so the JS knows whether
// each individual row is enabled / forced / supported.
'autoUpdatesEnabled' => openstation_plugins_window_auto_updates_enabled(),
'currentUserId' => (int) get_current_user_id(),
// The plugin file path WordPress uses to identify the
// OpenStation plugin itself in REST mutations
// (`/wp/v2/plugins/{plugin}`). The JS uses this to detect
// "user just deactivated/deleted us" and reload the page
// out of the now-stale desktop shell before they hit any
// dead UI.
//
// Stripped of `.php` to match Core's REST representation —
// the `/wp/v2/plugins` controller returns `plugin` as
// `substr( $file, 0, -4 )` (see
// `wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php`).
// Comparing the raw `plugin_basename()` against the REST
// field always missed by exactly four characters, which
// silently skipped the self-deactivate reload.
'selfPluginFile' => substr( plugin_basename( OPENSTATION_FILE ), 0, -4 ),
// The wp-admin root URL — the JS navigates here after a
// self-deactivate so the user lands on the classic
// Dashboard rather than reloading their current URL
// (which might be a deactivated plugin's `?page=…` route
// that now 403s).
'adminUrl' => esc_url_raw( admin_url() ),
),
);
/**
* Filter the args used to register the native Plugins window.
*
* @param array $window_args Args passed to `openstation_register_window()`.
*/
$window_args = (array) apply_filters( 'openstation_plugins_window_args', $window_args );
$registered = openstation_register_window( 'desktop-mode-plugins', $window_args );
if ( is_wp_error( $registered ) ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
error_log( '[openstation] Native Plugins window registration failed: ' . $registered->get_error_message() );
}
}
add_action( 'init', 'openstation_plugins_window_register_window', 20 );