From 1dd70e99f02b1c8ae538b2c8b8be013dbc834e8a Mon Sep 17 00:00:00 2001 From: Mehbub Rashid Date: Sat, 6 Jul 2024 13:46:47 +0600 Subject: [PATCH] Fix the remote source folder structure if necessary. It re-structures and corrects the folder/zip structure of the extracted remote zip folder - if not correct already. --- Puc/v5p4/UpdateChecker.php | 71 ++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/Puc/v5p4/UpdateChecker.php b/Puc/v5p4/UpdateChecker.php index 8833547..890f581 100644 --- a/Puc/v5p4/UpdateChecker.php +++ b/Puc/v5p4/UpdateChecker.php @@ -924,23 +924,66 @@ if ( !class_exists(UpdateChecker::class, false) ): return $source; } + // Fix the remote source structure if necessary. + //The update archive should contain a single directory that contains the rest of plugin/theme files. + //Otherwise, WordPress will try to copy the entire working directory ($source == $remoteSource). + //We can't rename $remoteSource because that would break WordPress code that cleans up temporary files + //after update. + if ( $this->isBadDirectoryStructure($remoteSource) ) { + + // Create a new folder using plugin slug. + $new_directory = trailingslashit( $remoteSource ) . $this->slug . '/'; + + if ( ! $wp_filesystem->is_dir( $new_directory ) ) { + $wp_filesystem->mkdir( $new_directory ); + + // Move all files inside newly created directory. + $sourceFiles = $wp_filesystem->dirlist($remoteSource); + if ( is_array($sourceFiles) ) { + $sourceFiles = array_keys($sourceFiles); + $allMoved = true; + foreach ($sourceFiles as $filename) { + + // Skip for our newly created folder. + if ( $filename === $this->slug ) { + continue; + } + + $previousSource = trailingslashit( $remoteSource ) . $filename; + $newSource = trailingslashit( $new_directory ) . $filename; + + if ( !$wp_filesystem->move($previousSource, $newSource, true) ) { + $allMoved = false; + break; + } + } + + if ( $allMoved ) { + // Rename source. + $source = $new_directory; + } + else { + // Delete our newly created folder including all files in it. + $wp_filesystem->rmdir( $new_directory, true ); + + // And return a relevant error. + return new WP_Error( + 'puc-incorrect-directory-structure', + sprintf( + 'The directory structure of the update was incorrect. All files should be inside ' . + 'a directory named %s, not at the root of the ZIP archive. Plugin Update Checker tried to fix the directory structure, but failed.', + htmlentities($this->slug) + ) + ); + } + } + } + } + //Rename the source to match the existing directory. $correctedSource = trailingslashit($remoteSource) . $this->directoryName . '/'; if ( $source !== $correctedSource ) { - //The update archive should contain a single directory that contains the rest of plugin/theme files. - //Otherwise, WordPress will try to copy the entire working directory ($source == $remoteSource). - //We can't rename $remoteSource because that would break WordPress code that cleans up temporary files - //after update. - if ( $this->isBadDirectoryStructure($remoteSource) ) { - return new WP_Error( - 'puc-incorrect-directory-structure', - sprintf( - 'The directory structure of the update is incorrect. All files should be inside ' . - 'a directory named %s, not at the root of the ZIP archive.', - htmlentities($this->slug) - ) - ); - } + /** @var \WP_Upgrader_Skin $upgrader ->skin */ $upgrader->skin->feedback(sprintf(