PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.13
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.13
1.1.13 1.1.12 1.1.11 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 All 37 releases
← All changes | includes/desktop-files/store.php +40 -43 1.1.2 → 1.1.13 View file →
@@ -118,11 +118,20 @@
118 118 // `<div class="wpdberror">…</div>` to the REST response body and
119 119 // break `await response.json()` on the client. `$wpdb->last_error`
120 120 // still holds the message, so genuine DB failures surface via the
121 121 // `WP_Error` we return when no existing row is found.
122 - $prev_suppress = $wpdb->suppress_errors( true );
123 - $ok = $wpdb->insert( $tables['placements'], $row, array( '%d', '%d', '%d', '%s', '%s', '%d', '%d', '%d', '%d', '%s' ) );
124 - $wpdb->suppress_errors( $prev_suppress );
122 + $insert = static function () use ( $tables, $row ) {
123 + global $wpdb;
124 + $prev_suppress = $wpdb->suppress_errors( true );
125 + $ok = $wpdb->insert( $tables['placements'], $row, array( '%d', '%d', '%d', '%s', '%s', '%d', '%d', '%d', '%d', '%s' ) );
126 + $wpdb->suppress_errors( $prev_suppress );
127 + return array( $ok, (int) $wpdb->insert_id );
128 + };
129 + $result = 'upload' === $type ? openstation_stored_files_place_insert( $ref, $insert ) : $insert();
130 + if ( is_wp_error( $result ) ) {
131 + return $result;
132 + }
133 + list( $ok, $id ) = $result;
125 134 if ( false === $ok ) {
126 135 // Disambiguate the two cases hidden behind a generic `false`:
127 136 // (a) The `placement_unique` index collided
128 137 // with an existing row for this (user, parent, type,
@@ -187,10 +196,8 @@
187 196 }
188 197
189 198 return $existing_id;
190 199 }
191 - $id = (int) $wpdb->insert_id;
192 -
193 200 $row['id'] = $id;
194 201
195 202 /**
196 203 * Fires after a placement is created.
@@ -530,13 +537,14 @@
530 537 $args = (array) apply_filters( 'openstation_files_query_args', $args, $user_id, $parent_id );
531 538
532 539 // Active queries always exclude trashed rows. Recycle-bin
533 540 // callers reach for the dedicated trash store.
534 - if ( ! empty( $args['share_view'] ) ) {
535 - // Shared sub-folder — return every placement in the folder
536 - // regardless of which user originally placed it. The icons
537 - // are part of the folder; the owner_id column is audit info,
538 - // not a permission gate.
541 + if ( ! empty( $args['share_view'] ) || (int) $args['parent_id'] > 0 ) {
542 + // A sub-folder, the viewer's own or shared with them: return
543 + // every placement in it regardless of which user placed it,
544 + // so the owner of a shared folder sees what a writer added.
545 + // The icons are part of the folder; the owner_id column is
546 + // audit info, not a permission gate.
539 547 $rows = $wpdb->get_results(
540 548 $wpdb->prepare(
541 549 "SELECT * FROM {$tables['placements']}
542 550 WHERE parent_id = %d
@@ -567,11 +575,11 @@
567 575 foreach ( $rows as $row ) {
568 576 $normalized = openstation_files_normalize_placement_row( $row );
569 577 $file = openstation_resolve_file( $normalized['file_type'], $normalized['file_ref'] );
570 578 if ( empty( $args['share_view'] ) ) {
571 - // Private folder / desktop root — keep the existing
572 - // per-row read filter so stale/inaccessible entities
573 - // don't clutter the user's own view.
579 + // The viewer's own folder or desktop root: keep the
580 + // per-row read filter so stale or inaccessible entities,
581 + // a writer's included, don't clutter the user's own view.
574 582 if ( $file && ! $file->can_read( $user_id ) ) {
575 583 continue;
576 584 }
577 585 } elseif ( $file && ! $file->can_read( $user_id ) ) {
@@ -604,10 +612,12 @@
604 612 * on first hydrate so plugin shortcuts behave like any
605 613 * other tile (drag, sort, right-click, clean up).
606 614 *
607 615 * Idempotent on both axes: a folder/shortcut that already has
608 - * any placement is left alone. Coordinates use the column-major
609 - * grid that `src/desktop-files/grid.ts` mirrors on the JS side.
616 + * any placement is left alone. Coordinates come from
617 + * `includes/desktop-files/grid.php`, which mirrors
618 + * `src/desktop-files/grid.ts` — pitch, reading order, and the
619 + * assumed canvas the scan wraps at.
610 620 *
611 621 * Called by the placements list endpoint when the requested
612 622 * folder is the root (`parent_id=0`).
613 623 *
@@ -682,10 +692,11 @@
682 692 }
683 693
684 694 // Build an occupied set from EXISTING root placements so
685 695 // we never drop an orphan on top of a tile the user
686 - // already has. Cell math mirrors `src/desktop-files/grid.ts`
687 - // (padding 16 + col 96 + row 110).
696 + // already has. Cell math lives in
697 + // `includes/desktop-files/grid.php`, the mirror of
698 + // `src/desktop-files/grid.ts`.
688 699 $existing = $wpdb->get_results(
689 700 $wpdb->prepare(
690 701 "SELECT x, y FROM {$tables['placements']}
691 702 WHERE owner_id = %d
@@ -694,30 +705,19 @@
694 705 $user_id
695 706 ),
696 707 ARRAY_A
697 708 );
698 - $occupied = array();
699 - foreach ( (array) $existing as $row ) {
700 - $col = max( 0, (int) round( ( (int) $row['x'] - 16 ) / 96 ) );
701 - $row_idx = max( 0, (int) round( ( (int) $row['y'] - 16 ) / 110 ) );
702 - $occupied[ "$col,$row_idx" ] = true;
703 - }
709 + $occupied = openstation_files_grid_occupied( $existing );
704 710
705 - $find_next = function () use ( &$occupied ) {
706 - for ( $col = 0; $col < 999; $col++ ) {
707 - for ( $row = 0; $row < 999; $row++ ) {
708 - $key = "$col,$row";
709 - if ( ! isset( $occupied[ $key ] ) ) {
710 - $occupied[ $key ] = true;
711 - return array( $col, $row );
712 - }
713 - }
714 - }
715 - return array( 0, 0 );
716 - };
711 + // The desktop reads in columns, and the scan wraps to the next one
712 + // at the assumed canvas height rather than running a column 999
713 + // cells deep. The server has no viewport; a slot it invents below
714 + // the fold is a tile the user cannot reach, because the layer that
715 + // renders it does not scroll.
716 + $order = openstation_files_grid_order( 0 );
717 717
718 - $placed = 0;
719 - $emit_at = function ( $type, $ref, $col, $row ) use ( $user_id, &$occupied, &$placed ) {
718 + $placed = 0;
719 + $emit_at = function ( $type, $ref, $col, $row ) use ( $user_id, &$occupied, &$placed ) {
720 720 $occupied[ "$col,$row" ] = true;
721 721 $result = openstation_files_place(
722 722 $user_id,
723 723 0,
@@ -722,19 +722,16 @@
722 722 $user_id,
723 723 0,
724 724 $type,
725 725 (string) $ref,
726 - array(
727 - 'x' => 16 + $col * 96,
728 - 'y' => 16 + $row * 110,
729 - )
726 + openstation_files_grid_cell_to_point( $col, $row )
730 727 );
731 728 if ( ! is_wp_error( $result ) ) {
732 729 ++$placed;
733 730 }
734 731 };
735 - $emit_next = function ( $type, $ref ) use ( $find_next, $emit_at ) {
736 - list( $col, $row ) = $find_next();
732 + $emit_next = function ( $type, $ref ) use ( &$occupied, $order, $emit_at ) {
733 + list( $col, $row ) = openstation_files_grid_next_free( $occupied, $order );
737 734 $emit_at( $type, $ref, $col, $row );
738 735 };
739 736
740 737 // Pinned shortcuts get reserved top-left slots. Anchored to