PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.10
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.10
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
← All changes | includes/desktop-files/schema.php +131 -97 0.9.21.1.10 View file →
@@ -1,12 +1,12 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — Files-on-the-Desktop schema.
3 + * OpenStation — Files-on-the-Desktop schema.
4 4 *
5 - * Three custom tables back the system:
5 + * Five custom tables back the system:
6 6 *
7 7 * - `_desktop_mode_file_placements` — every (user, parent_folder,
8 - * type, ref, x, y, sort) tuple. Indexed on `(user_id, parent_id)`
8 + * type, ref, x, y, sort) tuple. Indexed on `(owner_id, parent_id)`
9 9 * and `(file_type, file_ref)` for two queries we run constantly:
10 10 * "show me what's on user X's folder Y" and "where else does
11 11 * this entity appear" (used when an entity is deleted to clean
12 12 * up dangling placements).
@@ -21,36 +21,55 @@
21 21 * - `_desktop_mode_file_tombstones` — id ledger of removals so the
22 22 * Heartbeat delta sync (Phase 6) can tell connected clients
23 23 * "this placement / folder is gone." Pruned daily.
24 24 *
25 + * - `_desktop_mode_folder_shares` — one row per (folder, principal)
26 + * grant: user- or role-principal, `read` | `write` capability,
27 + * `pending` | `accepted` | `denied` state.
28 + *
29 + * - `_desktop_mode_share_user_decisions` — per-user opt-ins for
30 + * role-principal shares (each member of the role accepts or
31 + * denies individually; the shares row itself stays `pending`).
32 + *
25 33 * dbDelta is the only safe path for schema migrations against the
26 34 * Core tables environment — Phase 6 re-uses this file by bumping
27 - * `DESKTOP_MODE_FILES_SCHEMA_VERSION` and adding columns.
35 + * `OPENSTATION_FILES_SCHEMA_VERSION` and adding columns.
28 36 *
29 - * @package WPDesktopMode
30 - * @since 0.9.0
37 + * @package OpenStation
31 38 */
32 39
33 40 defined( 'ABSPATH' ) || exit;
34 41
35 -define( 'DESKTOP_MODE_FILES_SCHEMA_VERSION', '12' );
36 -define( 'DESKTOP_MODE_FILES_SCHEMA_OPTION', 'desktop_mode_files_schema_version' );
42 +define( 'OPENSTATION_FILES_SCHEMA_VERSION', '13' );
43 +/**
44 + * The VALUE keeps its pre-rebrand spelling on purpose: it is a
45 + * persisted or externally-visible identifier, so renaming it would
46 + * orphan data already written by live installs (or break a live
47 + * URL). The mismatch between this constant's name and its value is
48 + * deliberate — it is NOT a half-finished rename.
49 + */
50 +define( 'OPENSTATION_FILES_SCHEMA_OPTION', 'desktop_mode_files_schema_version' );
37 51
38 52 /**
39 53 * Returns the per-table names with the active prefix applied.
40 54 *
41 - * @since 0.9.0
55 + * The `desktop_mode_` segment is the pre-rebrand spelling and is frozen:
56 + * these are real tables holding real rows on live installs. Renaming
57 + * them silently creates a second, empty set and every desktop icon,
58 + * folder and uploaded file disappears. The mismatch against the
59 + * `openstation_*` function name is deliberate.
42 60 *
43 - * @return array{ placements: string, folders: string, tombstones: string }
61 + * @return array{ placements: string, folders: string, tombstones: string, shares: string, decisions: string }
44 62 */
45 -function desktop_mode_files_table_names() {
63 +function openstation_files_table_names() {
46 64 global $wpdb;
47 65 return array(
48 - 'placements' => $wpdb->prefix . 'desktop_mode_file_placements',
49 - 'folders' => $wpdb->prefix . 'desktop_mode_folders',
50 - 'tombstones' => $wpdb->prefix . 'desktop_mode_file_tombstones',
51 - 'shares' => $wpdb->prefix . 'desktop_mode_folder_shares',
52 - 'decisions' => $wpdb->prefix . 'desktop_mode_share_user_decisions',
66 + 'placements' => $wpdb->prefix . 'desktop_mode_file_placements',
67 + 'folders' => $wpdb->prefix . 'desktop_mode_folders',
68 + 'tombstones' => $wpdb->prefix . 'desktop_mode_file_tombstones',
69 + 'shares' => $wpdb->prefix . 'desktop_mode_folder_shares',
70 + 'decisions' => $wpdb->prefix . 'desktop_mode_share_user_decisions',
71 + 'stored_files' => $wpdb->prefix . 'desktop_mode_stored_files',
53 72 );
54 73 }
55 74
56 75 /**
@@ -56,20 +75,18 @@
56 75 /**
57 76 * Idempotent `dbDelta` call. Hooked on plugin activation and on
58 77 * `admin_init` (gated by a version-option mismatch) so a manual
59 78 * file copy install still ends up with the tables.
60 - *
61 - * @since 0.9.0
62 79 */
63 -function desktop_mode_files_install_schema() {
80 +function openstation_files_install_schema() {
64 81 global $wpdb;
65 82
66 83 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
67 84
68 - $tables = desktop_mode_files_table_names();
69 - $charset_collate = $wpdb->get_charset_collate();
85 + $tables = openstation_files_table_names();
86 + $charset_collate = $wpdb->get_charset_collate();
70 87
71 - // Schema v2 (since 0.8.0): adds trash columns to both placements
88 + // Schema v2: adds trash columns to both placements
72 89 // and folders so deleted shortcuts and folders land in the
73 90 // recycle bin instead of vanishing. `trashed_at_ms` is the
74 91 // epoch-ms timestamp of the trash event (NULL = active).
75 92 // `trashed_by` records the user that fired it (for permission
@@ -124,8 +141,32 @@
124 141 PRIMARY KEY (id),
125 142 KEY kind_removed (kind, removed_at_ms)
126 143 ) $charset_collate;";
127 144
145 + // Schema v13: real per-user file storage. One row
146 + // per uploaded file; the bytes live flat on disk under
147 + // `uploads/desktop-mode-files/<owner_id>/<disk_name>` with a
148 + // server-generated extensionless `disk_name` (UUID) — hierarchy,
149 + // naming, and sharing are entirely DB concerns (folders +
150 + // placements + shares tables), the disk is a dumb blob store.
151 + // No UNIQUE keys beyond the PK on purpose: dbDelta's UNIQUE-KEY
152 + // quirks (see the shares-table comment below) don't apply, and
153 + // disk_name uniqueness is guaranteed by the UUID generator plus
154 + // a collision check at write time.
155 + $stored_files_sql = "CREATE TABLE {$tables['stored_files']} (
156 + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
157 + owner_id BIGINT UNSIGNED NOT NULL,
158 + display_name VARCHAR(255) NOT NULL DEFAULT '',
159 + disk_name VARCHAR(64) NOT NULL DEFAULT '',
160 + size_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0,
161 + mime VARCHAR(100) NOT NULL DEFAULT '',
162 + created_at_ms BIGINT UNSIGNED NOT NULL DEFAULT 0,
163 + updated_at_ms BIGINT UNSIGNED NOT NULL DEFAULT 0,
164 + PRIMARY KEY (id),
165 + KEY owner_id (owner_id),
166 + KEY disk_name (disk_name)
167 + ) $charset_collate;";
168 +
128 169 // Schema v9 — per-principal grants (`folder_shares` table) +
129 170 // per-user opt-in decisions (`share_user_decisions` table).
130 171 // `share_meta` on the folders row stays as a diagnostic-only
131 172 // column; visibility is computed entirely from the shares
@@ -153,19 +194,20 @@
153 194 // `owner_id` as a missing column and ADD it (leaving the old
154 195 // `user_id` in place + the new `owner_id` NULL). Running the
155 196 // CHANGE COLUMN first means dbDelta sees the table already
156 197 // matches the desired shape.
157 - desktop_mode_files_rename_user_id_to_owner_id();
198 + openstation_files_rename_user_id_to_owner_id();
158 199
159 200 dbDelta( $placements_sql );
160 201 dbDelta( $folders_sql );
161 202 dbDelta( $tombstones_sql );
203 + dbDelta( $stored_files_sql );
162 204
163 205 // dbDelta has well-documented quirks with `NULL`-only columns
164 206 // (no DEFAULT) — under some MySQL/MariaDB combos it silently
165 207 // skips the ADD COLUMN. Verify the v2 trash columns are
166 208 // physically present and ALTER them in directly when not.
167 - desktop_mode_files_ensure_trash_columns();
209 + openstation_files_ensure_trash_columns();
168 210
169 211 // v4: clean up duplicate placements created by sessions that
170 212 // hit the auto-orphan-placer while the v2 trash columns were
171 213 // missing — every `WHERE trashed_at_ms IS NULL` precheck
@@ -172,15 +214,15 @@
172 214 // returned empty, so each pageload re-inserted every
173 215 // registered shortcut. Collapse runs of identical
174 216 // `(owner_id, parent_id, file_type, file_ref)` rows down to
175 217 // the lowest id.
176 - desktop_mode_files_dedupe_placements();
218 + openstation_files_dedupe_placements();
177 219
178 220 // v5: enforce uniqueness at the DB level so a future bug
179 221 // (or a racing pair of REST requests) can never re-create
180 222 // the duplicate shortcuts again. Must run AFTER dedupe —
181 223 // adding a unique key against duplicate rows would fail.
182 - desktop_mode_files_ensure_unique_placement_index();
224 + openstation_files_ensure_unique_placement_index();
183 225
184 226 // v9: belt-and-suspenders existence check for the shares +
185 227 // decisions tables. The folder-sharing feature is the
186 228 // canonical source of truth for "who can see this folder" —
@@ -186,10 +228,10 @@
186 228 // canonical source of truth for "who can see this folder" —
187 229 // the `share_meta` JSON column on the folders table remains
188 230 // for diagnostic purposes only and is not consulted by the
189 231 // visibility resolver.
190 - desktop_mode_files_ensure_shares_table();
191 - desktop_mode_files_ensure_decisions_table();
232 + openstation_files_ensure_shares_table();
233 + openstation_files_ensure_decisions_table();
192 234
193 235 // v10: `updated_by` column on placements so the If-Match 409
194 236 // conflict toast names the SESSION that actually won the race,
195 237 // not just whoever currently owns the row. Critical for the
@@ -195,20 +237,18 @@
195 237 // not just whoever currently owns the row. Critical for the
196 238 // shared-write scenario where User B (writer recipient) moves a
197 239 // placement and User C gets the conflict — without this column,
198 240 // the toast would blame User A (owner of the row).
199 - desktop_mode_files_ensure_updated_by_column();
241 + openstation_files_ensure_updated_by_column();
200 242
201 - update_option( DESKTOP_MODE_FILES_SCHEMA_OPTION, DESKTOP_MODE_FILES_SCHEMA_VERSION );
243 + update_option( OPENSTATION_FILES_SCHEMA_OPTION, OPENSTATION_FILES_SCHEMA_VERSION );
202 244
203 245 /**
204 246 * Fires after the files schema is installed / migrated.
205 247 *
206 - * @since 0.9.0
207 - *
208 248 * @param string $version The version that was installed.
209 249 */
210 - do_action( 'desktop_mode_files_schema_installed', DESKTOP_MODE_FILES_SCHEMA_VERSION );
250 + do_action( 'openstation_files_schema_installed', OPENSTATION_FILES_SCHEMA_VERSION );
211 251 }
212 252
213 253 /**
214 254 * Belt-and-suspenders verifier for the v2 trash columns. Reads
@@ -215,14 +255,13 @@
215 255 * `INFORMATION_SCHEMA.COLUMNS` for the placements + folders tables
216 256 * and `ALTER`s in any column dbDelta missed. Idempotent: each
217 257 * `ALTER` only fires when the column is not already there.
218 258 *
219 - * @since 0.8.0
220 259 * @internal
221 260 */
222 -function desktop_mode_files_ensure_trash_columns() {
261 +function openstation_files_ensure_trash_columns() {
223 262 global $wpdb;
224 - $tables = desktop_mode_files_table_names();
263 + $tables = openstation_files_table_names();
225 264
226 265 // Two-worker race protection: between the INFORMATION_SCHEMA
227 266 // check and the ALTER, a concurrent worker (cron + admin-init,
228 267 // REST + heartbeat) can run the same check, see the column
@@ -235,12 +274,12 @@
235 274 $ensure = static function ( $table, $column, $definition ) use ( $wpdb ) {
236 275 $col_exists = static function () use ( $wpdb, $table, $column ) {
237 276 return (int) $wpdb->get_var(
238 277 $wpdb->prepare(
239 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
278 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
240 279 WHERE TABLE_SCHEMA = DATABASE()
241 280 AND TABLE_NAME = %s
242 - AND COLUMN_NAME = %s",
281 + AND COLUMN_NAME = %s',
243 282 $table,
244 283 $column
245 284 )
246 285 );
@@ -260,34 +299,38 @@
260 299 $wpdb->query( "ALTER TABLE `{$table}` ADD COLUMN `{$column}` {$definition}" );
261 300 }
262 301 };
263 302
264 - $ensure( $tables['placements'], 'trashed_at_ms', 'BIGINT UNSIGNED NULL' );
265 - $ensure( $tables['placements'], 'trashed_by', 'BIGINT UNSIGNED NULL' );
303 + $ensure( $tables['placements'], 'trashed_at_ms', 'BIGINT UNSIGNED NULL' );
304 + $ensure( $tables['placements'], 'trashed_by', 'BIGINT UNSIGNED NULL' );
266 305 $ensure( $tables['placements'], 'trashed_via_folder', 'BIGINT UNSIGNED NULL' );
267 306 // v6: ancestry snapshot — JSON capturing every folder in the
268 307 // parent chain at trash time so a restore can resurrect the
269 308 // chain even when a folder was hard-deleted in the meantime.
270 - $ensure( $tables['placements'], 'trashed_meta', 'LONGTEXT NULL' );
271 - $ensure( $tables['folders'], 'trashed_at_ms', 'BIGINT UNSIGNED NULL' );
272 - $ensure( $tables['folders'], 'trashed_by', 'BIGINT UNSIGNED NULL' );
273 - $ensure( $tables['folders'], 'trashed_meta', 'LONGTEXT NULL' );
309 + $ensure( $tables['placements'], 'trashed_meta', 'LONGTEXT NULL' );
310 + $ensure( $tables['folders'], 'trashed_at_ms', 'BIGINT UNSIGNED NULL' );
311 + $ensure( $tables['folders'], 'trashed_by', 'BIGINT UNSIGNED NULL' );
312 + $ensure( $tables['folders'], 'trashed_meta', 'LONGTEXT NULL' );
274 313 }
275 314
276 315 /**
277 316 * Collapse duplicate `(owner_id, parent_id, file_type, file_ref)`
278 - * placement rows down to the lowest id, deleting the rest. Only
279 - * meaningful for `file_type IN ('shortcut','folder')` — those are
280 - * the types where two rows for the same ref are redundant. Other
281 - * types (post / page / attachment / …) might legitimately appear
282 - * twice on the same desktop, so the dedupe leaves them alone.
317 + * placement rows down to the lowest id, deleting the rest. The
318 + * DELETE is restricted to `file_type IN ('shortcut','folder')` —
319 + * the types where legacy duplicates were actually observed. Note
320 + * that the v5 `placement_unique` index added right after this
321 + * covers EVERY file type, so duplicates of any type within the
322 + * same (owner, parent) are disallowed at the DB level; if legacy
323 + * duplicates of another type exist, the (error-suppressed)
324 + * `ADD UNIQUE` in
325 + * `openstation_files_ensure_unique_placement_index()` will fail
326 + * and leave the index absent until those rows are cleaned up.
283 327 *
284 - * @since 0.8.0
285 328 * @internal
286 329 */
287 -function desktop_mode_files_dedupe_placements() {
330 +function openstation_files_dedupe_placements() {
288 331 global $wpdb;
289 - $tables = desktop_mode_files_table_names();
332 + $tables = openstation_files_table_names();
290 333 $tbl = $tables['placements'];
291 334
292 335 // Once the unique index exists, MySQL prevents duplicate
293 336 // inserts at the DB level — dedupe is a no-op and the
@@ -295,12 +338,12 @@
295 338 // call. Skip in that case so the cost is paid exactly once,
296 339 // during the v4 → v5 migration.
297 340 $has_unique = (int) $wpdb->get_var(
298 341 $wpdb->prepare(
299 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
342 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
300 343 WHERE TABLE_SCHEMA = DATABASE()
301 344 AND TABLE_NAME = %s
302 - AND INDEX_NAME = %s",
345 + AND INDEX_NAME = %s',
303 346 $tbl,
304 347 'placement_unique'
305 348 )
306 349 );
@@ -334,22 +377,21 @@
334 377 * Note: `file_ref` is `VARCHAR(255)` — combined with the three
335 378 * other columns this fits comfortably under MySQL's 3072-byte
336 379 * InnoDB index-key limit on `utf8mb4`.
337 380 *
338 - * @since 0.8.0
339 381 * @internal
340 382 */
341 -function desktop_mode_files_ensure_unique_placement_index() {
383 +function openstation_files_ensure_unique_placement_index() {
342 384 global $wpdb;
343 - $tables = desktop_mode_files_table_names();
385 + $tables = openstation_files_table_names();
344 386 $tbl = $tables['placements'];
345 387
346 388 $exists = (int) $wpdb->get_var(
347 389 $wpdb->prepare(
348 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
390 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
349 391 WHERE TABLE_SCHEMA = DATABASE()
350 392 AND TABLE_NAME = %s
351 - AND INDEX_NAME = %s",
393 + AND INDEX_NAME = %s',
352 394 $tbl,
353 395 'placement_unique'
354 396 )
355 397 );
@@ -372,9 +414,9 @@
372 414 /**
373 415 * Add the v10 `updated_by` column to the placements table.
374 416 *
375 417 * Tracks which user last mutated the row (created, moved, restored).
376 - * Used by `desktop_mode_files_check_if_match()` so the If-Match 409
418 + * Used by `openstation_files_check_if_match()` so the If-Match 409
377 419 * conflict toast attributes the change to the SESSION that won the
378 420 * race rather than to the row's static owner — critical when a
379 421 * writer recipient of a shared folder rearranges placements and
380 422 * another viewer hits a stale `If-Match`.
@@ -381,21 +423,20 @@
381 423 *
382 424 * NULL on legacy rows (pre-v10). The conflict resolver falls back
383 425 * to `owner_id` when this column is NULL, matching the old behavior.
384 426 *
385 - * @since 0.18.x (schema v10)
386 427 * @internal
387 428 */
388 -function desktop_mode_files_ensure_updated_by_column() {
429 +function openstation_files_ensure_updated_by_column() {
389 430 global $wpdb;
390 - $tables = desktop_mode_files_table_names();
431 + $tables = openstation_files_table_names();
391 432 $tbl = $tables['placements'];
392 433 $exists = (int) $wpdb->get_var(
393 434 $wpdb->prepare(
394 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
435 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
395 436 WHERE TABLE_SCHEMA = DATABASE()
396 437 AND TABLE_NAME = %s
397 - AND COLUMN_NAME = %s",
438 + AND COLUMN_NAME = %s',
398 439 $tbl,
399 440 'updated_by'
400 441 )
401 442 );
@@ -413,9 +454,9 @@
413 454
414 455 /**
415 456 * Rename `placements.user_id` to `placements.owner_id` and the
416 457 * matching `user_parent` index to `owner_parent`. The two
417 - * desktop-mode-owned tables historically used different names for
458 + * os-owned tables historically used different names for
418 459 * the same "row's owner" concept — folders carried `owner_id` from
419 460 * day one, placements carried `user_id`. v11 unifies them so SQL
420 461 * and PHP read identically across the two tables.
421 462 *
@@ -423,9 +464,9 @@
423 464 * dbDelta runs after this and creates the table with the new
424 465 * column name directly) and when the column is already renamed.
425 466 *
426 467 * Must run BEFORE `dbDelta( $placements_sql )` in
427 - * `desktop_mode_files_install_schema()` — dbDelta does NOT rename
468 + * `openstation_files_install_schema()` — dbDelta does NOT rename
428 469 * columns, so against a v≤10 table whose definition says
429 470 * `owner_id` it would ADD a new `owner_id` column and leave the
430 471 * stale `user_id` in place. Running the CHANGE COLUMN first puts
431 472 * the table in the desired shape so dbDelta sees no diff.
@@ -435,14 +476,13 @@
435 476 * partial run during dev iteration) gets a clean retry. The
436 477 * function is idempotent — early-returns when `user_id` is absent,
437 478 * so healthy v11 installs see a cheap no-op on the retry.
438 479 *
439 - * @since 0.22.0 (schema v11, redelivered at v12)
440 480 * @internal
441 481 */
442 -function desktop_mode_files_rename_user_id_to_owner_id() {
482 +function openstation_files_rename_user_id_to_owner_id() {
443 483 global $wpdb;
444 - $tables = desktop_mode_files_table_names();
484 + $tables = openstation_files_table_names();
445 485 $tbl = $tables['placements'];
446 486
447 487 // Fresh install — the table doesn't exist yet; dbDelta creates
448 488 // it with `owner_id` directly. Nothing to migrate.
@@ -447,10 +487,10 @@
447 487 // Fresh install — the table doesn't exist yet; dbDelta creates
448 488 // it with `owner_id` directly. Nothing to migrate.
449 489 $table_exists = (int) $wpdb->get_var(
450 490 $wpdb->prepare(
451 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
452 - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s",
491 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
492 + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
453 493 $tbl
454 494 )
455 495 );
456 496 if ( 0 === $table_exists ) {
@@ -509,22 +549,21 @@
509 549 * declarations on a non-`utf8mb4` collation gets silently skipped
510 550 * on some MySQL/MariaDB combos; we mirror the trash-columns
511 551 * pattern and `CREATE TABLE IF NOT EXISTS` the row explicitly.
512 552 *
513 - * @since 0.18.0
514 553 * @internal
515 554 */
516 -function desktop_mode_files_ensure_shares_table() {
555 +function openstation_files_ensure_shares_table() {
517 556 global $wpdb;
518 - $tables = desktop_mode_files_table_names();
557 + $tables = openstation_files_table_names();
519 558 $charset_collate = $wpdb->get_charset_collate();
520 559 $tbl = $tables['shares'];
521 560
522 561 $exists = (int) $wpdb->get_var(
523 562 $wpdb->prepare(
524 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
563 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
525 564 WHERE TABLE_SCHEMA = DATABASE()
526 - AND TABLE_NAME = %s",
565 + AND TABLE_NAME = %s',
527 566 $tbl
528 567 )
529 568 );
530 569 if ( 0 === $exists ) {
@@ -551,12 +590,12 @@
551 590 // Existing table — make sure `target_type` is there for
552 591 // installs that ran a pre-target_type build of v8.
553 592 $has_col = (int) $wpdb->get_var(
554 593 $wpdb->prepare(
555 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
594 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
556 595 WHERE TABLE_SCHEMA = DATABASE()
557 596 AND TABLE_NAME = %s
558 - AND COLUMN_NAME = %s",
597 + AND COLUMN_NAME = %s',
559 598 $tbl,
560 599 'target_type'
561 600 )
562 601 );
@@ -574,22 +613,21 @@
574 613
575 614 /**
576 615 * Belt-and-suspenders verifier for the decisions table.
577 616 *
578 - * @since 0.18.0
579 617 * @internal
580 618 */
581 -function desktop_mode_files_ensure_decisions_table() {
619 +function openstation_files_ensure_decisions_table() {
582 620 global $wpdb;
583 - $tables = desktop_mode_files_table_names();
621 + $tables = openstation_files_table_names();
584 622 $charset_collate = $wpdb->get_charset_collate();
585 623 $tbl = $tables['decisions'];
586 624
587 625 $exists = (int) $wpdb->get_var(
588 626 $wpdb->prepare(
589 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
627 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
590 628 WHERE TABLE_SCHEMA = DATABASE()
591 - AND TABLE_NAME = %s",
629 + AND TABLE_NAME = %s',
592 630 $tbl
593 631 )
594 632 );
595 633 if ( 0 === $exists ) {
@@ -612,34 +650,30 @@
612 650 /**
613 651 * Lazy migrator — runs on `admin_init` when the stored schema
614 652 * version doesn't match the constant. Idempotent: `dbDelta`
615 653 * itself is a no-op when the table already matches.
616 - *
617 - * @since 0.9.0
618 654 */
619 -function desktop_mode_files_maybe_install_schema() {
620 - $installed = get_option( DESKTOP_MODE_FILES_SCHEMA_OPTION, '' );
621 - if ( $installed === DESKTOP_MODE_FILES_SCHEMA_VERSION ) {
655 +function openstation_files_maybe_install_schema() {
656 + $installed = get_option( OPENSTATION_FILES_SCHEMA_OPTION, '' );
657 + if ( OPENSTATION_FILES_SCHEMA_VERSION === $installed ) {
622 658 return;
623 659 }
624 - desktop_mode_files_install_schema();
660 + openstation_files_install_schema();
625 661 }
626 -add_action( 'admin_init', 'desktop_mode_files_maybe_install_schema' );
662 +add_action( 'admin_init', 'openstation_files_maybe_install_schema' );
627 663 // REST + front-end requests never fire `admin_init` — without these
628 664 // hooks a session that hits a REST endpoint before any admin page
629 665 // load would query the placements / folders tables before the v2
630 666 // trash columns exist, throwing wpdb errors and blanking the desktop.
631 -add_action( 'rest_api_init', 'desktop_mode_files_maybe_install_schema' );
632 -add_action( 'init', 'desktop_mode_files_maybe_install_schema', 1 );
633 -register_activation_hook( DESKTOP_MODE_FILE, 'desktop_mode_files_install_schema' );
667 +add_action( 'rest_api_init', 'openstation_files_maybe_install_schema' );
668 +add_action( 'init', 'openstation_files_maybe_install_schema', 1 );
669 +register_activation_hook( OPENSTATION_FILE, 'openstation_files_install_schema' );
634 670
635 671 /**
636 672 * Current epoch-ms timestamp. Centralized so the store and the
637 673 * tombstone writer stay in lock-step.
638 674 *
639 - * @since 0.9.0
640 - *
641 675 * @return int
642 676 */
643 -function desktop_mode_files_now_ms() {
677 +function openstation_files_now_ms() {
644 678 return (int) round( microtime( true ) * 1000 );
645 679 }