PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.5
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.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 0.9.5, at includes/plugins-window/permissions.php

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