PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.9
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.9
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 0.8.6 All 33 releases
desktop-mode / includes / multisite.php

multisite.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 1.1.9, at includes/multisite.php

271 lines 9.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OpenStation — Multisite integration: the shell's multisite block (which
4 * instance this shell is, the sites the user may switch to, the network
5 * admin menu mirroring the admin bar's Network Admin node — every URL a
6 * link OUT, never a window source, see docs/multisite.md), and the
7 * per-site table cleanup when a subsite is deleted.
8 *
9 * @package OpenStation
10 */
11
12 defined( 'ABSPATH' ) || exit;
13
14 /**
15 * How many of the network's sites a super admin's switcher lists beyond
16 * their own: the network Sites screen's first page. A row, not a
17 * directory — a larger network picks its set through the filter below.
18 */
19 const OPENSTATION_MULTISITE_SWITCHER_SITES = 20;
20
21 /**
22 * The multisite block of the shell config.
23 *
24 * On a network every site is its own OpenStation, and so is the network
25 * admin: the block says which instance this shell is, lists every site
26 * the user may switch to (the overview's site switcher), and carries
27 * the Network Admin tile's rows. On a single-site install the block
28 * comes from the OpenStation network the site belongs to, or is the
29 * hub of (`includes/network/`), and is null outside one. `networkAdmin`
30 * is null for users who cannot reach the network admin, which is what
31 * keeps the tile from registering.
32 *
33 * @return array|null
34 */
35 function openstation_multisite_payload() {
36 if ( ! is_user_logged_in() ) {
37 return null;
38 }
39 if ( ! is_multisite() ) {
40 // A single site has a switcher only as a hub or member of an
41 // OpenStation network, and only while that module is on.
42 if ( ! openstation_network_on() ) {
43 return null;
44 }
45 $member = openstation_network_member_payload();
46 return openstation_multisite_with_hop( null !== $member ? $member : openstation_network_hub_payload() );
47 }
48
49 $network_admin = null;
50 if ( current_user_can( 'manage_network' ) ) {
51 $network_admin = array(
52 'url' => esc_url_raw( network_admin_url() ),
53 'shellUrl' => esc_url_raw( network_admin_url( 'admin.php?page=' . OPENSTATION_SHELL_PAGE_SLUG ) ),
54 'rows' => openstation_multisite_network_admin_rows(),
55 'foreign' => false,
56 );
57 }
58
59 return openstation_multisite_with_hop(
60 array(
61 'isNetworkAdmin' => is_network_admin(),
62 'networkAdmin' => $network_admin,
63 'current' => is_network_admin() ? 'network' : (string) get_current_blog_id(),
64 'sites' => openstation_multisite_sites(),
65 )
66 );
67 }
68
69 /**
70 * The mint route for hop tokens, on any block that has somewhere to
71 * hop to. See `includes/network/hop.php`.
72 *
73 * @param array|null $block The multisite block.
74 * @return array|null
75 */
76 function openstation_multisite_with_hop( $block ) {
77 if ( is_array( $block ) && openstation_network_on() ) {
78 $block['hopUrl'] = esc_url_raw( rest_url( 'desktop-mode/v1/network/hop' ) );
79 }
80 return $block;
81 }
82
83 /**
84 * Whether the OpenStation Network module is on, from anywhere that
85 * runs whether or not it loaded. The bootstrap always loads; the
86 * module does not.
87 *
88 * @return bool
89 */
90 function openstation_network_on() {
91 return function_exists( 'openstation_network_enabled' ) && openstation_network_enabled();
92 }
93
94 /**
95 * The Network Admin tile's rows: the network dashboard and the screens
96 * the admin bar's Network Admin node offers, with its capability gates
97 * copied one for one so the tile can never offer a screen the admin
98 * bar would have hidden.
99 *
100 * @param bool $all Every row regardless of the current user — for the
101 * list served to a network's members, whose users the
102 * hub gates on arrival instead.
103 * @return array<int,array{title:string,url:string}>
104 */
105 function openstation_multisite_network_admin_rows( $all = false ) {
106 $rows = array(
107 array(
108 'title' => __( 'Dashboard', 'desktop-mode' ),
109 'url' => esc_url_raw( network_admin_url() ),
110 ),
111 );
112 $gated = array(
113 'manage_sites' => array( 'sites.php', __( 'Sites', 'desktop-mode' ) ),
114 'manage_network_users' => array( 'users.php', __( 'Users', 'desktop-mode' ) ),
115 'manage_network_themes' => array( 'themes.php', __( 'Themes', 'desktop-mode' ) ),
116 'manage_network_plugins' => array( 'plugins.php', __( 'Plugins', 'desktop-mode' ) ),
117 'manage_network_options' => array( 'settings.php', __( 'Settings', 'desktop-mode' ) ),
118 );
119 foreach ( $gated as $capability => $row ) {
120 if ( $all || current_user_can( $capability ) ) {
121 $rows[] = array(
122 'title' => $row[1],
123 'url' => esc_url_raw( network_admin_url( $row[0] ) ),
124 );
125 }
126 }
127 return $rows;
128 }
129
130 /**
131 * The network's sites by path, up to {@see OPENSTATION_MULTISITE_SWITCHER_SITES},
132 * minus the archived, spam and deleted.
133 *
134 * @return array<int,string> Site names keyed by blog id.
135 */
136 function openstation_multisite_network_sites() {
137 $names = array();
138 $sites = get_sites(
139 array(
140 'number' => OPENSTATION_MULTISITE_SWITCHER_SITES,
141 'archived' => 0,
142 'spam' => 0,
143 'deleted' => 0,
144 'orderby' => 'path',
145 'order' => 'ASC',
146 )
147 );
148 foreach ( $sites as $site ) {
149 $names[ (int) $site->blog_id ] = (string) $site->blogname;
150 }
151 return $names;
152 }
153
154 /**
155 * The sites the user may switch to, each with its own shell screen.
156 *
157 * The user's own sites first — `get_blogs_of_user()`, the list behind
158 * the admin bar's My Sites, minus the archived, spam and deleted, in
159 * the order Core keeps them — then, for a super admin, who can reach
160 * every site whether or not they are a member, the network's sites by
161 * path up to {@see OPENSTATION_MULTISITE_SWITCHER_SITES}; then the
162 * members of the OpenStation network this install is the hub of.
163 *
164 * @return array[] Each `id` (the blog id, or `member:<id>`), `name`, `shellUrl`.
165 */
166 function openstation_multisite_sites() {
167 $names = array();
168 foreach ( get_blogs_of_user( get_current_user_id() ) as $blog ) {
169 $names[ (int) $blog->userblog_id ] = (string) $blog->blogname;
170 }
171 if ( current_user_can( 'manage_network' ) ) {
172 foreach ( openstation_multisite_network_sites() as $blog_id => $name ) {
173 if ( ! isset( $names[ $blog_id ] ) ) {
174 $names[ $blog_id ] = $name;
175 }
176 }
177 }
178
179 $sites = array();
180 foreach ( $names as $blog_id => $name ) {
181 $sites[] = array(
182 'id' => (string) $blog_id,
183 'name' => $name,
184 'shellUrl' => esc_url_raw( get_admin_url( $blog_id, 'admin.php?page=' . OPENSTATION_SHELL_PAGE_SLUG ) ),
185 'kind' => 'local',
186 'foreign' => false,
187 );
188 }
189 foreach ( openstation_network_on() ? openstation_network_member_entries() : array() as $member ) {
190 $sites[] = array(
191 'id' => $member['id'],
192 'name' => $member['name'],
193 'shellUrl' => $member['shellUrl'],
194 'kind' => 'member',
195 'foreign' => true,
196 );
197 }
198
199 /**
200 * Filters the sites the overview's site switcher offers.
201 *
202 * Trim it on a large network, reorder it, rename an entry, or build
203 * a different set. A site dropped here is not offered, though the
204 * admin bar still reaches it.
205 *
206 * @param array[] $sites Each `id` (blog id as a string, or `member:<id>`), `name`, `shellUrl`,
207 * `kind` (`local` for a site of this network, `member` for an install
208 * that joined from elsewhere, which the switcher marks as external),
209 * `foreign` (whether the entry is another install, which a switch to
210 * it needs a login token for).
211 */
212 return apply_filters( 'openstation_multisite_sites', $sites );
213 }
214
215 /**
216 * The plugin's per-site tables, unprefixed.
217 *
218 * A STATIC list, not a read from the schema helpers, on purpose:
219 * deleting a site must drop every table the plugin ever created there,
220 * and the games module (owner of the last two) only loads while its
221 * feature toggle is on — its helper may not exist on the request that
222 * deletes the site, but the tables it created earlier still do. The
223 * names are frozen identifiers (see AGENTS.md), and
224 * `Tests_OpenStation_Multisite` pins this list against the loaded
225 * schema helpers so a new table cannot be forgotten here.
226 *
227 * @return string[] Table names without any prefix.
228 */
229 function openstation_site_table_names() {
230 return array(
231 'desktop_mode_file_placements',
232 'desktop_mode_folders',
233 'desktop_mode_file_tombstones',
234 'desktop_mode_folder_shares',
235 'desktop_mode_share_user_decisions',
236 'desktop_mode_stored_files',
237 'desktop_mode_game_scores',
238 'desktop_mode_game_challenges',
239 'openstation_presence',
240 );
241 }
242
243 /**
244 * Adds the plugin's tables to the set Core drops when a site is
245 * deleted. Without this, every deleted subsite left its
246 * `wp_N_desktop_mode_*` tables behind forever.
247 *
248 * Core drops with `DROP TABLE IF EXISTS`, so listing a table the site
249 * never created (games disabled, or a site deleted before its lazy
250 * `init` table creation ran) is fine.
251 *
252 * @param string[] $tables Table names Core will drop.
253 * @param int $site_id The site being deleted.
254 * @return string[] The list with the plugin's tables appended.
255 */
256 function openstation_filter_wpmu_drop_tables( $tables, $site_id ) {
257 global $wpdb;
258
259 // Core switches to the deleted site before applying the filter,
260 // but the prefix is anchored on the passed id rather than trusted
261 // from the switch — a future caller that forgets to switch would
262 // otherwise drop the CURRENT site's tables.
263 $prefix = $wpdb->get_blog_prefix( $site_id );
264 foreach ( openstation_site_table_names() as $name ) {
265 $tables[] = $prefix . $name;
266 }
267
268 return $tables;
269 }
270 add_filter( 'wpmu_drop_tables', 'openstation_filter_wpmu_drop_tables', 10, 2 );
271