PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.8.8
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.8.8
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 / desktop-mode.php

desktop-mode.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.8.8, at desktop-mode.php

198 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Desktop Mode
4 * Plugin URI: https://github.com/WordPress/desktop-mode
5 * Description: Renders the WordPress admin as a desktop OS. Admin screens become draggable, resizable, minimizable windows floating on a desktop with a dock. Purely opt-in per user.
6 * Version: 0.8.8
7 * Requires at least: 6.0
8 * Requires PHP: 7.4
9 * Author: Daniel López Sánchez
10 * Author URI: https://github.com/allterraindeveloper
11 * License: GPLv2 or later
12 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
13 * Text Domain: desktop-mode
14 *
15 * @package WPDesktopMode
16 */
17
18 defined( 'ABSPATH' ) || exit;
19
20 define( 'DESKTOP_MODE_VERSION', '0.8.8' );
21 define( 'DESKTOP_MODE_FILE', __FILE__ );
22 define( 'DESKTOP_MODE_DIR', plugin_dir_path( __FILE__ ) );
23 define( 'DESKTOP_MODE_URL', plugin_dir_url( __FILE__ ) );
24
25 // Foundation primitives — must load before anything that consumes them.
26 require_once DESKTOP_MODE_DIR . 'includes/core/registry-factory.php';
27
28 // Routing helpers register filters at file-load time but call
29 // chromeless / classic detection helpers (still in helpers.php)
30 // at hook-fire time — both files load before any hook fires, so
31 // the order is strict-but-flexible. Routing first because it is
32 // the smaller, more isolated piece.
33 require_once DESKTOP_MODE_DIR . 'includes/core/routing.php';
34
35 require_once DESKTOP_MODE_DIR . 'includes/helpers.php';
36
37 // Dock + payload assembly. Loaded right after helpers.php so the
38 // foundational `desktop_mode_is_enabled()` etc. exist by the time
39 // any payload function is invoked at hook-fire time.
40 require_once DESKTOP_MODE_DIR . 'includes/core/payload.php';
41 require_once DESKTOP_MODE_DIR . 'includes/ajax.php';
42 require_once DESKTOP_MODE_DIR . 'includes/assets.php';
43 require_once DESKTOP_MODE_DIR . 'includes/admin-bar.php';
44 require_once DESKTOP_MODE_DIR . 'includes/session.php';
45 require_once DESKTOP_MODE_DIR . 'includes/presence.php';
46 require_once DESKTOP_MODE_DIR . 'includes/nonce-refresh.php';
47 require_once DESKTOP_MODE_DIR . 'includes/sticky-notes/heartbeat.php';
48 require_once DESKTOP_MODE_DIR . 'includes/os-settings.php';
49 require_once DESKTOP_MODE_DIR . 'includes/seen-intros.php';
50 require_once DESKTOP_MODE_DIR . 'includes/welcome-dialog.php';
51 require_once DESKTOP_MODE_DIR . 'includes/portal.php';
52 require_once DESKTOP_MODE_DIR . 'includes/default-window.php';
53 require_once DESKTOP_MODE_DIR . 'includes/themes-tabs.php';
54 require_once DESKTOP_MODE_DIR . 'includes/media-query.php';
55 require_once DESKTOP_MODE_DIR . 'includes/accents.php';
56 require_once DESKTOP_MODE_DIR . 'includes/toast-types.php';
57 require_once DESKTOP_MODE_DIR . 'includes/registries/native-windows.php';
58 require_once DESKTOP_MODE_DIR . 'includes/registries/window-tabs.php';
59 require_once DESKTOP_MODE_DIR . 'includes/registries/icons.php';
60 require_once DESKTOP_MODE_DIR . 'includes/registries/wallpapers.php';
61 require_once DESKTOP_MODE_DIR . 'includes/registries/widgets.php';
62 require_once DESKTOP_MODE_DIR . 'includes/components.php';
63 require_once DESKTOP_MODE_DIR . 'includes/commands.php';
64 require_once DESKTOP_MODE_DIR . 'includes/settings-tabs.php';
65 require_once DESKTOP_MODE_DIR . 'includes/dock-rail-renderer.php';
66 require_once DESKTOP_MODE_DIR . 'includes/title-bar-buttons.php';
67 require_once DESKTOP_MODE_DIR . 'includes/window-chrome.php';
68 require_once DESKTOP_MODE_DIR . 'includes/window-notices.php';
69 require_once DESKTOP_MODE_DIR . 'includes/wallpapers.php';
70 require_once DESKTOP_MODE_DIR . 'includes/widgets/heartbeat.php';
71 require_once DESKTOP_MODE_DIR . 'includes/render.php';
72 require_once DESKTOP_MODE_DIR . 'includes/extended-options.php';
73 require_once DESKTOP_MODE_DIR . 'includes/oauth-relay.php';
74 require_once DESKTOP_MODE_DIR . 'includes/devtools.php';
75 require_once DESKTOP_MODE_DIR . 'includes/ai-copilot/bootstrap.php';
76 require_once DESKTOP_MODE_DIR . 'includes/recycle-bin/bootstrap.php';
77 require_once DESKTOP_MODE_DIR . 'includes/desktop-files/bootstrap.php';
78 require_once DESKTOP_MODE_DIR . 'includes/posts-window/bootstrap.php';
79 require_once DESKTOP_MODE_DIR . 'includes/pages-window/bootstrap.php';
80 require_once DESKTOP_MODE_DIR . 'includes/users-window/bootstrap.php';
81 require_once DESKTOP_MODE_DIR . 'includes/user-edit-window/bootstrap.php';
82 require_once DESKTOP_MODE_DIR . 'includes/plugins-window/bootstrap.php';
83 require_once DESKTOP_MODE_DIR . 'includes/comments-window/bootstrap.php';
84 require_once DESKTOP_MODE_DIR . 'includes/my-wordpress/bootstrap.php';
85 require_once DESKTOP_MODE_DIR . 'includes/content-graph/bootstrap.php';
86 require_once DESKTOP_MODE_DIR . 'includes/pwa.php';
87 require_once DESKTOP_MODE_DIR . 'includes/compat/divi.php';
88
89 /**
90 * Cascade-deactivate plugins that declare `Requires Plugins: desktop-mode`
91 * when Desktop Mode itself is being deactivated.
92 *
93 * Without this, a third-party plugin like `wp-desktop-messages` keeps
94 * its `init` hook armed after Desktop Mode is turned off — the next
95 * admin page load fires `init`, the hook calls
96 * `desktop_mode_register_window()`, and the request fatals because the
97 * function lives in the plugin we just deactivated. The user lands on
98 * a white screen instead of the classic admin we redirected them to.
99 *
100 * WordPress's plugin dependency feature (6.5+) blocks ACTIVATION of a
101 * plugin whose declared `Requires Plugins` aren't all active, but it
102 * does NOT auto-deactivate dependents when their requirement is
103 * deactivated through any path — the user is expected to do that
104 * themselves. The classic plugins.php list shows a warning; the REST
105 * controller (`PUT /wp/v2/plugins/desktop-mode/desktop-mode`) we route
106 * through has no such gate. So we cascade ourselves.
107 *
108 * Timing: `deactivate_plugins()` writes `active_plugins` to the DB
109 * AFTER its hook loop finishes. If we call `deactivate_plugins()`
110 * from inside our `register_deactivation_hook` callback, our nested
111 * write-back is overwritten the moment the outer call runs its own
112 * `update_option`. So we register the cascade to fire on
113 * `shutdown` — by then the outer `deactivate_plugins` has finished
114 * and our write-back sticks.
115 *
116 * Matching uses `WP_Plugin_Dependencies::get_dependents()` keyed on
117 * our own directory slug (`dirname( plugin_basename( __FILE__ ) )`),
118 * which is the same string the dependent's `Requires Plugins` header
119 * resolves against. The filter below lets sites widen or narrow the
120 * cascade — e.g. add a plugin that wraps `desktop_mode_*` calls in
121 * `function_exists` guards and shouldn't be torn down with us.
122 *
123 * Silent deactivation (`$silent = true`) skips the dependent
124 * plugins' own deactivation hooks. Those callbacks routinely call
125 * `desktop_mode_*` helpers expecting Desktop Mode to be wired up;
126 * firing them mid-cascade can trigger the same fatal we're trying
127 * to prevent. Skipping them is the safer default.
128 *
129 * @since 0.18.4
130 */
131 function desktop_mode_cascade_deactivate_dependents() {
132 // Defer to `shutdown` so we run AFTER the outer
133 // `deactivate_plugins()` has flushed its own option update.
134 // Inline cascade gets clobbered by the outer's write-back.
135 add_action( 'shutdown', 'desktop_mode_do_cascade_deactivate', 0 );
136 }
137 register_deactivation_hook( DESKTOP_MODE_FILE, 'desktop_mode_cascade_deactivate_dependents' );
138
139 /**
140 * The deferred cascade body — runs on `shutdown` after the
141 * outer `deactivate_plugins()` has persisted its update.
142 *
143 * Split out from the `register_deactivation_hook` callback because
144 * that callback must register, not execute, the cascade. See
145 * {@see desktop_mode_cascade_deactivate_dependents} for the timing
146 * rationale.
147 *
148 * @since 0.18.4
149 */
150 function desktop_mode_do_cascade_deactivate() {
151 if ( ! class_exists( 'WP_Plugin_Dependencies' ) ) {
152 // Pre-6.5 — no native dependency tracking. Sites running an
153 // old Core won't have dependents declared via the header
154 // either; nothing to cascade.
155 return;
156 }
157
158 WP_Plugin_Dependencies::initialize();
159
160 $slug = dirname( plugin_basename( DESKTOP_MODE_FILE ) );
161 if ( '' === $slug || '.' === $slug ) {
162 return;
163 }
164
165 $dependents = (array) WP_Plugin_Dependencies::get_dependents( $slug );
166
167 /**
168 * Filter the list of plugin files to cascade-deactivate when
169 * Desktop Mode is deactivated. Defaults to every plugin whose
170 * `Requires Plugins` header lists our directory slug.
171 *
172 * @since 0.18.4
173 *
174 * @param string[] $dependents Plugin files (e.g. "foo/foo.php").
175 * @param string $slug Desktop Mode's directory slug.
176 */
177 $dependents = (array) apply_filters(
178 'desktop_mode_cascade_deactivate_dependents',
179 $dependents,
180 $slug
181 );
182
183 if ( empty( $dependents ) ) {
184 return;
185 }
186
187 $active = (array) get_option( 'active_plugins', array() );
188 $targets = array_values( array_intersect( $active, $dependents ) );
189 if ( empty( $targets ) ) {
190 return;
191 }
192
193 if ( ! function_exists( 'deactivate_plugins' ) ) {
194 require_once ABSPATH . 'wp-admin/includes/plugin.php';
195 }
196 deactivate_plugins( $targets, true );
197 }
198