ages(); $dropped = []; foreach ( $this->staged_tables() as $table ) { if ( isset( $live[ $table ] ) || ! isset( $ages[ $table ] ) || $ages[ $table ] < $min_age_seconds ) { continue; } $this->drop( $table ); $dropped[] = $table; } return $dropped; } /** @return string[] Staging tables that exist, each checked against the exact stem. */ private function staged_tables(): array { $stem = (string) $this->wpdb->prefix . 'shiftora_stg_'; $wpdb = $this->wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- server metadata, nothing to cache $found = (array) $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $stem ) . '%' ) ); return array_values( array_filter( array_map( 'strval', $found ), static fn( string $table ): bool => str_starts_with( $table, $stem ) ) ); } /** @return array Seconds since each staging table was created, per the server's own clock. */ private function ages(): array { $wpdb = $this->wpdb; $stem = (string) $wpdb->prefix . 'shiftora_stg_'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- server metadata, nothing to cache $rows = (array) $wpdb->get_results( $wpdb->prepare( 'SELECT TABLE_NAME, TIMESTAMPDIFF( SECOND, CREATE_TIME, NOW() ) AS age FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE %s AND CREATE_TIME IS NOT NULL', $wpdb->esc_like( $stem ) . '%' ), ARRAY_A ); $ages = []; foreach ( $rows as $row ) { if ( isset( $row['TABLE_NAME'], $row['age'] ) && is_numeric( $row['age'] ) ) { $ages[ (string) $row['TABLE_NAME'] ] = (int) $row['age']; } } return $ages; } private function drop( string $table ): void { $wpdb = $this->wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- the transfer reads and writes the site's own tables, a cached copy would be stale $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $table ) ); } }