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 / permissions.php

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

173 lines 6.5 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: capability gates.
4 *
5 * Multi-tier gating, parallel to WordPress core's `plugins.php` flow:
6 *
7 * - `activate_plugins` → REGISTER the window (the broad gate).
8 * Cap-only check; the opt-in toggle is JS-side.
9 * - `install_plugins` → Browse tab + install/upload (JS hides the
10 * tab; AJAX routes re-validate).
11 * - `delete_plugins` → bulk-delete + per-row delete action.
12 * - `upload_plugins` → .zip upload (file or drag-drop).
13 *
14 * UI-side gating is purely UX polish — the AJAX routes in `ajax.php`
15 * re-validate every cap before mutating anything.
16 *
17 * @package OpenStation
18 */
19
20 defined( 'ABSPATH' ) || exit;
21
22 /**
23 * Whether the user is eligible to have the Plugins window registered.
24 *
25 * Cap-only check — the opt-in toggle is a runtime, JS-side gate. A
26 * user who toggles the setting on AFTER load needs the window
27 * already registered for the JS-side remap to find it.
28 *
29 * @param int|null $user_id Optional. Defaults to `get_current_user_id()`.
30 * @return bool
31 */
32 function openstation_plugins_window_user_can_register( $user_id = null ) {
33 $user_id = null === $user_id ? get_current_user_id() : (int) $user_id;
34 $can = $user_id > 0 && user_can( $user_id, 'activate_plugins' );
35
36 /**
37 * Filter whether the current user can have the Plugins window
38 * registered. This is the boot-time check; runtime "should the
39 * dock click use the native window?" is the JS-side
40 * `nativePluginsEnabled` flag.
41 *
42 * @param bool $can Default: `activate_plugins` capability.
43 * @param int $user_id User being checked.
44 */
45 return (bool) apply_filters(
46 'openstation_plugins_window_user_can_register',
47 $can,
48 $user_id
49 );
50 }
51
52 /**
53 * Combined cap-and-opt-in check. Used by callers that want the
54 * combined answer (e.g. analytics, an arrange-menu entry).
55 *
56 * @param int|null $user_id Optional.
57 * @return bool
58 */
59 function openstation_plugins_window_user_can_use( $user_id = null ) {
60 $user_id = null === $user_id ? get_current_user_id() : (int) $user_id;
61
62 $cap_ok = openstation_plugins_window_user_can_register( $user_id );
63
64 $opt_in = false;
65 if ( $cap_ok && function_exists( 'openstation_get_os_settings' ) ) {
66 $settings = openstation_get_os_settings( $user_id );
67 $opt_in = ! empty( $settings['nativePluginsEnabled'] );
68 }
69
70 $can = $cap_ok && $opt_in;
71
72 /**
73 * Filter whether the current user has opted into the native
74 * Plugins experience.
75 *
76 * @param bool $can Default gate result.
77 * @param int $user_id User being checked.
78 */
79 return (bool) apply_filters( 'openstation_plugins_window_user_can_use', $can, $user_id );
80 }
81
82 /**
83 * Capability flags surfaced to the JS bundle so the UI can hide
84 * actions the viewer can't perform. Server still re-validates every
85 * mutation, so a tampered flag here changes nothing security-wise.
86 *
87 * @param int|null $user_id Optional.
88 * @return array{install:bool,delete:bool,upload:bool,activate:bool,update:bool}
89 */
90 function openstation_plugins_window_caps( $user_id = null ) {
91 $user_id = null === $user_id ? get_current_user_id() : (int) $user_id;
92
93 return array(
94 'activate' => $user_id > 0 && user_can( $user_id, 'activate_plugins' ),
95 'install' => $user_id > 0 && user_can( $user_id, 'install_plugins' ),
96 'delete' => $user_id > 0 && user_can( $user_id, 'delete_plugins' ),
97 'upload' => $user_id > 0 && user_can( $user_id, 'upload_plugins' ),
98 // Mirrors Core's `current_user_can( 'update_plugins' )` gate on
99 // the inline "Update now" link in `wp_plugin_update_row()` — the
100 // JS uses it to hide the Update action for editors / non-admin
101 // roles even when `openstation_update_available.available` is
102 // true. Server-side, `wp_ajax_update_plugin` re-checks the cap.
103 'update' => $user_id > 0 && user_can( $user_id, 'update_plugins' ),
104 );
105 }
106
107 /**
108 * Whether the Plugins window should surface an "Automatic Updates"
109 * column at all.
110 *
111 * Mirrors Core's `WP_Plugins_List_Table::__construct()` gate:
112 *
113 * $this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'plugin' )
114 * && current_user_can( 'update_plugins' )
115 * && ( ! is_multisite() || $this->screen->in_admin( 'network' ) );
116 *
117 * `wp_is_auto_update_enabled_for_type()` lives in
118 * `wp-admin/includes/update.php`. On admin requests `init` fires
119 * INSIDE `wp-load.php`, BEFORE `wp-admin/admin.php` requires its
120 * includes — so by the time native windows register their config on
121 * `init` priority 20, the helper isn't loaded yet. We lazy-require
122 * it from this gate so the config blob always reflects the true
123 * state. (The check is gated by `is_admin()` so REST / front-end
124 * requests don't pay the cost.)
125 *
126 * On multisite, only network admins can toggle plugin auto-updates —
127 * Core gates the column on the network screen specifically, but we
128 * use the `manage_network_plugins` capability as the user-facing
129 * equivalent (true for super admins, false for everyone else).
130 *
131 * @param int|null $user_id Optional. Defaults to `get_current_user_id()`.
132 * @return bool
133 */
134 function openstation_plugins_window_auto_updates_enabled( $user_id = null ) {
135 $user_id = null === $user_id ? get_current_user_id() : (int) $user_id;
136
137 $enabled = false;
138 if ( $user_id > 0 && user_can( $user_id, 'update_plugins' ) ) {
139 // Lazy-require Core's admin update helper if it hasn't been
140 // loaded yet. Same posture `wp_ajax_install_plugin` uses for
141 // `plugins_api()` — admin-side files are safe to load when
142 // we're in admin context. We guard with `is_admin()` so REST
143 // / front-end requests don't pull in admin includes.
144 if ( ! function_exists( 'wp_is_auto_update_enabled_for_type' ) && is_admin() ) {
145 require_once ABSPATH . 'wp-admin/includes/update.php';
146 }
147 if (
148 function_exists( 'wp_is_auto_update_enabled_for_type' )
149 && wp_is_auto_update_enabled_for_type( 'plugin' )
150 ) {
151 if ( is_multisite() ) {
152 // Network-only — match Core's `screen->in_admin( 'network' )`
153 // gate as closely as we can outside a screen context.
154 $enabled = user_can( $user_id, 'manage_network_plugins' );
155 } else {
156 $enabled = true;
157 }
158 }
159 }
160
161 /**
162 * Filter whether the Plugins window's "Automatic Updates" column
163 * should be shown to the current user. Return `false` to hide the
164 * column entirely (Core hides it when the auto-update subsystem is
165 * disabled or when the viewer isn't on a network admin screen on
166 * multisite).
167 *
168 * @param bool $enabled Default gate result.
169 * @param int $user_id User being checked.
170 */
171 return (bool) apply_filters( 'openstation_plugins_window_auto_updates_enabled', $enabled, $user_id );
172 }
173