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

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