PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.12
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.12
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 0.8.9 All 36 releases
← All changes | includes/desktop-files/stored-files-store.php +28 -82 1.1.2 → 1.1.12 View file →
@@ -163,8 +163,36 @@
163 163 * @param array $args `display_name`, `disk_name`, `size_bytes`, `mime`.
164 164 * @return int|WP_Error Row id.
165 165 */
166 166 function openstation_stored_files_create( $owner_id, $args ) {
167 + $id = openstation_stored_files_locked(
168 + static function () use ( $owner_id, $args ) {
169 + return openstation_stored_files_create_locked( $owner_id, $args );
170 + }
171 + );
172 + if ( ! is_wp_error( $id ) ) {
173 + /**
174 + * Fires after a stored-file row is created (bytes are already
175 + * on disk at this point).
176 + *
177 + * @param int $id Stored-file id.
178 + * @param int $owner_id Owner.
179 + */
180 + do_action( 'openstation_stored_file_created', $id, (int) $owner_id );
181 +
182 + }
183 + return $id;
184 +}
185 +
186 +/**
187 + * Insert a stored-file row while holding the reconciliation lock.
188 + *
189 + * @internal
190 + * @param int $owner_id Owner.
191 + * @param array $args Stored-file attributes.
192 + * @return int|WP_Error
193 + */
194 +function openstation_stored_files_create_locked( $owner_id, $args ) {
167 195 global $wpdb;
168 196 $owner_id = (int) $owner_id;
169 197 if ( $owner_id <= 0 ) {
170 198 return new WP_Error( 'openstation_stored_files_invalid_user', __( 'A user id is required.', 'desktop-mode' ), array( 'status' => 400 ) );
@@ -205,17 +233,8 @@
205 233 return new WP_Error( 'openstation_stored_files_insert_failed', __( 'Failed to record the uploaded file.', 'desktop-mode' ), array( 'status' => 500 ) );
206 234 }
207 235 $id = (int) $wpdb->insert_id;
208 236
209 - /**
210 - * Fires after a stored-file row is created (bytes are already
211 - * on disk at this point).
212 - *
213 - * @param int $id Stored-file id.
214 - * @param int $owner_id Owner.
215 - */
216 - do_action( 'openstation_stored_file_created', $id, $owner_id );
217 -
218 237 return $id;
219 238 }
220 239
221 240 /**
@@ -586,82 +605,9 @@
586 605 openstation_stored_files_purge( $file_id );
587 606 }
588 607 add_action( 'openstation_file_unplaced', 'openstation_stored_files_handle_unplaced', 10, 2 );
589 608
590 -/**
591 - * Daily reconciliation sweep, both directions:
592 - *
593 - * Two classes of orphan get collected:
594 - *
595 - * a) Rows with no placement at all (crashed uploads, interrupted
596 - * purges) older than the grace period → delete row + bytes.
597 - * b) Bytes on disk with no matching row (interrupted deletes)
598 - * whose mtime is older than the grace period → delete bytes.
599 - *
600 - * Rows whose bytes are missing are left alone — `exists()` still
601 - * renders the tile so the user can see and remove it.
602 - */
603 -function openstation_stored_files_reconcile() {
604 - global $wpdb;
605 - $tables = openstation_files_table_names();
606 - $grace = DAY_IN_SECONDS;
607 609
608 - // a) Placement-less rows past grace.
609 - $cutoff_ms = openstation_files_now_ms() - ( $grace * 1000 );
610 - $orphans = $wpdb->get_col(
611 - $wpdb->prepare(
612 - "SELECT sf.id FROM {$tables['stored_files']} sf
613 - LEFT JOIN {$tables['placements']} p
614 - ON p.file_type = 'upload'
615 - AND p.file_ref = CAST( sf.id AS CHAR )
616 - WHERE p.id IS NULL
617 - AND sf.created_at_ms < %d",
618 - $cutoff_ms
619 - )
620 - );
621 - foreach ( (array) $orphans as $orphan_id ) {
622 - openstation_stored_files_delete( (int) $orphan_id );
623 - }
624 -
625 - // b) Row-less bytes past grace. The flat layout makes this a
626 - // two-level scan: <base>/<user_id>/<disk_name>.
627 - $base = openstation_stored_files_dir();
628 - if ( ! is_dir( $base ) ) {
629 - return;
630 - }
631 - $user_dirs = glob( $base . '/*', GLOB_ONLYDIR );
632 - foreach ( (array) $user_dirs as $user_dir ) {
633 - $owner_id = (int) basename( $user_dir );
634 - if ( $owner_id <= 0 ) {
635 - continue;
636 - }
637 - $known = $wpdb->get_col(
638 - $wpdb->prepare(
639 - "SELECT disk_name FROM {$tables['stored_files']} WHERE owner_id = %d",
640 - $owner_id
641 - )
642 - );
643 - $known_set = array_flip( array_map( 'strval', (array) $known ) );
644 - $entries = glob( $user_dir . '/*' );
645 - foreach ( (array) $entries as $entry ) {
646 - $name = basename( $entry );
647 - if ( 'index.php' === $name || ! is_file( $entry ) ) {
648 - continue;
649 - }
650 - if ( isset( $known_set[ $name ] ) ) {
651 - continue;
652 - }
653 - if ( ! openstation_stored_files_valid_disk_name( $name ) ) {
654 - continue; // Not ours — leave foreign files alone.
655 - }
656 - $mtime = (int) filemtime( $entry );
657 - if ( $mtime > 0 && ( time() - $mtime ) > $grace ) {
658 - wp_delete_file( $entry );
659 - }
660 - }
661 - }
662 -}
663 -add_action( 'desktop_mode_files_daily_prune', 'openstation_stored_files_reconcile' );
664 610
665 611 /**
666 612 * When a WordPress user is deleted, purge their stored files (rows,
667 613 * bytes, shares, recipient placements) and remove their directory.