Filesystem API: Attempt to create directory in copy_dir().

Adds a check to the start of `copy_dir()` that the destination directory exists and attempts to create it if it does not.

An error is returned if the directory can not be created, either due to a permissions error or the parent directory not existing.

Props caraffande, costdev, zunaid321.
Fixes #41855.



git-svn-id: https://develop.svn.wordpress.org/trunk@55938 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Peter Wilson 2023-06-19 01:58:25 +00:00
parent 1e090291f0
commit 7cfc7a46f9
2 changed files with 91 additions and 0 deletions

View File

@ -1910,6 +1910,14 @@ function copy_dir( $from, $to, $skip_list = array() ) {
$from = trailingslashit( $from );
$to = trailingslashit( $to );
if ( ! $wp_filesystem->exists( $to ) && ! $wp_filesystem->mkdir( $to ) ) {
return new WP_Error(
'mkdir_destination_failed_copy_dir',
__( 'Could not create the destination directory.' ),
basename( $to )
);
}
foreach ( (array) $dirlist as $filename => $fileinfo ) {
if ( in_array( $filename, $skip_list, true ) ) {
continue;

View File

@ -0,0 +1,83 @@
<?php
/**
* Tests copy_dir().
*
* @group file.php
*
* @covers ::copy_dir
*/
class Tests_Filesystem_CopyDir extends WP_UnitTestCase {
/**
* The test directory.
*
* @var string $test_dir
*/
private static $test_dir;
/**
* Sets up the filesystem and test directory before any tests run.
*/
public static function set_up_before_class() {
parent::set_up_before_class();
require_once ABSPATH . 'wp-admin/includes/file.php';
WP_Filesystem();
self::$test_dir = get_temp_dir() . 'copy_dir/';
}
/**
* Sets up the test directory before each test.
*/
public function set_up() {
global $wp_filesystem;
parent::set_up();
// Create the root directory.
$wp_filesystem->mkdir( self::$test_dir );
}
/**
* Removes the test directory after each test.
*/
public function tear_down() {
global $wp_filesystem;
// Delete the root directory and its contents.
$wp_filesystem->delete( self::$test_dir, true );
parent::tear_down();
}
/**
* Tests that the destination is created if it does not already exist.
*
* @ticket 41855
*/
public function test_should_create_destination_it_if_does_not_exist() {
global $wp_filesystem;
$from = self::$test_dir . 'folder1/folder2/';
$to = self::$test_dir . 'folder3/folder2/';
// Create the file structure for the test.
$wp_filesystem->mkdir( self::$test_dir . 'folder1' );
$wp_filesystem->mkdir( self::$test_dir . 'folder3' );
$wp_filesystem->mkdir( $from );
$wp_filesystem->touch( $from . 'file1.txt' );
$wp_filesystem->mkdir( $from . 'subfolder1' );
$wp_filesystem->touch( $from . 'subfolder1/file2.txt' );
$this->assertTrue( copy_dir( $from, $to ), 'copy_dir() failed.' );
$this->assertDirectoryExists( $to, 'The destination was not created.' );
$this->assertFileExists( $to . 'file1.txt', 'The destination file was not created.' );
$this->assertDirectoryExists( $to . 'subfolder1/', 'The destination subfolder was not created.' );
$this->assertFileExists( $to . 'subfolder1/file2.txt', 'The destination subfolder file was not created.' );
}
}