Make WordPress Core


Ignore:
Timestamp:
02/07/2010 04:52:35 AM (15 years ago)
Author:
dd32
Message:

Introduce ZipArchive version of unzip_file(), More efficient on memory usage for supporting hosts. See #10403

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-admin/includes/file.php

    r12948 r13005  
    505505        return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
    506506
    507     // Unzip uses a lot of memory, but not this much hopefully
     507    // Unzip can use a lot of memory, but not this much hopefully
    508508    @ini_set('memory_limit', '256M');
    509 
    510     require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
    511 
    512     $archive = new PclZip($file);
    513 
    514     // Is the archive valid?
    515     if ( false == ($archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING)) )
    516         return new WP_Error('incompatible_archive', __('Incompatible Archive.'), $archive->errorInfo(true));
    517 
    518     if ( 0 == count($archive_files) )
    519         return new WP_Error('empty_archive', __('Empty archive.'));
    520509
    521510    $needed_dirs = array();
     
    530519
    531520            $dir = implode('/', array_slice($path, 0, $i+1) );
    532             if ( preg_match('!^[a-z]:$!i', $dir) ) // Skip it if it looks like a Windows Drive letter only.
     521            if ( preg_match('!^[a-z]:$!i', $dir) ) // Skip it if it looks like a Windows Drive letter.
    533522                continue;
    534523
     
    540529    }
    541530
    542     // Determine any children directories needed (From within the archive)
    543     foreach ( $archive_files as $file )
    544         $needed_dirs[] = $to . untrailingslashit( $file['folder'] ? $file['filename'] : dirname($file['filename']) );
    545 
     531    if ( class_exists('ZipArchive') && apply_filters('unzip_file_use_ziparchive', true ) )
     532        return _unzip_file_ziparchive($file, $to, $needed_dirs);
     533    else
     534        return _unzip_file_pclzip($file, $to, $needed_dirs);
     535}
     536
     537function _unzip_file_ziparchive($file, $to, $needed_dirs = array()) {
     538    global $wp_filesystem;
     539
     540    $z = new ZipArchive();
     541    if ( ! $z->open($file) )
     542        return new WP_Error('incompatible_archive', __('Incompatible Archive.'));
     543
     544    for ( $i = 0; $i < $z->numFiles; $i++ ) {
     545        if ( ! $info = $z->statIndex($i) )
     546            return new WP_Error('stat_failure', __('Could not retrieve file from archive.'));
     547
     548        if ( '/' == substr($info['name'], -1) ) // directory
     549            $needed_dirs[] = $to . untrailingslashit($info['name']);
     550        else
     551            $needed_dirs[] = $to . untrailingslashit(dirname($info['name']));
     552    }
     553   
    546554    $needed_dirs = array_unique($needed_dirs);
    547555    asort($needed_dirs);
    548 
     556   
    549557    // Create those directories if need be:
    550558    foreach ( $needed_dirs as $_dir ) {
     
    552560            return new WP_Error('mkdir_failed', __('Could not create directory.'), $_dir);
    553561    }
     562    unset($needed_dirs);
     563   
     564    for ( $i = 0; $i < $z->numFiles; $i++ ) {
     565        if ( ! $info = $z->statIndex($i) )
     566            return new WP_Error('stat_failure', __('Could not retrieve file from archive.'));
     567
     568        if ( '/' == substr($info['name'], -1) ) // directory
     569            continue;
     570
     571        if ( ! $wp_filesystem->put_contents( $to . $info['name'], $z->getFromIndex($i), FS_CHMOD_FILE) )
     572            return new WP_Error('copy_failed', __('Could not copy file.'), $to . $file['filename']);
     573    }
     574
     575    return true;
     576}
     577
     578function _unzip_file_pclzip($file, $to, $needed_dirs = array()) {
     579    global $wp_filesystem;
     580
     581    require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
     582
     583    $archive = new PclZip($file);
     584
     585    // Is the archive valid?
     586    if ( false == ($archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING)) )
     587        return new WP_Error('incompatible_archive', __('Incompatible Archive.'), $archive->errorInfo(true));
     588
     589    if ( 0 == count($archive_files) )
     590        return new WP_Error('empty_archive', __('Empty archive.'));
     591
     592    // Determine any children directories needed (From within the archive)
     593    foreach ( $archive_files as $file )
     594        $needed_dirs[] = $to . untrailingslashit( $file['folder'] ? $file['filename'] : dirname($file['filename']) );
     595
     596    $needed_dirs = array_unique($needed_dirs);
     597    asort($needed_dirs);
     598
     599    // Create those directories if need be:
     600    foreach ( $needed_dirs as $_dir ) {
     601        if ( ! $wp_filesystem->mkdir($_dir, FS_CHMOD_DIR) && ! $wp_filesystem->is_dir($_dir) ) // Only check to see if the Dir exists upon creation failure. Less I/O this way.
     602            return new WP_Error('mkdir_failed', __('Could not create directory.'), $_dir);
     603    }
     604    unset($needed_dirs);
    554605
    555606    // Extract the files from the zip
Note: See TracChangeset for help on using the changeset viewer.