Last active
April 7, 2022 23:42
-
-
Save mejta/162c54ef859801d5dff8d2b01a91153f to your computer and use it in GitHub Desktop.
Script that cleans unused files in WordPress uploads folder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Find WordPress wp-blog-header.php file. | |
| * | |
| * @param string $folder | |
| * | |
| * @return string | |
| */ | |
| function find_blog_header( string $folder ): string { | |
| $folder = rtrim( $folder, '/' ); | |
| $count = 0; | |
| while ( $count < 20 ) { | |
| if ( file_exists( $folder . '/wp-blog-header.php' ) ) { | |
| return $folder . '/wp-blog-header.php'; | |
| } | |
| if ( file_exists( $folder . '/wp/wp-blog-header.php' ) ) { | |
| return $folder . '/wp/wp-blog-header.php'; | |
| } | |
| $folder = dirname( $folder ); | |
| $count ++; | |
| } | |
| return ''; | |
| } | |
| /** | |
| * Find uploads folder. | |
| * | |
| * @return string | |
| */ | |
| function find_uploads_folder(): string { | |
| $upload_dir = wp_upload_dir(); | |
| return $upload_dir['basedir']; | |
| } | |
| /** | |
| * Get the SQL dump from the database. | |
| * | |
| * @return string | |
| */ | |
| function get_sql_dump(): string { | |
| $destination = sys_get_temp_dir() . '/' . wp_generate_uuid4() . '.sql'; | |
| if ( file_exists( $destination ) ) { | |
| unlink( $destination ); | |
| } | |
| exec( "mysqldump --user=" . DB_USER . " --password=" . DB_PASSWORD . " --host=" . DB_HOST . " " . DB_NAME . " > " . $destination ); | |
| $dump = file_get_contents( $destination ); | |
| unlink( $destination ); | |
| return $dump; | |
| } | |
| /** | |
| * Get the file count in folder. | |
| * | |
| * @param $path | |
| * | |
| * @return int | |
| */ | |
| function get_file_count( $path ): int { | |
| $size = 0; | |
| $ignore = array( '.', '..', '.DS_Store' ); | |
| $files = scandir( $path ); | |
| foreach ( $files as $t ) { | |
| if ( in_array( $t, $ignore ) ) { | |
| continue; | |
| } elseif ( is_dir( rtrim( $path, '/' ) . '/' . $t ) ) { | |
| $size += get_file_count( rtrim( $path, '/' ) . '/' . $t ); | |
| } else { | |
| $size ++; | |
| } | |
| } | |
| return $size; | |
| } | |
| /** | |
| * Removes empty folders recursively. | |
| * | |
| * @param $path | |
| * | |
| * @return bool | |
| */ | |
| function remove_empty_folders( $path ): bool { | |
| $empty = true; | |
| foreach ( glob( $path . DIRECTORY_SEPARATOR . '*' ) as $file ) { | |
| if ( is_dir( $file ) ) { | |
| if ( ! remove_empty_folders( $file ) ) { | |
| $empty = false; | |
| } | |
| } else { | |
| $empty = false; | |
| } | |
| } | |
| if ( $empty ) { | |
| @rmdir( $path ); | |
| } | |
| return $empty; | |
| } | |
| /** | |
| * Walk through the uploads folder and run callback on each file. | |
| * | |
| * @param string $dir | |
| * @param callable $callback | |
| */ | |
| function walk_all_files( string $dir, callable $callback ): void { | |
| $root = scandir( $dir ); | |
| foreach ( $root as $value ) { | |
| if ( $value === '.' || $value === '..' ) { | |
| continue; | |
| } | |
| if ( is_file( $dir . DIRECTORY_SEPARATOR . $value ) ) { | |
| $callback( $dir . DIRECTORY_SEPARATOR . $value, $dir ); | |
| continue; | |
| } | |
| walk_all_files( $dir . DIRECTORY_SEPARATOR . $value, $callback ); | |
| } | |
| } | |
| $blog_header = find_blog_header( __DIR__ ); | |
| if ( empty( $blog_header ) ) { | |
| die( "Could not find WordPress root folder." ); | |
| } | |
| const WP_USE_THEMES = false; | |
| $_SERVER['HTTP_HOST'] = null; | |
| $_SERVER['REQUEST_METHOD'] = 'GET'; | |
| echo "\nIncluding WordPress...\n"; | |
| require $blog_header; | |
| echo "\nRequesting database dump...\n"; | |
| $dump = get_sql_dump(); | |
| $uploads = find_uploads_folder(); | |
| echo "\nProcessing files...\n"; | |
| $file_count = get_file_count( $uploads ); | |
| $process = 0; | |
| $percent = $process / $file_count * 100; | |
| $width = 50; | |
| $bar = floor( $width / 100 * $percent ); | |
| $deleted = 0; | |
| echo "[ " . str_repeat( "=", $bar ) . ">" . str_repeat( " ", $width - $bar ) . " ] " . round( $percent, 2 ) . "% (" . $process . "/" . $file_count . ")"; | |
| walk_all_files( $uploads, function ( string $file ) use ( $uploads, $dump, &$process, $width, &$bar, &$percent, $file_count, &$deleted ) { | |
| $process ++; | |
| $percent = $process / $file_count * 100; | |
| $bar = floor( $width / 100 * $percent ); | |
| echo "\033[0G\033[2K[ " . str_repeat( "=", $bar ) . ">" . str_repeat( " ", $width - $bar ) . " ] " . round( $percent, 2 ) . "% (" . $process . "/" . $file_count . ")"; | |
| if ( preg_match( "~[0-9]{4}/[0-9]{2}/(?<filename>[^/]+$)~m", $file, $matches ) ) { | |
| if ( mb_strpos( $dump, $matches['filename'] ) === false ) { | |
| if ( unlink( $file ) ) { | |
| $deleted ++; | |
| } else { | |
| echo " > could not remove " . $file . "\n"; | |
| } | |
| } | |
| } | |
| } ); | |
| echo "\033[0G\033[2K > deleted " . $deleted . " files\n"; | |
| echo "\nRemoving empty folders...\n"; | |
| remove_empty_folders( $uploads ); | |
| echo "\nFinished!\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage:
php clean-wordpress-uploads.php