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/trash.php +211 -235 0.9.21.1.10 View file →
@@ -1,7 +1,7 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — Files-on-the-Desktop trash + restore + purge.
3 + * OpenStation — Files-on-the-Desktop trash + restore + purge.
4 4 *
5 5 * Both placements and folders soft-trash before they ever hit the
6 6 * physical row delete. Trashed rows live in the same tables (with
7 7 * `trashed_at_ms` / `trashed_by` columns set; `trashed_via_folder`
@@ -19,48 +19,58 @@
19 19 *
20 20 * - Veto any trash / restore / purge (`*_user_can_*` filters).
21 21 * - Observe any state transition (`*_before_*` / `*_after_*`).
22 22 * - React to recycle-bin list / restore / purge of the new types
23 - * via the existing recycle-bin hooks (`desktop_mode_recycle_bin_*`).
23 + * via the existing recycle-bin hooks (`openstation_recycle_bin_*`).
24 24 *
25 - * @package WPDesktopMode
26 - * @since 0.8.0
25 + * @package OpenStation
27 26 */
28 27
29 28 defined( 'ABSPATH' ) || exit;
30 29
31 -/* ================================================================== *
30 +/*
31 +================================================================== *
32 32 * Capability gates.
33 - * ================================================================== */
33 + * ==================================================================
34 + */
34 35
35 36 /**
36 - * Whether the given user can trash a placement they own. Defaults
37 - * to ownership; plugins can broaden via filter.
37 + * Default ownership check shared by every trash / restore / purge
38 + * capability gate: the acting user must be the row's `owner_id`.
38 39 *
39 - * @since 0.8.0
40 + * @access private
40 41 *
41 42 * @param int $user_id Acting user.
42 - * @param array $row Placement row (raw from DB or normalized).
43 + * @param array $row Placement or folder row.
43 44 * @return bool
44 45 */
45 -function desktop_mode_files_user_can_trash_placement( $user_id, $row ) {
46 +function openstation_files_user_owns_row( $user_id, $row ) {
46 47 $user_id = (int) $user_id;
47 - $can = ( $user_id > 0 )
48 + return ( $user_id > 0 )
48 49 && isset( $row['owner_id'] )
49 50 && (int) $row['owner_id'] === $user_id;
51 +}
52 +
53 +/**
54 + * Whether the given user can trash a placement they own. Defaults
55 + * to ownership; plugins can broaden via filter.
56 + *
57 + * @param int $user_id Acting user.
58 + * @param array $row Placement row (raw from DB or normalized).
59 + * @return bool
60 + */
61 +function openstation_files_user_can_trash_placement( $user_id, $row ) {
50 62 /**
51 63 * Filter whether the user can trash this placement.
52 64 *
53 - * @since 0.8.0
54 - *
55 65 * @param bool $can Default: ownership match.
56 66 * @param int $user_id Acting user.
57 67 * @param array $row Placement row.
58 68 */
59 69 return (bool) apply_filters(
60 - 'desktop_mode_files_user_can_trash_placement',
61 - $can,
62 - $user_id,
70 + 'openstation_files_user_can_trash_placement',
71 + openstation_files_user_owns_row( $user_id, $row ),
72 + (int) $user_id,
63 73 $row
64 74 );
65 75 }
66 76
@@ -66,30 +76,22 @@
66 76
67 77 /**
68 78 * Whether the given user can restore a trashed placement.
69 79 *
70 - * @since 0.8.0
71 - *
72 80 * @param int $user_id Acting user.
73 81 * @param array $row Placement row (already trashed).
74 82 * @return bool
75 83 */
76 -function desktop_mode_files_user_can_restore_placement( $user_id, $row ) {
77 - $user_id = (int) $user_id;
78 - $can = ( $user_id > 0 )
79 - && isset( $row['owner_id'] )
80 - && (int) $row['owner_id'] === $user_id;
84 +function openstation_files_user_can_restore_placement( $user_id, $row ) {
81 85 /**
82 - * @since 0.8.0
83 - *
84 86 * @param bool $can
85 87 * @param int $user_id
86 88 * @param array $row
87 89 */
88 90 return (bool) apply_filters(
89 - 'desktop_mode_files_user_can_restore_placement',
90 - $can,
91 - $user_id,
91 + 'openstation_files_user_can_restore_placement',
92 + openstation_files_user_owns_row( $user_id, $row ),
93 + (int) $user_id,
92 94 $row
93 95 );
94 96 }
95 97
@@ -94,27 +96,19 @@
94 96 }
95 97
96 98 /**
97 99 * Whether the given user can permanently purge a trashed placement.
98 - *
99 - * @since 0.8.0
100 100 */
101 -function desktop_mode_files_user_can_purge_placement( $user_id, $row ) {
102 - $user_id = (int) $user_id;
103 - $can = ( $user_id > 0 )
104 - && isset( $row['owner_id'] )
105 - && (int) $row['owner_id'] === $user_id;
101 +function openstation_files_user_can_purge_placement( $user_id, $row ) {
106 102 /**
107 - * @since 0.8.0
108 - *
109 103 * @param bool $can
110 104 * @param int $user_id
111 105 * @param array $row
112 106 */
113 107 return (bool) apply_filters(
114 - 'desktop_mode_files_user_can_purge_placement',
115 - $can,
116 - $user_id,
108 + 'openstation_files_user_can_purge_placement',
109 + openstation_files_user_owns_row( $user_id, $row ),
110 + (int) $user_id,
117 111 $row
118 112 );
119 113 }
120 114
@@ -119,27 +113,19 @@
119 113 }
120 114
121 115 /**
122 116 * Whether the given user can trash a folder. Default: folder owner.
123 - *
124 - * @since 0.8.0
125 117 */
126 -function desktop_mode_files_user_can_trash_folder( $user_id, $row ) {
127 - $user_id = (int) $user_id;
128 - $can = ( $user_id > 0 )
129 - && isset( $row['owner_id'] )
130 - && (int) $row['owner_id'] === $user_id;
118 +function openstation_files_user_can_trash_folder( $user_id, $row ) {
131 119 /**
132 - * @since 0.8.0
133 - *
134 120 * @param bool $can
135 121 * @param int $user_id
136 122 * @param array $row
137 123 */
138 124 return (bool) apply_filters(
139 - 'desktop_mode_files_user_can_trash_folder',
140 - $can,
141 - $user_id,
125 + 'openstation_files_user_can_trash_folder',
126 + openstation_files_user_owns_row( $user_id, $row ),
127 + (int) $user_id,
142 128 $row
143 129 );
144 130 }
145 131
@@ -144,27 +130,19 @@
144 130 }
145 131
146 132 /**
147 133 * Whether the given user can restore a trashed folder.
148 - *
149 - * @since 0.8.0
150 134 */
151 -function desktop_mode_files_user_can_restore_folder( $user_id, $row ) {
152 - $user_id = (int) $user_id;
153 - $can = ( $user_id > 0 )
154 - && isset( $row['owner_id'] )
155 - && (int) $row['owner_id'] === $user_id;
135 +function openstation_files_user_can_restore_folder( $user_id, $row ) {
156 136 /**
157 - * @since 0.8.0
158 - *
159 137 * @param bool $can
160 138 * @param int $user_id
161 139 * @param array $row
162 140 */
163 141 return (bool) apply_filters(
164 - 'desktop_mode_files_user_can_restore_folder',
165 - $can,
166 - $user_id,
142 + 'openstation_files_user_can_restore_folder',
143 + openstation_files_user_owns_row( $user_id, $row ),
144 + (int) $user_id,
167 145 $row
168 146 );
169 147 }
170 148
@@ -169,32 +147,25 @@
169 147 }
170 148
171 149 /**
172 150 * Whether the given user can permanently purge a trashed folder.
173 - *
174 - * @since 0.8.0
175 151 */
176 -function desktop_mode_files_user_can_purge_folder( $user_id, $row ) {
177 - $user_id = (int) $user_id;
178 - $can = ( $user_id > 0 )
179 - && isset( $row['owner_id'] )
180 - && (int) $row['owner_id'] === $user_id;
152 +function openstation_files_user_can_purge_folder( $user_id, $row ) {
181 153 /**
182 - * @since 0.8.0
183 - *
184 154 * @param bool $can
185 155 * @param int $user_id
186 156 * @param array $row
187 157 */
188 158 return (bool) apply_filters(
189 - 'desktop_mode_files_user_can_purge_folder',
190 - $can,
191 - $user_id,
159 + 'openstation_files_user_can_purge_folder',
160 + openstation_files_user_owns_row( $user_id, $row ),
161 + (int) $user_id,
192 162 $row
193 163 );
194 164 }
195 165
196 -/* ================================================================== *
166 +/*
167 +================================================================== *
197 168 * Ancestry snapshot + resurrection.
198 169 *
199 170 * When a placement is soft-trashed we capture every folder in
200 171 * its parent chain into a JSON blob on `placements.trashed_meta`.
@@ -202,9 +173,10 @@
202 173 * still alive are reused, trashed folders cascade-restore, and
203 174 * hard-deleted folders are recreated (with new ids; the chain is
204 175 * rewritten as it walks). The placement comes back at the same
205 176 * visual position inside the (possibly resurrected) parent.
206 - * ================================================================== */
177 + * ==================================================================
178 + */
207 179
208 180 /**
209 181 * Walk up `$parent_id` through the folders + placements tables and
210 182 * return the parent chain root-first.
@@ -223,16 +195,14 @@
223 195 * )
224 196 *
225 197 * Returns `[]` for a root-level placement (`$parent_id === 0`).
226 198 *
227 - * @since 0.8.0
228 - *
229 199 * @param int $parent_id Immediate parent folder id.
230 200 * @return array<int, array<string, mixed>>
231 201 */
232 -function desktop_mode_files_capture_ancestry( $parent_id ) {
202 +function openstation_files_capture_ancestry( $parent_id ) {
233 203 global $wpdb;
234 - $tables = desktop_mode_files_table_names();
204 + $tables = openstation_files_table_names();
235 205 $chain = array();
236 206 $cursor = (int) $parent_id;
237 207 $guard = 0; // depth-bound — defends against accidental cycles.
238 208 while ( $cursor > 0 && $guard < 32 ) {
@@ -249,9 +219,9 @@
249 219 }
250 220 // The folder's "where I sit on the desktop tree" lives on
251 221 // its placement row. Pick any active or trashed placement
252 222 // of this folder — we just need its parent_id + (x, y).
253 - $placement = $wpdb->get_row(
223 + $placement = $wpdb->get_row(
254 224 $wpdb->prepare(
255 225 "SELECT parent_id, x, y FROM {$tables['placements']}
256 226 WHERE file_type = 'folder' AND file_ref = %s
257 227 ORDER BY id ASC LIMIT 1",
@@ -260,9 +230,9 @@
260 230 ARRAY_A
261 231 );
262 232 $share_meta_raw = isset( $folder['share_meta'] ) ? (string) $folder['share_meta'] : '';
263 233 $share_meta = '' !== $share_meta_raw ? json_decode( $share_meta_raw, true ) : null;
264 - $entry = array(
234 + $entry = array(
265 235 'folder_id' => (int) $folder['id'],
266 236 'folder_name' => (string) $folder['name'],
267 237 'folder_share_mode' => (string) $folder['share_mode'],
268 238 'folder_share_meta' => is_array( $share_meta ) ? $share_meta : null,
@@ -284,10 +254,8 @@
284 254 * downstream entries rewrite their `placement_parent_id` so a
285 255 * deeper folder lands inside the correct (possibly recreated)
286 256 * parent.
287 257 *
288 - * @since 0.8.0
289 - *
290 258 * @param int $user_id Acting user (used as owner for any
291 259 * recreated folder).
292 260 * @param array $ancestry Root-first chain captured at trash time.
293 261 * @return int Resolved leaf parent id (0 when the placement was
@@ -292,9 +260,9 @@
292 260 * @param array $ancestry Root-first chain captured at trash time.
293 261 * @return int Resolved leaf parent id (0 when the placement was
294 262 * at desktop root).
295 263 */
296 -function desktop_mode_files_resurrect_ancestry( $user_id, $ancestry ) {
264 +function openstation_files_resurrect_ancestry( $user_id, $ancestry ) {
297 265 if ( empty( $ancestry ) ) {
298 266 return 0;
299 267 }
300 268 $user_id = (int) $user_id;
@@ -308,15 +276,15 @@
308 276 $resolved_parent = isset( $id_map[ $orig_par ] )
309 277 ? (int) $id_map[ $orig_par ]
310 278 : $orig_par;
311 279
312 - $folder = desktop_mode_files_get_folder( $orig_id, true );
280 + $folder = openstation_files_get_folder( $orig_id, true );
313 281 if ( $folder ) {
314 282 // Folder still exists. If trashed, restore it (cascade
315 283 // brings back its own children that were trashed via
316 284 // folder cascade).
317 285 if ( ! empty( $folder['trashed_at_ms'] ) ) {
318 - desktop_mode_files_restore_folder( $user_id, $orig_id );
286 + openstation_files_restore_folder( $user_id, $orig_id );
319 287 }
320 288 $id_map[ $orig_id ] = $orig_id;
321 289 $resolved = $orig_id;
322 290 continue;
@@ -325,23 +293,26 @@
325 293 // Folder is gone — recreate it and place it under the
326 294 // resolved parent. Owner falls back to the acting user
327 295 // when the original owner can't be inferred (shared-
328 296 // folder edge case Phase 6 will revisit).
329 - $owner_id = (int) ( $entry['folder_owner_id'] ?: $user_id );
330 - $new_id = desktop_mode_files_create_folder( $owner_id, array(
331 - 'name' => (string) $entry['folder_name'],
332 - 'share_mode' => (string) $entry['folder_share_mode'],
333 - 'share_meta' => $entry['folder_share_meta'],
334 - ) );
297 + $owner_id = (int) ( $entry['folder_owner_id'] ? $entry['folder_owner_id'] : $user_id );
298 + $new_id = openstation_files_create_folder(
299 + $owner_id,
300 + array(
301 + 'name' => (string) $entry['folder_name'],
302 + 'share_mode' => (string) $entry['folder_share_mode'],
303 + 'share_meta' => $entry['folder_share_meta'],
304 + )
305 + );
335 306 if ( is_wp_error( $new_id ) ) {
336 307 // Fall back to root — restoring at the wrong place is
337 308 // strictly better than failing the restore outright.
338 - $resolved = $resolved_parent;
309 + $resolved = $resolved_parent;
339 310 $id_map[ $orig_id ] = $resolved;
340 311 continue;
341 312 }
342 313 // Place the recreated folder where the snapshot says.
343 - desktop_mode_files_place(
314 + openstation_files_place(
344 315 $user_id,
345 316 $resolved_parent,
346 317 'folder',
347 318 (string) $new_id,
@@ -355,11 +326,13 @@
355 326 }
356 327 return $resolved;
357 328 }
358 329
359 -/* ================================================================== *
330 +/*
331 +================================================================== *
360 332 * Placement: trash / restore / purge.
361 - * ================================================================== */
333 + * ==================================================================
334 + */
362 335
363 336 /**
364 337 * Soft-trash a placement. Sets `trashed_at_ms`, `trashed_by`. Returns
365 338 * `true` on success, `WP_Error` on permission failure / missing row.
@@ -366,19 +339,17 @@
366 339 *
367 340 * Idempotent: trashing an already-trashed placement is a no-op
368 341 * success.
369 342 *
370 - * @since 0.8.0
371 - *
372 343 * @param int $user_id Acting user.
373 344 * @param int $placement_id Placement id.
374 345 * @return true|WP_Error
375 346 */
376 -function desktop_mode_files_trash_placement( $user_id, $placement_id ) {
347 +function openstation_files_trash_placement( $user_id, $placement_id ) {
377 348 global $wpdb;
378 349 $user_id = (int) $user_id;
379 350 $placement_id = (int) $placement_id;
380 - $tables = desktop_mode_files_table_names();
351 + $tables = openstation_files_table_names();
381 352
382 353 $row = $wpdb->get_row(
383 354 $wpdb->prepare(
384 355 "SELECT * FROM {$tables['placements']} WHERE id = %d",
@@ -387,9 +358,9 @@
387 358 ARRAY_A
388 359 );
389 360 if ( ! $row ) {
390 361 return new WP_Error(
391 - 'desktop_mode_files_placement_not_found',
362 + 'openstation_files_placement_not_found',
392 363 __( 'Placement not found.', 'desktop-mode' ),
393 364 array( 'status' => 404 )
394 365 );
395 366 }
@@ -395,11 +366,11 @@
395 366 }
396 367 if ( null !== $row['trashed_at_ms'] && '' !== $row['trashed_at_ms'] ) {
397 368 return true;
398 369 }
399 - if ( ! desktop_mode_files_user_can_trash_placement( $user_id, $row ) ) {
370 + if ( ! openstation_files_user_can_trash_placement( $user_id, $row ) ) {
400 371 return new WP_Error(
401 - 'desktop_mode_files_forbidden',
372 + 'openstation_files_forbidden',
402 373 __( 'You do not have permission to trash this item.', 'desktop-mode' ),
403 374 array( 'status' => 403 )
404 375 );
405 376 }
@@ -406,18 +377,16 @@
406 377
407 378 /**
408 379 * Fires before a placement is trashed.
409 380 *
410 - * @since 0.8.0
411 - *
412 381 * @param int $placement_id Placement id.
413 382 * @param int $user_id Acting user.
414 383 * @param array $row Placement row.
415 384 */
416 - do_action( 'desktop_mode_files_before_trash_placement', $placement_id, $user_id, $row );
385 + do_action( 'openstation_files_before_trash_placement', $placement_id, $user_id, $row );
417 386
418 - $now = desktop_mode_files_now_ms();
419 - $ancestry = desktop_mode_files_capture_ancestry( (int) $row['parent_id'] );
387 + $now = openstation_files_now_ms();
388 + $ancestry = openstation_files_capture_ancestry( (int) $row['parent_id'] );
420 389 $meta = wp_json_encode( array( 'ancestry' => $ancestry ) );
421 390 $result = $wpdb->update(
422 391 $tables['placements'],
423 392 array(
@@ -436,9 +405,9 @@
436 405 // 200 OK and the UI would show "moved to trash" with nothing
437 406 // actually trashed.
438 407 if ( false === $result ) {
439 408 return new WP_Error(
440 - 'desktop_mode_files_trash_failed',
409 + 'openstation_files_trash_failed',
441 410 isset( $wpdb->last_error ) && $wpdb->last_error
442 411 ? (string) $wpdb->last_error
443 412 : __( 'Failed to write trash row.', 'desktop-mode' ),
444 413 array( 'status' => 500 )
@@ -447,14 +416,12 @@
447 416
448 417 /**
449 418 * Fires after a placement is trashed.
450 419 *
451 - * @since 0.8.0
452 - *
453 420 * @param int $placement_id Placement id.
454 421 * @param int $user_id Acting user.
455 422 */
456 - do_action( 'desktop_mode_files_after_trash_placement', $placement_id, $user_id );
423 + do_action( 'openstation_files_after_trash_placement', $placement_id, $user_id );
457 424
458 425 return true;
459 426 }
460 427
@@ -460,19 +427,17 @@
460 427
461 428 /**
462 429 * Restore a trashed placement back to its original folder + (x, y).
463 430 *
464 - * @since 0.8.0
465 - *
466 431 * @param int $user_id Acting user.
467 432 * @param int $placement_id Placement id.
468 433 * @return true|WP_Error
469 434 */
470 -function desktop_mode_files_restore_placement( $user_id, $placement_id ) {
435 +function openstation_files_restore_placement( $user_id, $placement_id ) {
471 436 global $wpdb;
472 437 $user_id = (int) $user_id;
473 438 $placement_id = (int) $placement_id;
474 - $tables = desktop_mode_files_table_names();
439 + $tables = openstation_files_table_names();
475 440
476 441 $row = $wpdb->get_row(
477 442 $wpdb->prepare(
478 443 "SELECT * FROM {$tables['placements']} WHERE id = %d",
@@ -481,9 +446,9 @@
481 446 ARRAY_A
482 447 );
483 448 if ( ! $row ) {
484 449 return new WP_Error(
485 - 'desktop_mode_files_placement_not_found',
450 + 'openstation_files_placement_not_found',
486 451 __( 'Placement not found.', 'desktop-mode' ),
487 452 array( 'status' => 404 )
488 453 );
489 454 }
@@ -489,11 +454,11 @@
489 454 }
490 455 if ( null === $row['trashed_at_ms'] || '' === $row['trashed_at_ms'] ) {
491 456 return true; // Already active — idempotent.
492 457 }
493 - if ( ! desktop_mode_files_user_can_restore_placement( $user_id, $row ) ) {
458 + if ( ! openstation_files_user_can_restore_placement( $user_id, $row ) ) {
494 459 return new WP_Error(
495 - 'desktop_mode_files_forbidden',
460 + 'openstation_files_forbidden',
496 461 __( 'You do not have permission to restore this item.', 'desktop-mode' ),
497 462 array( 'status' => 403 )
498 463 );
499 464 }
@@ -498,24 +463,24 @@
498 463 );
499 464 }
500 465
501 466 // Resolve the parent folder. Three branches:
502 - // - parent is alive → reuse the same id
503 - // - parent is trashed → cascade-restore it (and rest of the
504 - // chain) before placing the leaf
505 - // - parent is gone → walk the captured ancestry and
506 - // recreate every missing folder in
507 - // the chain
467 + // - parent is alive → reuse the same id
468 + // - parent is trashed → cascade-restore it (and rest of the
469 + // chain) before placing the leaf
470 + // - parent is gone → walk the captured ancestry and
471 + // recreate every missing folder in
472 + // the chain
508 473 $original_parent_id = (int) $row['parent_id'];
509 474 $resolved_parent_id = $original_parent_id;
510 475 if ( $original_parent_id > 0 ) {
511 - $parent_alive = desktop_mode_files_get_folder( $original_parent_id, true );
476 + $parent_alive = openstation_files_get_folder( $original_parent_id, true );
512 477 if ( $parent_alive ) {
513 478 if ( ! empty( $parent_alive['trashed_at_ms'] ) ) {
514 479 // Cascade restore — reach into the snapshot the
515 480 // folder itself stored at trash time so any chain
516 481 // above it is also resurrected.
517 - $folder_restore = desktop_mode_files_restore_folder( $user_id, $original_parent_id );
482 + $folder_restore = openstation_files_restore_folder( $user_id, $original_parent_id );
518 483 if ( is_wp_error( $folder_restore ) ) {
519 484 return $folder_restore;
520 485 }
521 486 }
@@ -522,14 +487,14 @@
522 487 $resolved_parent_id = $original_parent_id;
523 488 } else {
524 489 // Hard-deleted parent — read the ancestry snapshot we
525 490 // stored at trash time and resurrect the chain.
526 - $meta_raw = isset( $row['trashed_meta'] ) ? (string) $row['trashed_meta'] : '';
527 - $decoded = '' !== $meta_raw ? json_decode( $meta_raw, true ) : null;
528 - $ancestry = ( is_array( $decoded ) && isset( $decoded['ancestry'] ) && is_array( $decoded['ancestry'] ) )
491 + $meta_raw = isset( $row['trashed_meta'] ) ? (string) $row['trashed_meta'] : '';
492 + $decoded = '' !== $meta_raw ? json_decode( $meta_raw, true ) : null;
493 + $ancestry = ( is_array( $decoded ) && isset( $decoded['ancestry'] ) && is_array( $decoded['ancestry'] ) )
529 494 ? $decoded['ancestry']
530 495 : array();
531 - $resolved_parent_id = desktop_mode_files_resurrect_ancestry( $user_id, $ancestry );
496 + $resolved_parent_id = openstation_files_resurrect_ancestry( $user_id, $ancestry );
532 497 }
533 498 }
534 499
535 500 /**
@@ -534,15 +499,13 @@
534 499
535 500 /**
536 501 * Fires before a placement is restored.
537 502 *
538 - * @since 0.8.0
539 - *
540 503 * @param int $placement_id
541 504 * @param int $user_id
542 505 * @param array $row
543 506 */
544 - do_action( 'desktop_mode_files_before_restore_placement', $placement_id, $user_id, $row );
507 + do_action( 'openstation_files_before_restore_placement', $placement_id, $user_id, $row );
545 508
546 509 $wpdb->update(
547 510 $tables['placements'],
548 511 array(
@@ -550,9 +513,9 @@
550 513 'trashed_at_ms' => null,
551 514 'trashed_by' => null,
552 515 'trashed_via_folder' => null,
553 516 'trashed_meta' => null,
554 - 'updated_at_ms' => desktop_mode_files_now_ms(),
517 + 'updated_at_ms' => openstation_files_now_ms(),
555 518 ),
556 519 array( 'id' => $placement_id ),
557 520 array( '%d', null, null, null, null, '%d' ),
558 521 array( '%d' )
@@ -562,17 +525,15 @@
562 525 // a placement coming back to life must not carry lingering
563 526 // tombstones from an earlier (reversible) removal. Without this,
564 527 // every heartbeat tick would re-deliver those tombstones to the
565 528 // client and the row would flicker off the desktop on each tick.
566 - desktop_mode_files_clear_tombstones_for( 'placement', $placement_id );
529 + openstation_files_clear_tombstones_for( 'placement', $placement_id );
567 530
568 531 /**
569 - * @since 0.8.0
570 - *
571 532 * @param int $placement_id
572 533 * @param int $user_id
573 534 */
574 - do_action( 'desktop_mode_files_after_restore_placement', $placement_id, $user_id );
535 + do_action( 'openstation_files_after_restore_placement', $placement_id, $user_id );
575 536
576 537 return true;
577 538 }
578 539
@@ -578,19 +539,17 @@
578 539
579 540 /**
580 541 * Permanently delete a trashed placement.
581 542 *
582 - * @since 0.8.0
583 - *
584 543 * @param int $user_id
585 544 * @param int $placement_id
586 545 * @return true|WP_Error
587 546 */
588 -function desktop_mode_files_purge_placement( $user_id, $placement_id ) {
547 +function openstation_files_purge_placement( $user_id, $placement_id ) {
589 548 global $wpdb;
590 549 $user_id = (int) $user_id;
591 550 $placement_id = (int) $placement_id;
592 - $tables = desktop_mode_files_table_names();
551 + $tables = openstation_files_table_names();
593 552
594 553 $row = $wpdb->get_row(
595 554 $wpdb->prepare(
596 555 "SELECT * FROM {$tables['placements']} WHERE id = %d",
@@ -600,11 +559,11 @@
600 559 );
601 560 if ( ! $row ) {
602 561 return true; // Already gone — idempotent.
603 562 }
604 - if ( ! desktop_mode_files_user_can_purge_placement( $user_id, $row ) ) {
563 + if ( ! openstation_files_user_can_purge_placement( $user_id, $row ) ) {
605 564 return new WP_Error(
606 - 'desktop_mode_files_forbidden',
565 + 'openstation_files_forbidden',
607 566 __( 'You do not have permission to delete this item.', 'desktop-mode' ),
608 567 array( 'status' => 403 )
609 568 );
610 569 }
@@ -609,32 +568,41 @@
609 568 );
610 569 }
611 570
612 571 /**
613 - * @since 0.8.0
614 - *
615 572 * @param int $placement_id
616 573 * @param int $user_id
617 574 * @param array $row
618 575 */
619 - do_action( 'desktop_mode_files_before_purge_placement', $placement_id, $user_id, $row );
576 + do_action( 'openstation_files_before_purge_placement', $placement_id, $user_id, $row );
620 577
621 578 $wpdb->delete( $tables['placements'], array( 'id' => $placement_id ), array( '%d' ) );
622 579
580 + // Mirror `openstation_files_remove()`: a purge IS a permanent
581 + // removal, so the same lifecycle action fires. Load-bearing for
582 + // the `upload` type — the stored-files listener deletes the real
583 + // bytes when the owner's last placement goes away; without this
584 + // the recycle-bin "Delete forever" path leaked them.
585 + do_action(
586 + 'openstation_file_unplaced',
587 + $placement_id,
588 + openstation_files_normalize_placement_row( $row )
589 + );
590 +
623 591 /**
624 - * @since 0.8.0
625 - *
626 592 * @param int $placement_id
627 593 * @param int $user_id
628 594 */
629 - do_action( 'desktop_mode_files_after_purge_placement', $placement_id, $user_id );
595 + do_action( 'openstation_files_after_purge_placement', $placement_id, $user_id );
630 596
631 597 return true;
632 598 }
633 599
634 -/* ================================================================== *
600 +/*
601 +================================================================== *
635 602 * Folder: trash / restore / purge (cascades to child placements).
636 - * ================================================================== */
603 + * ==================================================================
604 + */
637 605
638 606 /**
639 607 * Soft-trash a folder. Cascades to every child placement (any
640 608 * placement whose `parent_id = folder_id`), marking them with
@@ -642,19 +610,17 @@
642 610 * the same set without time-window heuristics.
643 611 *
644 612 * Idempotent on already-trashed.
645 613 *
646 - * @since 0.8.0
647 - *
648 614 * @param int $user_id
649 615 * @param int $folder_id
650 616 * @return true|WP_Error
651 617 */
652 -function desktop_mode_files_trash_folder( $user_id, $folder_id ) {
618 +function openstation_files_trash_folder( $user_id, $folder_id ) {
653 619 global $wpdb;
654 620 $user_id = (int) $user_id;
655 621 $folder_id = (int) $folder_id;
656 - $tables = desktop_mode_files_table_names();
622 + $tables = openstation_files_table_names();
657 623
658 624 $row = $wpdb->get_row(
659 625 $wpdb->prepare(
660 626 "SELECT * FROM {$tables['folders']} WHERE id = %d",
@@ -663,9 +629,9 @@
663 629 ARRAY_A
664 630 );
665 631 if ( ! $row ) {
666 632 return new WP_Error(
667 - 'desktop_mode_files_folder_not_found',
633 + 'openstation_files_folder_not_found',
668 634 __( 'Folder not found.', 'desktop-mode' ),
669 635 array( 'status' => 404 )
670 636 );
671 637 }
@@ -671,11 +637,11 @@
671 637 }
672 638 if ( null !== $row['trashed_at_ms'] && '' !== $row['trashed_at_ms'] ) {
673 639 return true;
674 640 }
675 - if ( ! desktop_mode_files_user_can_trash_folder( $user_id, $row ) ) {
641 + if ( ! openstation_files_user_can_trash_folder( $user_id, $row ) ) {
676 642 return new WP_Error(
677 - 'desktop_mode_files_forbidden',
643 + 'openstation_files_forbidden',
678 644 __( 'You do not have permission to trash this folder.', 'desktop-mode' ),
679 645 array( 'status' => 403 )
680 646 );
681 647 }
@@ -680,17 +646,15 @@
680 646 );
681 647 }
682 648
683 649 /**
684 - * @since 0.8.0
685 - *
686 650 * @param int $folder_id
687 651 * @param int $user_id
688 652 * @param array $row
689 653 */
690 - do_action( 'desktop_mode_files_before_trash_folder', $folder_id, $user_id, $row );
654 + do_action( 'openstation_files_before_trash_folder', $folder_id, $user_id, $row );
691 655
692 - $now = desktop_mode_files_now_ms();
656 + $now = openstation_files_now_ms();
693 657 // Capture the folder's own placement-chain ancestry so a future
694 658 // restore can resurrect any parent folders that got hard-deleted
695 659 // while this one was sitting in trash.
696 660 $folder_placement = $wpdb->get_row(
@@ -701,12 +665,12 @@
701 665 (string) $folder_id
702 666 ),
703 667 ARRAY_A
704 668 );
705 - $folder_ancestry = $folder_placement
706 - ? desktop_mode_files_capture_ancestry( (int) $folder_placement['parent_id'] )
669 + $folder_ancestry = $folder_placement
670 + ? openstation_files_capture_ancestry( (int) $folder_placement['parent_id'] )
707 671 : array();
708 - $folder_meta = wp_json_encode( array( 'ancestry' => $folder_ancestry ) );
672 + $folder_meta = wp_json_encode( array( 'ancestry' => $folder_ancestry ) );
709 673
710 674 // Trash the folder row.
711 675 $folder_update = $wpdb->update(
712 676 $tables['folders'],
@@ -721,9 +685,9 @@
721 685 array( '%d' )
722 686 );
723 687 if ( false === $folder_update ) {
724 688 return new WP_Error(
725 - 'desktop_mode_files_trash_failed',
689 + 'openstation_files_trash_failed',
726 690 isset( $wpdb->last_error ) && $wpdb->last_error
727 691 ? (string) $wpdb->last_error
728 692 : __( 'Failed to trash folder.', 'desktop-mode' ),
729 693 array( 'status' => 500 )
@@ -737,9 +701,9 @@
737 701 // just one child later (after the parent folder was hard-
738 702 // deleted) can still recreate the chain — same shape as a
739 703 // direct trash. Captured per-row because every child shares
740 704 // the same parent chain, so we compute once.
741 - $ancestry = desktop_mode_files_capture_ancestry( $folder_id );
705 + $ancestry = openstation_files_capture_ancestry( $folder_id );
742 706 $meta = wp_json_encode( array( 'ancestry' => $ancestry ) );
743 707 $wpdb->query(
744 708 $wpdb->prepare(
745 709 "UPDATE {$tables['placements']}
@@ -768,18 +732,16 @@
768 732 $folder_id
769 733 )
770 734 );
771 735 foreach ( (array) $child_folder_ids as $child_id ) {
772 - desktop_mode_files_trash_folder( $user_id, (int) $child_id );
736 + openstation_files_trash_folder( $user_id, (int) $child_id );
773 737 }
774 738
775 739 /**
776 - * @since 0.8.0
777 - *
778 740 * @param int $folder_id
779 741 * @param int $user_id
780 742 */
781 - do_action( 'desktop_mode_files_after_trash_folder', $folder_id, $user_id );
743 + do_action( 'openstation_files_after_trash_folder', $folder_id, $user_id );
782 744
783 745 return true;
784 746 }
785 747
@@ -788,19 +750,17 @@
788 750 * its cascade. Items that were trashed BEFORE the folder cascade
789 751 * (i.e. `trashed_via_folder IS NULL`) stay in the recycle bin —
790 752 * the user trashed them deliberately, separate from the folder.
791 753 *
792 - * @since 0.8.0
793 - *
794 754 * @param int $user_id
795 755 * @param int $folder_id
796 756 * @return true|WP_Error
797 757 */
798 -function desktop_mode_files_restore_folder( $user_id, $folder_id ) {
758 +function openstation_files_restore_folder( $user_id, $folder_id ) {
799 759 global $wpdb;
800 760 $user_id = (int) $user_id;
801 761 $folder_id = (int) $folder_id;
802 - $tables = desktop_mode_files_table_names();
762 + $tables = openstation_files_table_names();
803 763
804 764 $row = $wpdb->get_row(
805 765 $wpdb->prepare(
806 766 "SELECT * FROM {$tables['folders']} WHERE id = %d",
@@ -809,9 +769,9 @@
809 769 ARRAY_A
810 770 );
811 771 if ( ! $row ) {
812 772 return new WP_Error(
813 - 'desktop_mode_files_folder_not_found',
773 + 'openstation_files_folder_not_found',
814 774 __( 'Folder not found.', 'desktop-mode' ),
815 775 array( 'status' => 404 )
816 776 );
817 777 }
@@ -817,11 +777,11 @@
817 777 }
818 778 if ( null === $row['trashed_at_ms'] || '' === $row['trashed_at_ms'] ) {
819 779 return true;
820 780 }
821 - if ( ! desktop_mode_files_user_can_restore_folder( $user_id, $row ) ) {
781 + if ( ! openstation_files_user_can_restore_folder( $user_id, $row ) ) {
822 782 return new WP_Error(
823 - 'desktop_mode_files_forbidden',
783 + 'openstation_files_forbidden',
824 784 __( 'You do not have permission to restore this folder.', 'desktop-mode' ),
825 785 array( 'status' => 403 )
826 786 );
827 787 }
@@ -826,17 +786,15 @@
826 786 );
827 787 }
828 788
829 789 /**
830 - * @since 0.8.0
831 - *
832 790 * @param int $folder_id
833 791 * @param int $user_id
834 792 * @param array $row
835 793 */
836 - do_action( 'desktop_mode_files_before_restore_folder', $folder_id, $user_id, $row );
794 + do_action( 'openstation_files_before_restore_folder', $folder_id, $user_id, $row );
837 795
838 - $now = desktop_mode_files_now_ms();
796 + $now = openstation_files_now_ms();
839 797 // Snapshot nested folder ids BEFORE we null `trashed_via_folder`
840 798 // on the placements — that column is the only stable link from
841 799 // a child folder's placement back to the parent cascade.
842 800 $nested_ids = $wpdb->get_col(
@@ -883,12 +841,12 @@
883 841 );
884 842 if ( $folder_placement_row ) {
885 843 $origin_parent = (int) $folder_placement_row['parent_id'];
886 844 $alive = $origin_parent > 0
887 - ? desktop_mode_files_get_folder( $origin_parent, true )
845 + ? openstation_files_get_folder( $origin_parent, true )
888 846 : null;
889 847 if ( $origin_parent > 0 && ! $alive ) {
890 - $resolved = desktop_mode_files_resurrect_ancestry( $user_id, $ancestry );
848 + $resolved = openstation_files_resurrect_ancestry( $user_id, $ancestry );
891 849 $wpdb->update(
892 850 $tables['placements'],
893 851 array(
894 852 'parent_id' => $resolved,
@@ -916,9 +874,9 @@
916 874 )
917 875 );
918 876 // Recursively restore nested folders captured in the snapshot.
919 877 foreach ( (array) $nested_ids as $nid ) {
920 - desktop_mode_files_restore_folder( $user_id, (int) $nid );
878 + openstation_files_restore_folder( $user_id, (int) $nid );
921 879 }
922 880
923 881 // Enforce the "tombstones never refer to alive rows" invariant
924 882 // across the restored cohort: the folder itself, every cascade-
@@ -926,9 +884,9 @@
926 884 // folder recursed into above already clears its own. Here we
927 885 // scrub the FOLDER's own tombstones plus those of every cascade-
928 886 // restored placement so a fresh heartbeat tick can't surface
929 887 // them as `removed.*` against the now-alive rows.
930 - desktop_mode_files_clear_tombstones_for( 'folder', $folder_id );
888 + openstation_files_clear_tombstones_for( 'folder', $folder_id );
931 889 $restored_placement_ids = $wpdb->get_col(
932 890 $wpdb->prepare(
933 891 "SELECT id FROM {$tables['placements']}
934 892 WHERE trashed_via_folder IS NULL
@@ -937,18 +895,16 @@
937 895 (string) $folder_id
938 896 )
939 897 );
940 898 foreach ( (array) $restored_placement_ids as $rpid ) {
941 - desktop_mode_files_clear_tombstones_for( 'placement', (int) $rpid );
899 + openstation_files_clear_tombstones_for( 'placement', (int) $rpid );
942 900 }
943 901
944 902 /**
945 - * @since 0.8.0
946 - *
947 903 * @param int $folder_id
948 904 * @param int $user_id
949 905 */
950 - do_action( 'desktop_mode_files_after_restore_folder', $folder_id, $user_id );
906 + do_action( 'openstation_files_after_restore_folder', $folder_id, $user_id );
951 907
952 908 return true;
953 909 }
954 910
@@ -956,19 +912,17 @@
956 912 * Permanently delete a trashed folder and all its trashed-via-
957 913 * cascade child placements. Independent placements that landed in
958 914 * the trash separately stay there.
959 915 *
960 - * @since 0.8.0
961 - *
962 916 * @param int $user_id
963 917 * @param int $folder_id
964 918 * @return true|WP_Error
965 919 */
966 -function desktop_mode_files_purge_folder( $user_id, $folder_id ) {
920 +function openstation_files_purge_folder( $user_id, $folder_id ) {
967 921 global $wpdb;
968 922 $user_id = (int) $user_id;
969 923 $folder_id = (int) $folder_id;
970 - $tables = desktop_mode_files_table_names();
924 + $tables = openstation_files_table_names();
971 925
972 926 $row = $wpdb->get_row(
973 927 $wpdb->prepare(
974 928 "SELECT * FROM {$tables['folders']} WHERE id = %d",
@@ -978,11 +932,11 @@
978 932 );
979 933 if ( ! $row ) {
980 934 return true;
981 935 }
982 - if ( ! desktop_mode_files_user_can_purge_folder( $user_id, $row ) ) {
936 + if ( ! openstation_files_user_can_purge_folder( $user_id, $row ) ) {
983 937 return new WP_Error(
984 - 'desktop_mode_files_forbidden',
938 + 'openstation_files_forbidden',
985 939 __( 'You do not have permission to delete this folder.', 'desktop-mode' ),
986 940 array( 'status' => 403 )
987 941 );
988 942 }
@@ -987,15 +941,13 @@
987 941 );
988 942 }
989 943
990 944 /**
991 - * @since 0.8.0
992 - *
993 945 * @param int $folder_id
994 946 * @param int $user_id
995 947 * @param array $row
996 948 */
997 - do_action( 'desktop_mode_files_before_purge_folder', $folder_id, $user_id, $row );
949 + do_action( 'openstation_files_before_purge_folder', $folder_id, $user_id, $row );
998 950
999 951 // Cascade-revoke every share + per-user decision for the folder
1000 952 // BEFORE deleting the folder row. Without this, purge left
1001 953 // orphan `folder_shares` + `share_user_decisions` rows pointing
@@ -1001,13 +953,18 @@
1001 953 // orphan `folder_shares` + `share_user_decisions` rows pointing
1002 954 // at a folder id that no longer exists — `compute_visible_folders`
1003 955 // would still join them, and the row leak grew with every
1004 956 // recycle-bin empty. Mirrors the same cleanup
1005 - // `desktop_mode_files_delete_folder_recursive` does for the
957 + // `openstation_files_delete_folder_recursive` does for the
1006 958 // "delete from desktop" path.
959 + // `target_type` scoping is load-bearing: `folder_id` carries a
960 + // STORED-FILE id on `target_type='file'` rows, and the two id
961 + // sequences are independent — without the predicate a folder
962 + // purge wipes an unrelated user's file share that happens to
963 + // collide numerically.
1007 964 $share_ids = (array) $wpdb->get_col(
1008 965 $wpdb->prepare(
1009 - "SELECT id FROM {$tables['shares']} WHERE folder_id = %d",
966 + "SELECT id FROM {$tables['shares']} WHERE target_type = 'folder' AND folder_id = %d",
1010 967 $folder_id
1011 968 )
1012 969 );
1013 970 if ( ! empty( $share_ids ) ) {
@@ -1038,9 +995,9 @@
1038 995 (string) $folder_id
1039 996 )
1040 997 );
1041 998 foreach ( $pointing_ids as $pid ) {
1042 - desktop_mode_files_write_tombstone( 'placement', (int) $pid );
999 + openstation_files_write_tombstone( 'placement', (int) $pid );
1043 1000 }
1044 1001 if ( ! empty( $pointing_ids ) ) {
1045 1002 $placeholders = implode( ',', array_fill( 0, count( $pointing_ids ), '%d' ) );
1046 1003 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
@@ -1051,29 +1008,50 @@
1051 1008 )
1052 1009 );
1053 1010 }
1054 1011
1012 + // Upload placements among the cascade-trashed children carry
1013 + // real bytes — run the stored-files deletion contract for them
1014 + // after the rows go. Direct guarded call (not the public
1015 + // `openstation_file_unplaced` action) so cascade hook semantics
1016 + // for every other type stay unchanged.
1017 + $cascade_upload_rows = (array) $wpdb->get_results(
1018 + $wpdb->prepare(
1019 + "SELECT * FROM {$tables['placements']}
1020 + WHERE trashed_via_folder = %d AND file_type = 'upload'",
1021 + $folder_id
1022 + ),
1023 + ARRAY_A
1024 + );
1055 1025 $wpdb->delete(
1056 1026 $tables['placements'],
1057 1027 array( 'trashed_via_folder' => $folder_id ),
1058 1028 array( '%d' )
1059 1029 );
1030 + if ( function_exists( 'openstation_stored_files_handle_unplaced' ) ) {
1031 + foreach ( $cascade_upload_rows as $upload_row ) {
1032 + openstation_stored_files_handle_unplaced(
1033 + (int) $upload_row['id'],
1034 + openstation_files_normalize_placement_row( $upload_row )
1035 + );
1036 + }
1037 + }
1060 1038 $wpdb->delete( $tables['folders'], array( 'id' => $folder_id ), array( '%d' ) );
1061 1039
1062 1040 /**
1063 - * @since 0.8.0
1064 - *
1065 1041 * @param int $folder_id
1066 1042 * @param int $user_id
1067 1043 */
1068 - do_action( 'desktop_mode_files_after_purge_folder', $folder_id, $user_id );
1044 + do_action( 'openstation_files_after_purge_folder', $folder_id, $user_id );
1069 1045
1070 1046 return true;
1071 1047 }
1072 1048
1073 -/* ================================================================== *
1049 +/*
1050 +================================================================== *
1074 1051 * Recycle-bin list builder.
1075 - * ================================================================== */
1052 + * ==================================================================
1053 + */
1076 1054
1077 1055 /**
1078 1056 * Count of trashed placements + folders surfaced to the recycle bin
1079 1057 * for `$user_id`. Mirrors `_list_trashed_for_recycle_bin`'s "skip
@@ -1078,20 +1056,18 @@
1078 1056 * Count of trashed placements + folders surfaced to the recycle bin
1079 1057 * for `$user_id`. Mirrors `_list_trashed_for_recycle_bin`'s "skip
1080 1058 * cascaded children" rule so the badge matches the visible list.
1081 1059 *
1082 - * @since 0.8.0
1083 - *
1084 1060 * @param int $user_id Owner.
1085 1061 * @return int
1086 1062 */
1087 -function desktop_mode_files_count_trashed_for_recycle_bin( $user_id ) {
1063 +function openstation_files_count_trashed_for_recycle_bin( $user_id ) {
1088 1064 global $wpdb;
1089 1065 $user_id = (int) $user_id;
1090 1066 if ( $user_id <= 0 ) {
1091 1067 return 0;
1092 1068 }
1093 - $tables = desktop_mode_files_table_names();
1069 + $tables = openstation_files_table_names();
1094 1070
1095 1071 $placements = (int) $wpdb->get_var(
1096 1072 $wpdb->prepare(
1097 1073 "SELECT COUNT(*) FROM {$tables['placements']}
@@ -1100,9 +1076,9 @@
1100 1076 AND trashed_via_folder IS NULL",
1101 1077 $user_id
1102 1078 )
1103 1079 );
1104 - $folders = (int) $wpdb->get_var(
1080 + $folders = (int) $wpdb->get_var(
1105 1081 $wpdb->prepare(
1106 1082 "SELECT COUNT(*) FROM {$tables['folders']}
1107 1083 WHERE owner_id = %d AND trashed_at_ms IS NOT NULL",
1108 1084 $user_id
@@ -1115,17 +1091,15 @@
1115 1091 * Return the trashed placements + folders for a user, shaped as
1116 1092 * recycle-bin items. Used by the recycle bin's REST list endpoint
1117 1093 * to merge files-on-the-desktop trash with the WP-core trash.
1118 1094 *
1119 - * @since 0.8.0
1120 - *
1121 1095 * @param int $user_id Owner.
1122 1096 * @return array[] List of recycle-bin item shapes.
1123 1097 */
1124 -function desktop_mode_files_list_trashed_for_recycle_bin( $user_id ) {
1098 +function openstation_files_list_trashed_for_recycle_bin( $user_id ) {
1125 1099 global $wpdb;
1126 1100 $user_id = (int) $user_id;
1127 - $tables = desktop_mode_files_table_names();
1101 + $tables = openstation_files_table_names();
1128 1102 $out = array();
1129 1103
1130 1104 // Trashed placements owned by this user.
1131 1105 $placements = $wpdb->get_results(
@@ -1142,20 +1116,22 @@
1142 1116 // the whole bundle in the recycle bin.
1143 1117 if ( ! empty( $row['trashed_via_folder'] ) ) {
1144 1118 continue;
1145 1119 }
1146 - $file = function_exists( 'desktop_mode_resolve_file' )
1147 - ? desktop_mode_resolve_file( $row['file_type'], $row['file_ref'] )
1120 + $file = function_exists( 'openstation_resolve_file' )
1121 + ? openstation_resolve_file( $row['file_type'], $row['file_ref'] )
1148 1122 : null;
1149 - $title = $file ? (string) $file->title() : (string) $row['file_type'];
1123 + $title = $file
1124 + ? openstation_plain_text_title( $file->title() )
1125 + : (string) $row['file_type'];
1150 1126 $icon = $file ? (string) $file->icon() : 'dashicons-no-alt';
1151 1127 // Two recycle-bin buckets:
1152 - // - `shortcut` → plugin-registered icons (file_type='shortcut')
1153 - // - `placement` → every other placement (post / page /
1154 - // attachment / user / term / comment / …)
1128 + // - `shortcut` → plugin-registered icons (file_type='shortcut')
1129 + // - `placement` → every other placement (post / page /
1130 + // attachment / user / term / comment / …)
1155 1131 // Lets the bin's type-filter tabs split "Shortcuts" from
1156 1132 // "Files" without overloading either label.
1157 - $bucket = ( 'shortcut' === (string) $row['file_type'] )
1133 + $bucket = ( 'shortcut' === (string) $row['file_type'] )
1158 1134 ? 'shortcut'
1159 1135 : 'placement';
1160 1136 $subtitle = ( 'shortcut' === $bucket )
1161 1137 ? __( 'Desktop shortcut', 'desktop-mode' )
@@ -1180,10 +1156,10 @@
1180 1156 'icon' => $icon,
1181 1157 'deleted_at' => gmdate( 'c', (int) round( (int) $row['trashed_at_ms'] / 1000 ) ),
1182 1158 'deleted_by' => '',
1183 1159 'deleted_by_id' => (int) $row['trashed_by'],
1184 - 'can_restore' => desktop_mode_files_user_can_restore_placement( $user_id, $row ),
1185 - 'can_purge' => desktop_mode_files_user_can_purge_placement( $user_id, $row ),
1160 + 'can_restore' => openstation_files_user_can_restore_placement( $user_id, $row ),
1161 + 'can_purge' => openstation_files_user_can_purge_placement( $user_id, $row ),
1186 1162 'edit_link' => '',
1187 1163 );
1188 1164 if ( 'link' === (string) $row['file_type'] ) {
1189 1165 $item['type_label'] = __( 'URL', 'desktop-mode' );
@@ -1208,9 +1184,9 @@
1208 1184 WHERE trashed_via_folder = %d",
1209 1185 (int) $row['id']
1210 1186 )
1211 1187 );
1212 - $out[] = array(
1188 + $out[] = array(
1213 1189 'id' => (int) $row['id'],
1214 1190 'type' => 'folder',
1215 1191 'title' => (string) $row['name'],
1216 1192 'subtitle' => $child_count > 0
@@ -1225,10 +1201,10 @@
1225 1201 'icon' => 'dashicons-portfolio',
1226 1202 'deleted_at' => gmdate( 'c', (int) round( (int) $row['trashed_at_ms'] / 1000 ) ),
1227 1203 'deleted_by' => '',
1228 1204 'deleted_by_id' => (int) $row['trashed_by'],
1229 - 'can_restore' => desktop_mode_files_user_can_restore_folder( $user_id, $row ),
1230 - 'can_purge' => desktop_mode_files_user_can_purge_folder( $user_id, $row ),
1205 + 'can_restore' => openstation_files_user_can_restore_folder( $user_id, $row ),
1206 + 'can_purge' => openstation_files_user_can_purge_folder( $user_id, $row ),
1231 1207 'edit_link' => '',
1232 1208 );
1233 1209 }
1234 1210
@@ -1239,9 +1215,9 @@
1239 1215 if ( $uid <= 0 ) {
1240 1216 continue;
1241 1217 }
1242 1218 if ( ! isset( $user_cache[ $uid ] ) ) {
1243 - $u = get_userdata( $uid );
1219 + $u = get_userdata( $uid );
1244 1220 $user_cache[ $uid ] = $u ? $u->display_name : '';
1245 1221 }
1246 1222 $item['deleted_by'] = $user_cache[ $uid ];
1247 1223 }