$keep Package ids a job still points at. * @return void */ public static function sweep_unused( array $keep ): void { $dir = self::dir(); if ( is_wp_error( $dir ) ) { return; } foreach ( (array) glob( $dir . '*.zip' ) as $zip ) { if ( is_string( $zip ) && ! in_array( basename( $zip, '.zip' ), $keep, true ) && filemtime( $zip ) < time() - DAY_IN_SECONDS ) { wp_delete_file( $zip ); } } } /** * Delete a stored package, and any part file an unfinished upload of it left. * * @param string $package_id Package id. * @return void */ public static function delete( string $package_id ): void { $path = self::path( $package_id ); if ( is_wp_error( $path ) ) { return; } foreach ( array( $path, substr( $path, 0, -4 ) . '.part' ) as $file ) { if ( is_file( $file ) ) { wp_delete_file( $file ); } } } /** * The readable name a job's package is offered under. * * Packages sit on disk as a hash. Module exports record a name at start; * older and whole-site records get one built from the source and date. * * @param array $record Job record. * @return string */ public static function display_name( array $record ): string { if ( '' !== (string) ( $record['package_name'] ?? '' ) ) { return (string) $record['package_name']; } $stamp = strtotime( (string) ( $record['created_at'] ?? '' ) ); return sanitize_file_name( ( $record['module_id'] ?? $record['kind'] ?? 'package' ) . '-' . gmdate( 'Y-m-d-His', $stamp ? $stamp : time() ) . '.zip' ); } /** * Where a package sits, relative to the WordPress root, for display only. * * @param string $package_id Package id. * @return string Empty when the package is not stored. */ public static function relative_path( string $package_id ): string { if ( ! self::exists( $package_id ) ) { return ''; } return ltrim( str_replace( wp_normalize_path( ABSPATH ), '', wp_normalize_path( (string) self::path( $package_id ) ) ), '/' ); } /** * Write the guard files if they are missing. * * @param string $dir Trailing-slashed directory to close to the web. * @return void */ public static function guard( string $dir ): void { $guards = array( 'index.php' => " "Require all denied\n\nDeny from all\n\n", 'web.config' => "\n\n", ); foreach ( $guards as $name => $contents ) { if ( ! file_exists( $dir . $name ) ) { file_put_contents( $dir . $name, $contents ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents -- direct file I/O; WP_Filesystem needs credentials a REST request does not have. } } } }