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

197 lines 8.7 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.7
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.7' );
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/os-settings.php';
48 require_once DESKTOP_MODE_DIR . 'includes/seen-intros.php';
49 require_once DESKTOP_MODE_DIR . 'includes/welcome-dialog.php';
50 require_once DESKTOP_MODE_DIR . 'includes/portal.php';
51 require_once DESKTOP_MODE_DIR . 'includes/default-window.php';
52 require_once DESKTOP_MODE_DIR . 'includes/themes-tabs.php';
53 require_once DESKTOP_MODE_DIR . 'includes/media-query.php';
54 require_once DESKTOP_MODE_DIR . 'includes/accents.php';
55 require_once DESKTOP_MODE_DIR . 'includes/toast-types.php';
56 require_once DESKTOP_MODE_DIR . 'includes/registries/native-windows.php';
57 require_once DESKTOP_MODE_DIR . 'includes/registries/window-tabs.php';
58 require_once DESKTOP_MODE_DIR . 'includes/registries/icons.php';
59 require_once DESKTOP_MODE_DIR . 'includes/registries/wallpapers.php';
60 require_once DESKTOP_MODE_DIR . 'includes/registries/widgets.php';
61 require_once DESKTOP_MODE_DIR . 'includes/components.php';
62 require_once DESKTOP_MODE_DIR . 'includes/commands.php';
63 require_once DESKTOP_MODE_DIR . 'includes/settings-tabs.php';
64 require_once DESKTOP_MODE_DIR . 'includes/dock-rail-renderer.php';
65 require_once DESKTOP_MODE_DIR . 'includes/title-bar-buttons.php';
66 require_once DESKTOP_MODE_DIR . 'includes/window-chrome.php';
67 require_once DESKTOP_MODE_DIR . 'includes/window-notices.php';
68 require_once DESKTOP_MODE_DIR . 'includes/wallpapers.php';
69 require_once DESKTOP_MODE_DIR . 'includes/widgets/heartbeat.php';
70 require_once DESKTOP_MODE_DIR . 'includes/render.php';
71 require_once DESKTOP_MODE_DIR . 'includes/extended-options.php';
72 require_once DESKTOP_MODE_DIR . 'includes/oauth-relay.php';
73 require_once DESKTOP_MODE_DIR . 'includes/devtools.php';
74 require_once DESKTOP_MODE_DIR . 'includes/ai-copilot/bootstrap.php';
75 require_once DESKTOP_MODE_DIR . 'includes/recycle-bin/bootstrap.php';
76 require_once DESKTOP_MODE_DIR . 'includes/desktop-files/bootstrap.php';
77 require_once DESKTOP_MODE_DIR . 'includes/posts-window/bootstrap.php';
78 require_once DESKTOP_MODE_DIR . 'includes/pages-window/bootstrap.php';
79 require_once DESKTOP_MODE_DIR . 'includes/users-window/bootstrap.php';
80 require_once DESKTOP_MODE_DIR . 'includes/user-edit-window/bootstrap.php';
81 require_once DESKTOP_MODE_DIR . 'includes/plugins-window/bootstrap.php';
82 require_once DESKTOP_MODE_DIR . 'includes/comments-window/bootstrap.php';
83 require_once DESKTOP_MODE_DIR . 'includes/my-wordpress/bootstrap.php';
84 require_once DESKTOP_MODE_DIR . 'includes/content-graph/bootstrap.php';
85 require_once DESKTOP_MODE_DIR . 'includes/pwa.php';
86 require_once DESKTOP_MODE_DIR . 'includes/compat/divi.php';
87
88 /**
89 * Cascade-deactivate plugins that declare `Requires Plugins: desktop-mode`
90 * when Desktop Mode itself is being deactivated.
91 *
92 * Without this, a third-party plugin like `wp-desktop-messages` keeps
93 * its `init` hook armed after Desktop Mode is turned off — the next
94 * admin page load fires `init`, the hook calls
95 * `desktop_mode_register_window()`, and the request fatals because the
96 * function lives in the plugin we just deactivated. The user lands on
97 * a white screen instead of the classic admin we redirected them to.
98 *
99 * WordPress's plugin dependency feature (6.5+) blocks ACTIVATION of a
100 * plugin whose declared `Requires Plugins` aren't all active, but it
101 * does NOT auto-deactivate dependents when their requirement is
102 * deactivated through any path — the user is expected to do that
103 * themselves. The classic plugins.php list shows a warning; the REST
104 * controller (`PUT /wp/v2/plugins/desktop-mode/desktop-mode`) we route
105 * through has no such gate. So we cascade ourselves.
106 *
107 * Timing: `deactivate_plugins()` writes `active_plugins` to the DB
108 * AFTER its hook loop finishes. If we call `deactivate_plugins()`
109 * from inside our `register_deactivation_hook` callback, our nested
110 * write-back is overwritten the moment the outer call runs its own
111 * `update_option`. So we register the cascade to fire on
112 * `shutdown` — by then the outer `deactivate_plugins` has finished
113 * and our write-back sticks.
114 *
115 * Matching uses `WP_Plugin_Dependencies::get_dependents()` keyed on
116 * our own directory slug (`dirname( plugin_basename( __FILE__ ) )`),
117 * which is the same string the dependent's `Requires Plugins` header
118 * resolves against. The filter below lets sites widen or narrow the
119 * cascade — e.g. add a plugin that wraps `desktop_mode_*` calls in
120 * `function_exists` guards and shouldn't be torn down with us.
121 *
122 * Silent deactivation (`$silent = true`) skips the dependent
123 * plugins' own deactivation hooks. Those callbacks routinely call
124 * `desktop_mode_*` helpers expecting Desktop Mode to be wired up;
125 * firing them mid-cascade can trigger the same fatal we're trying
126 * to prevent. Skipping them is the safer default.
127 *
128 * @since 0.18.4
129 */
130 function desktop_mode_cascade_deactivate_dependents() {
131 // Defer to `shutdown` so we run AFTER the outer
132 // `deactivate_plugins()` has flushed its own option update.
133 // Inline cascade gets clobbered by the outer's write-back.
134 add_action( 'shutdown', 'desktop_mode_do_cascade_deactivate', 0 );
135 }
136 register_deactivation_hook( DESKTOP_MODE_FILE, 'desktop_mode_cascade_deactivate_dependents' );
137
138 /**
139 * The deferred cascade body — runs on `shutdown` after the
140 * outer `deactivate_plugins()` has persisted its update.
141 *
142 * Split out from the `register_deactivation_hook` callback because
143 * that callback must register, not execute, the cascade. See
144 * {@see desktop_mode_cascade_deactivate_dependents} for the timing
145 * rationale.
146 *
147 * @since 0.18.4
148 */
149 function desktop_mode_do_cascade_deactivate() {
150 if ( ! class_exists( 'WP_Plugin_Dependencies' ) ) {
151 // Pre-6.5 — no native dependency tracking. Sites running an
152 // old Core won't have dependents declared via the header
153 // either; nothing to cascade.
154 return;
155 }
156
157 WP_Plugin_Dependencies::initialize();
158
159 $slug = dirname( plugin_basename( DESKTOP_MODE_FILE ) );
160 if ( '' === $slug || '.' === $slug ) {
161 return;
162 }
163
164 $dependents = (array) WP_Plugin_Dependencies::get_dependents( $slug );
165
166 /**
167 * Filter the list of plugin files to cascade-deactivate when
168 * Desktop Mode is deactivated. Defaults to every plugin whose
169 * `Requires Plugins` header lists our directory slug.
170 *
171 * @since 0.18.4
172 *
173 * @param string[] $dependents Plugin files (e.g. "foo/foo.php").
174 * @param string $slug Desktop Mode's directory slug.
175 */
176 $dependents = (array) apply_filters(
177 'desktop_mode_cascade_deactivate_dependents',
178 $dependents,
179 $slug
180 );
181
182 if ( empty( $dependents ) ) {
183 return;
184 }
185
186 $active = (array) get_option( 'active_plugins', array() );
187 $targets = array_values( array_intersect( $active, $dependents ) );
188 if ( empty( $targets ) ) {
189 return;
190 }
191
192 if ( ! function_exists( 'deactivate_plugins' ) ) {
193 require_once ABSPATH . 'wp-admin/includes/plugin.php';
194 }
195 deactivate_plugins( $targets, true );
196 }
197