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 +111 -90 0.9.31.1.10 View file →
@@ -1,7 +1,7 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — Files-on-the-Desktop schema.
3 + * OpenStation — Files-on-the-Desktop schema.
4 4 *
5 5 * Five custom tables back the system:
6 6 *
7 7 * - `_desktop_mode_file_placements` — every (user, parent_folder,
@@ -31,34 +31,45 @@
31 31 * denies individually; the shares row itself stays `pending`).
32 32 *
33 33 * dbDelta is the only safe path for schema migrations against the
34 34 * Core tables environment — Phase 6 re-uses this file by bumping
35 - * `DESKTOP_MODE_FILES_SCHEMA_VERSION` and adding columns.
35 + * `OPENSTATION_FILES_SCHEMA_VERSION` and adding columns.
36 36 *
37 - * @package WPDesktopMode
38 - * @since 0.9.0
37 + * @package OpenStation
39 38 */
40 39
41 40 defined( 'ABSPATH' ) || exit;
42 41
43 -define( 'DESKTOP_MODE_FILES_SCHEMA_VERSION', '12' );
44 -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' );
45 51
46 52 /**
47 53 * Returns the per-table names with the active prefix applied.
48 54 *
49 - * @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.
50 60 *
51 61 * @return array{ placements: string, folders: string, tombstones: string, shares: string, decisions: string }
52 62 */
53 -function desktop_mode_files_table_names() {
63 +function openstation_files_table_names() {
54 64 global $wpdb;
55 65 return array(
56 - 'placements' => $wpdb->prefix . 'desktop_mode_file_placements',
57 - 'folders' => $wpdb->prefix . 'desktop_mode_folders',
58 - 'tombstones' => $wpdb->prefix . 'desktop_mode_file_tombstones',
59 - 'shares' => $wpdb->prefix . 'desktop_mode_folder_shares',
60 - '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',
61 72 );
62 73 }
63 74
64 75 /**
@@ -64,20 +75,18 @@
64 75 /**
65 76 * Idempotent `dbDelta` call. Hooked on plugin activation and on
66 77 * `admin_init` (gated by a version-option mismatch) so a manual
67 78 * file copy install still ends up with the tables.
68 - *
69 - * @since 0.9.0
70 79 */
71 -function desktop_mode_files_install_schema() {
80 +function openstation_files_install_schema() {
72 81 global $wpdb;
73 82
74 83 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
75 84
76 - $tables = desktop_mode_files_table_names();
77 - $charset_collate = $wpdb->get_charset_collate();
85 + $tables = openstation_files_table_names();
86 + $charset_collate = $wpdb->get_charset_collate();
78 87
79 - // Schema v2 (since 0.8.0): adds trash columns to both placements
88 + // Schema v2: adds trash columns to both placements
80 89 // and folders so deleted shortcuts and folders land in the
81 90 // recycle bin instead of vanishing. `trashed_at_ms` is the
82 91 // epoch-ms timestamp of the trash event (NULL = active).
83 92 // `trashed_by` records the user that fired it (for permission
@@ -132,8 +141,32 @@
132 141 PRIMARY KEY (id),
133 142 KEY kind_removed (kind, removed_at_ms)
134 143 ) $charset_collate;";
135 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 +
136 169 // Schema v9 — per-principal grants (`folder_shares` table) +
137 170 // per-user opt-in decisions (`share_user_decisions` table).
138 171 // `share_meta` on the folders row stays as a diagnostic-only
139 172 // column; visibility is computed entirely from the shares
@@ -161,19 +194,20 @@
161 194 // `owner_id` as a missing column and ADD it (leaving the old
162 195 // `user_id` in place + the new `owner_id` NULL). Running the
163 196 // CHANGE COLUMN first means dbDelta sees the table already
164 197 // matches the desired shape.
165 - desktop_mode_files_rename_user_id_to_owner_id();
198 + openstation_files_rename_user_id_to_owner_id();
166 199
167 200 dbDelta( $placements_sql );
168 201 dbDelta( $folders_sql );
169 202 dbDelta( $tombstones_sql );
203 + dbDelta( $stored_files_sql );
170 204
171 205 // dbDelta has well-documented quirks with `NULL`-only columns
172 206 // (no DEFAULT) — under some MySQL/MariaDB combos it silently
173 207 // skips the ADD COLUMN. Verify the v2 trash columns are
174 208 // physically present and ALTER them in directly when not.
175 - desktop_mode_files_ensure_trash_columns();
209 + openstation_files_ensure_trash_columns();
176 210
177 211 // v4: clean up duplicate placements created by sessions that
178 212 // hit the auto-orphan-placer while the v2 trash columns were
179 213 // missing — every `WHERE trashed_at_ms IS NULL` precheck
@@ -180,15 +214,15 @@
180 214 // returned empty, so each pageload re-inserted every
181 215 // registered shortcut. Collapse runs of identical
182 216 // `(owner_id, parent_id, file_type, file_ref)` rows down to
183 217 // the lowest id.
184 - desktop_mode_files_dedupe_placements();
218 + openstation_files_dedupe_placements();
185 219
186 220 // v5: enforce uniqueness at the DB level so a future bug
187 221 // (or a racing pair of REST requests) can never re-create
188 222 // the duplicate shortcuts again. Must run AFTER dedupe —
189 223 // adding a unique key against duplicate rows would fail.
190 - desktop_mode_files_ensure_unique_placement_index();
224 + openstation_files_ensure_unique_placement_index();
191 225
192 226 // v9: belt-and-suspenders existence check for the shares +
193 227 // decisions tables. The folder-sharing feature is the
194 228 // canonical source of truth for "who can see this folder" —
@@ -194,10 +228,10 @@
194 228 // canonical source of truth for "who can see this folder" —
195 229 // the `share_meta` JSON column on the folders table remains
196 230 // for diagnostic purposes only and is not consulted by the
197 231 // visibility resolver.
198 - desktop_mode_files_ensure_shares_table();
199 - desktop_mode_files_ensure_decisions_table();
232 + openstation_files_ensure_shares_table();
233 + openstation_files_ensure_decisions_table();
200 234
201 235 // v10: `updated_by` column on placements so the If-Match 409
202 236 // conflict toast names the SESSION that actually won the race,
203 237 // not just whoever currently owns the row. Critical for the
@@ -203,20 +237,18 @@
203 237 // not just whoever currently owns the row. Critical for the
204 238 // shared-write scenario where User B (writer recipient) moves a
205 239 // placement and User C gets the conflict — without this column,
206 240 // the toast would blame User A (owner of the row).
207 - desktop_mode_files_ensure_updated_by_column();
241 + openstation_files_ensure_updated_by_column();
208 242
209 - update_option( DESKTOP_MODE_FILES_SCHEMA_OPTION, DESKTOP_MODE_FILES_SCHEMA_VERSION );
243 + update_option( OPENSTATION_FILES_SCHEMA_OPTION, OPENSTATION_FILES_SCHEMA_VERSION );
210 244
211 245 /**
212 246 * Fires after the files schema is installed / migrated.
213 247 *
214 - * @since 0.9.0
215 - *
216 248 * @param string $version The version that was installed.
217 249 */
218 - do_action( 'desktop_mode_files_schema_installed', DESKTOP_MODE_FILES_SCHEMA_VERSION );
250 + do_action( 'openstation_files_schema_installed', OPENSTATION_FILES_SCHEMA_VERSION );
219 251 }
220 252
221 253 /**
222 254 * Belt-and-suspenders verifier for the v2 trash columns. Reads
@@ -223,14 +255,13 @@
223 255 * `INFORMATION_SCHEMA.COLUMNS` for the placements + folders tables
224 256 * and `ALTER`s in any column dbDelta missed. Idempotent: each
225 257 * `ALTER` only fires when the column is not already there.
226 258 *
227 - * @since 0.8.0
228 259 * @internal
229 260 */
230 -function desktop_mode_files_ensure_trash_columns() {
261 +function openstation_files_ensure_trash_columns() {
231 262 global $wpdb;
232 - $tables = desktop_mode_files_table_names();
263 + $tables = openstation_files_table_names();
233 264
234 265 // Two-worker race protection: between the INFORMATION_SCHEMA
235 266 // check and the ALTER, a concurrent worker (cron + admin-init,
236 267 // REST + heartbeat) can run the same check, see the column
@@ -243,12 +274,12 @@
243 274 $ensure = static function ( $table, $column, $definition ) use ( $wpdb ) {
244 275 $col_exists = static function () use ( $wpdb, $table, $column ) {
245 276 return (int) $wpdb->get_var(
246 277 $wpdb->prepare(
247 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
278 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
248 279 WHERE TABLE_SCHEMA = DATABASE()
249 280 AND TABLE_NAME = %s
250 - AND COLUMN_NAME = %s",
281 + AND COLUMN_NAME = %s',
251 282 $table,
252 283 $column
253 284 )
254 285 );
@@ -268,18 +299,18 @@
268 299 $wpdb->query( "ALTER TABLE `{$table}` ADD COLUMN `{$column}` {$definition}" );
269 300 }
270 301 };
271 302
272 - $ensure( $tables['placements'], 'trashed_at_ms', 'BIGINT UNSIGNED NULL' );
273 - $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' );
274 305 $ensure( $tables['placements'], 'trashed_via_folder', 'BIGINT UNSIGNED NULL' );
275 306 // v6: ancestry snapshot — JSON capturing every folder in the
276 307 // parent chain at trash time so a restore can resurrect the
277 308 // chain even when a folder was hard-deleted in the meantime.
278 - $ensure( $tables['placements'], 'trashed_meta', 'LONGTEXT NULL' );
279 - $ensure( $tables['folders'], 'trashed_at_ms', 'BIGINT UNSIGNED NULL' );
280 - $ensure( $tables['folders'], 'trashed_by', 'BIGINT UNSIGNED NULL' );
281 - $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' );
282 313 }
283 314
284 315 /**
285 316 * Collapse duplicate `(owner_id, parent_id, file_type, file_ref)`
@@ -290,17 +321,16 @@
290 321 * covers EVERY file type, so duplicates of any type within the
291 322 * same (owner, parent) are disallowed at the DB level; if legacy
292 323 * duplicates of another type exist, the (error-suppressed)
293 324 * `ADD UNIQUE` in
294 - * `desktop_mode_files_ensure_unique_placement_index()` will fail
325 + * `openstation_files_ensure_unique_placement_index()` will fail
295 326 * and leave the index absent until those rows are cleaned up.
296 327 *
297 - * @since 0.8.0
298 328 * @internal
299 329 */
300 -function desktop_mode_files_dedupe_placements() {
330 +function openstation_files_dedupe_placements() {
301 331 global $wpdb;
302 - $tables = desktop_mode_files_table_names();
332 + $tables = openstation_files_table_names();
303 333 $tbl = $tables['placements'];
304 334
305 335 // Once the unique index exists, MySQL prevents duplicate
306 336 // inserts at the DB level — dedupe is a no-op and the
@@ -308,12 +338,12 @@
308 338 // call. Skip in that case so the cost is paid exactly once,
309 339 // during the v4 → v5 migration.
310 340 $has_unique = (int) $wpdb->get_var(
311 341 $wpdb->prepare(
312 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
342 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
313 343 WHERE TABLE_SCHEMA = DATABASE()
314 344 AND TABLE_NAME = %s
315 - AND INDEX_NAME = %s",
345 + AND INDEX_NAME = %s',
316 346 $tbl,
317 347 'placement_unique'
318 348 )
319 349 );
@@ -347,22 +377,21 @@
347 377 * Note: `file_ref` is `VARCHAR(255)` — combined with the three
348 378 * other columns this fits comfortably under MySQL's 3072-byte
349 379 * InnoDB index-key limit on `utf8mb4`.
350 380 *
351 - * @since 0.8.0
352 381 * @internal
353 382 */
354 -function desktop_mode_files_ensure_unique_placement_index() {
383 +function openstation_files_ensure_unique_placement_index() {
355 384 global $wpdb;
356 - $tables = desktop_mode_files_table_names();
385 + $tables = openstation_files_table_names();
357 386 $tbl = $tables['placements'];
358 387
359 388 $exists = (int) $wpdb->get_var(
360 389 $wpdb->prepare(
361 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
390 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
362 391 WHERE TABLE_SCHEMA = DATABASE()
363 392 AND TABLE_NAME = %s
364 - AND INDEX_NAME = %s",
393 + AND INDEX_NAME = %s',
365 394 $tbl,
366 395 'placement_unique'
367 396 )
368 397 );
@@ -385,9 +414,9 @@
385 414 /**
386 415 * Add the v10 `updated_by` column to the placements table.
387 416 *
388 417 * Tracks which user last mutated the row (created, moved, restored).
389 - * 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
390 419 * conflict toast attributes the change to the SESSION that won the
391 420 * race rather than to the row's static owner — critical when a
392 421 * writer recipient of a shared folder rearranges placements and
393 422 * another viewer hits a stale `If-Match`.
@@ -394,21 +423,20 @@
394 423 *
395 424 * NULL on legacy rows (pre-v10). The conflict resolver falls back
396 425 * to `owner_id` when this column is NULL, matching the old behavior.
397 426 *
398 - * @since 0.8.5 (schema v10)
399 427 * @internal
400 428 */
401 -function desktop_mode_files_ensure_updated_by_column() {
429 +function openstation_files_ensure_updated_by_column() {
402 430 global $wpdb;
403 - $tables = desktop_mode_files_table_names();
431 + $tables = openstation_files_table_names();
404 432 $tbl = $tables['placements'];
405 433 $exists = (int) $wpdb->get_var(
406 434 $wpdb->prepare(
407 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
435 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
408 436 WHERE TABLE_SCHEMA = DATABASE()
409 437 AND TABLE_NAME = %s
410 - AND COLUMN_NAME = %s",
438 + AND COLUMN_NAME = %s',
411 439 $tbl,
412 440 'updated_by'
413 441 )
414 442 );
@@ -426,9 +454,9 @@
426 454
427 455 /**
428 456 * Rename `placements.user_id` to `placements.owner_id` and the
429 457 * matching `user_parent` index to `owner_parent`. The two
430 - * desktop-mode-owned tables historically used different names for
458 + * os-owned tables historically used different names for
431 459 * the same "row's owner" concept — folders carried `owner_id` from
432 460 * day one, placements carried `user_id`. v11 unifies them so SQL
433 461 * and PHP read identically across the two tables.
434 462 *
@@ -436,9 +464,9 @@
436 464 * dbDelta runs after this and creates the table with the new
437 465 * column name directly) and when the column is already renamed.
438 466 *
439 467 * Must run BEFORE `dbDelta( $placements_sql )` in
440 - * `desktop_mode_files_install_schema()` — dbDelta does NOT rename
468 + * `openstation_files_install_schema()` — dbDelta does NOT rename
441 469 * columns, so against a v≤10 table whose definition says
442 470 * `owner_id` it would ADD a new `owner_id` column and leave the
443 471 * stale `user_id` in place. Running the CHANGE COLUMN first puts
444 472 * the table in the desired shape so dbDelta sees no diff.
@@ -448,14 +476,13 @@
448 476 * partial run during dev iteration) gets a clean retry. The
449 477 * function is idempotent — early-returns when `user_id` is absent,
450 478 * so healthy v11 installs see a cheap no-op on the retry.
451 479 *
452 - * @since 0.8.9 (schema v11, redelivered at v12)
453 480 * @internal
454 481 */
455 -function desktop_mode_files_rename_user_id_to_owner_id() {
482 +function openstation_files_rename_user_id_to_owner_id() {
456 483 global $wpdb;
457 - $tables = desktop_mode_files_table_names();
484 + $tables = openstation_files_table_names();
458 485 $tbl = $tables['placements'];
459 486
460 487 // Fresh install — the table doesn't exist yet; dbDelta creates
461 488 // it with `owner_id` directly. Nothing to migrate.
@@ -460,10 +487,10 @@
460 487 // Fresh install — the table doesn't exist yet; dbDelta creates
461 488 // it with `owner_id` directly. Nothing to migrate.
462 489 $table_exists = (int) $wpdb->get_var(
463 490 $wpdb->prepare(
464 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
465 - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s",
491 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
492 + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
466 493 $tbl
467 494 )
468 495 );
469 496 if ( 0 === $table_exists ) {
@@ -522,22 +549,21 @@
522 549 * declarations on a non-`utf8mb4` collation gets silently skipped
523 550 * on some MySQL/MariaDB combos; we mirror the trash-columns
524 551 * pattern and `CREATE TABLE IF NOT EXISTS` the row explicitly.
525 552 *
526 - * @since 0.8.5
527 553 * @internal
528 554 */
529 -function desktop_mode_files_ensure_shares_table() {
555 +function openstation_files_ensure_shares_table() {
530 556 global $wpdb;
531 - $tables = desktop_mode_files_table_names();
557 + $tables = openstation_files_table_names();
532 558 $charset_collate = $wpdb->get_charset_collate();
533 559 $tbl = $tables['shares'];
534 560
535 561 $exists = (int) $wpdb->get_var(
536 562 $wpdb->prepare(
537 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
563 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
538 564 WHERE TABLE_SCHEMA = DATABASE()
539 - AND TABLE_NAME = %s",
565 + AND TABLE_NAME = %s',
540 566 $tbl
541 567 )
542 568 );
543 569 if ( 0 === $exists ) {
@@ -564,12 +590,12 @@
564 590 // Existing table — make sure `target_type` is there for
565 591 // installs that ran a pre-target_type build of v8.
566 592 $has_col = (int) $wpdb->get_var(
567 593 $wpdb->prepare(
568 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
594 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
569 595 WHERE TABLE_SCHEMA = DATABASE()
570 596 AND TABLE_NAME = %s
571 - AND COLUMN_NAME = %s",
597 + AND COLUMN_NAME = %s',
572 598 $tbl,
573 599 'target_type'
574 600 )
575 601 );
@@ -587,22 +613,21 @@
587 613
588 614 /**
589 615 * Belt-and-suspenders verifier for the decisions table.
590 616 *
591 - * @since 0.8.5
592 617 * @internal
593 618 */
594 -function desktop_mode_files_ensure_decisions_table() {
619 +function openstation_files_ensure_decisions_table() {
595 620 global $wpdb;
596 - $tables = desktop_mode_files_table_names();
621 + $tables = openstation_files_table_names();
597 622 $charset_collate = $wpdb->get_charset_collate();
598 623 $tbl = $tables['decisions'];
599 624
600 625 $exists = (int) $wpdb->get_var(
601 626 $wpdb->prepare(
602 - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
627 + 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
603 628 WHERE TABLE_SCHEMA = DATABASE()
604 - AND TABLE_NAME = %s",
629 + AND TABLE_NAME = %s',
605 630 $tbl
606 631 )
607 632 );
608 633 if ( 0 === $exists ) {
@@ -625,34 +650,30 @@
625 650 /**
626 651 * Lazy migrator — runs on `admin_init` when the stored schema
627 652 * version doesn't match the constant. Idempotent: `dbDelta`
628 653 * itself is a no-op when the table already matches.
629 - *
630 - * @since 0.9.0
631 654 */
632 -function desktop_mode_files_maybe_install_schema() {
633 - $installed = get_option( DESKTOP_MODE_FILES_SCHEMA_OPTION, '' );
634 - 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 ) {
635 658 return;
636 659 }
637 - desktop_mode_files_install_schema();
660 + openstation_files_install_schema();
638 661 }
639 -add_action( 'admin_init', 'desktop_mode_files_maybe_install_schema' );
662 +add_action( 'admin_init', 'openstation_files_maybe_install_schema' );
640 663 // REST + front-end requests never fire `admin_init` — without these
641 664 // hooks a session that hits a REST endpoint before any admin page
642 665 // load would query the placements / folders tables before the v2
643 666 // trash columns exist, throwing wpdb errors and blanking the desktop.
644 -add_action( 'rest_api_init', 'desktop_mode_files_maybe_install_schema' );
645 -add_action( 'init', 'desktop_mode_files_maybe_install_schema', 1 );
646 -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' );
647 670
648 671 /**
649 672 * Current epoch-ms timestamp. Centralized so the store and the
650 673 * tombstone writer stay in lock-step.
651 674 *
652 - * @since 0.9.0
653 - *
654 675 * @return int
655 676 */
656 -function desktop_mode_files_now_ms() {
677 +function openstation_files_now_ms() {
657 678 return (int) round( microtime( true ) * 1000 );
658 679 }