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

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