get_base_directory() . '/' . wp_generate_uuid4(); if ( ! wp_mkdir_p( $directory ) ) { throw new SyncException( esc_html__( 'A temporary working directory could not be created.', 'cherrylift' ) ); } // Packages hold unpublished content: keep them private to this system user (shared hosting). $this->filesystem()->chmod( $directory, 0700 ); return $directory; } /** * Recursively deletes a working directory. Refuses paths outside the base directory. * * @param string $directory Absolute path of a directory returned by create_directory(). * @return bool Whether the directory was deleted. */ public function delete( string $directory ): bool { $base = realpath( $this->get_base_directory() ); $path = realpath( $directory ); if ( false === $base || false === $path || 0 !== strpos( $path, $base . DIRECTORY_SEPARATOR ) ) { return false; } return $this->filesystem()->delete( $path, true ); } /** * Cron callback for the daily cleanup. * * @return void */ public function run_scheduled_cleanup(): void { $this->cleanup_expired(); } /** * Deletes working directories older than the configured lifetime. * * @return int Number of directories deleted. */ public function cleanup_expired(): int { $base = $this->get_base_directory(); if ( ! is_dir( $base ) ) { return 0; } /** * Filters how long temporary files are kept before cleanup: working directories, uploaded packages and WP-CLI exports. * * @since 0.2.0 * * @param int $lifetime Lifetime in seconds. Default one day. */ $lifetime = apply_filters( 'cherrylift_temp_file_lifetime', DAY_IN_SECONDS ); $lifetime = is_int( $lifetime ) && $lifetime > 0 ? $lifetime : DAY_IN_SECONDS; $deleted = 0; $entries = $this->filesystem()->dirlist( $base, false ); foreach ( is_array( $entries ) ? $entries : array() as $name => $entry ) { if ( 'd' !== $entry['type'] || (int) $entry['lastmodunix'] > time() - $lifetime ) { continue; } if ( $this->delete( $base . '/' . $name ) ) { ++$deleted; } } return $deleted; } /** * Returns a direct filesystem instance. Only used for our own temp files. * * @return WP_Filesystem_Direct */ private function filesystem(): WP_Filesystem_Direct { require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php'; return new WP_Filesystem_Direct( null ); } }