Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/wp-admin/includes/class-wp-upgrader.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ public function generic_strings() {
$this->strings['mkdir_failed'] = __( 'Could not create directory.' );
$this->strings['incompatible_archive'] = __( 'The package could not be installed.' );
$this->strings['files_not_writable'] = __( 'The update cannot be installed because some files could not be copied. This is usually due to inconsistent file permissions.' );
$this->strings['dir_not_readable'] = __( 'A directory could not be read.' );

$this->strings['maintenance_start'] = __( 'Enabling Maintenance mode…' );
$this->strings['maintenance_end'] = __( 'Disabling Maintenance mode…' );
Expand Down Expand Up @@ -558,7 +559,13 @@ public function install_package( $args = array() ) {
$remote_source = $args['source'];
$local_destination = $destination;

$source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) );
$dirlist = $wp_filesystem->dirlist( $remote_source );

if ( false === $dirlist ) {
return new WP_Error( 'source_read_failed', $this->strings['fs_error'], $this->strings['dir_not_readable'] );
}

$source_files = array_keys( $dirlist );
$remote_destination = $wp_filesystem->find_folder( $local_destination );

// Locate which directory to copy to the new folder. This is based on the actual folder holding the files.
Expand Down Expand Up @@ -605,7 +612,13 @@ public function install_package( $args = array() ) {

// Has the source location changed? If so, we need a new source_files list.
if ( $source !== $remote_source ) {
$source_files = array_keys( $wp_filesystem->dirlist( $source ) );
$dirlist = $wp_filesystem->dirlist( $source );

if ( false === $dirlist ) {
return new WP_Error( 'new_source_read_failed', $this->strings['fs_error'], $this->strings['dir_not_readable'] );
}

$source_files = array_keys( $dirlist );
}

/*
Expand Down
101 changes: 101 additions & 0 deletions tests/phpunit/tests/admin/wpUpgrader.php
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,107 @@ public function test_install_package_should_return_wp_error_when_no_source_files
);
}

/**
* Tests that `WP_Upgrader::install_package()` returns a WP_Error object
* when the source directory's file list cannot be retrieved.
*
* @ticket 61114
*
* @covers WP_Upgrader::install_package
*/
public function test_install_package_should_return_wp_error_when_source_directory_file_list_cannot_be_retrieved() {
self::$instance->generic_strings();

self::$upgrader_skin_mock
->expects( $this->once() )
->method( 'feedback' )
->with( 'installing_package' );

self::$wp_filesystem_mock
->expects( $this->once() )
->method( 'dirlist' )
->willReturn( false );

$args = array(
'source' => '/',
'destination' => '/',
);

$actual = self::$instance->install_package( $args );

$this->assertWPError(
$actual,
'WP_Upgrader::install_package() did not return a WP_Error object'
);

$this->assertSame(
'source_read_failed',
$actual->get_error_code(),
'Unexpected WP_Error code'
);
}

/**
* Tests that `WP_Upgrader::install_package()` returns a WP_Error object
* when the source directory is filtered and its file list cannot be retrieved.
*
* @ticket 61114
*
* @covers WP_Upgrader::install_package
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function test_install_package_should_return_wp_error_when_a_filtered_source_directory_file_list_cannot_be_retrieved() {
define( 'FS_CHMOD_DIR', 0755 );

self::$instance->generic_strings();

self::$upgrader_skin_mock
->expects( $this->once() )
->method( 'feedback' )
->with( 'installing_package' );

$first_source = array(
'subdir' => array(
'name' => 'subdir',
'type' => 'd',
'files' => array( 'subfile.php' ),
),
);

self::$wp_filesystem_mock
->expects( $this->exactly( 2 ) )
->method( 'dirlist' )
->willReturn( $first_source, false );

$args = array(
'source' => '/',
'destination' => '/',
);

// Filter the source to something else.
add_filter(
'upgrader_source_selection',
static function () {
return '/not_original_source/';
}
);

$actual = self::$instance->install_package( $args );

$this->assertWPError(
$actual,
'WP_Upgrader::install_package() did not return a WP_Error object'
);

$this->assertSame(
'new_source_read_failed',
$actual->get_error_code(),
'Unexpected WP_Error code'
);
}

/**
* Tests that `WP_Upgrader::install_package()` adds a trailing slash to
* the source directory of a single file.
Expand Down