Changeset 6779

Show
Ignore:
Timestamp:
02/11/08 05:45:54 (5 months ago)
Author:
ryan
Message:

First cut at plugin update. Props DD32 for the filesystem abstraction. see #5586

Files:

Legend:

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

    r6551 r6779  
    172172} 
    173173 
     174/** 
     175* Downloads a url to a local file using the Snoopy HTTP Class 
     176* 
     177* @param string $url the URL of the file to download 
     178* @return mixed false on failure, string Filename on success. 
     179*/ 
     180function download_url( $url ) { 
     181    //WARNING: The file is not automatically deleted, The script must unlink() the file. 
     182    if( ! $url ) 
     183        return false; 
     184 
     185    $tmpfname = tempnam('/tmp', 'wpupdate'); 
     186    if( ! $tmpfname ) 
     187        return false; 
     188 
     189    $handle = fopen($tmpfname, 'w'); 
     190    if( ! $handle ) 
     191        return false; 
     192 
     193    require_once( ABSPATH . 'wp-includes/class-snoopy.php' ); 
     194    $snoopy = new Snoopy(); 
     195    $snoopy->fetch($url); 
     196     
     197    fwrite($handle, $snoopy->results); 
     198    fclose($handle); 
     199 
     200    return $tmpfname; 
     201} 
     202 
     203function unzip_file($file, $to) { 
     204    global $wp_filesystem; 
     205 
     206    if ( ! $wp_filesystem || !is_object($wp_filesystem) ) 
     207        return new WP_Error('fs_unavailable', __('Could not access filesystem.')); 
     208             
     209    $fs =& $wp_filesystem; 
     210 
     211    require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php'); 
     212 
     213    $archive = new PclZip($file); 
     214 
     215    // Is the archive valid? 
     216    if ( false == ($archive_files = $archive->extract(PCLZIP_OPT_EXTRACT_AS_STRING)) ) 
     217        return new WP_Error('incompatible_archive', __('Incompatible archive'), $archive->error_string); 
     218 
     219    if ( 0 == count($archive_files) ) 
     220        return new WP_Error('empty_archive', __('Empty archive')); 
     221 
     222    $to = trailingslashit($to); 
     223    $path = explode('/', $to); 
     224    $tmppath = ''; 
     225    for ( $j = 0; $j < count($path) - 1; $j++ ) { 
     226        $tmppath .= $path[$j] . '/'; 
     227        if ( ! $fs->is_dir($tmppath) ) { 
     228            $fs->mkdir($tmppath); 
     229        } else { 
     230            $fs->setDefaultPermissions( $fs->getchmod($tmppath) ); 
     231        } 
     232    } 
     233 
     234    foreach ($archive_files as $file) { 
     235        $path = explode('/', $file['filename']); 
     236        $tmppath = ''; 
     237 
     238        // Loop through each of the items and check that the folder exists. 
     239        for ( $j = 0; $j < count($path) - 1; $j++ ) { 
     240            $tmppath .= $path[$j] . '/'; 
     241            if ( ! $fs->is_dir($to . $tmppath) ) 
     242                $fs->mkdir($to . $tmppath); 
     243        } 
     244 
     245        // We've made sure the folders are there, so let's extract the file now: 
     246        if ( ! $file['folder'] ) 
     247            $fs->put_contents( $to . $file['filename'], $file['content']); 
     248    } 
     249} 
     250 
     251function copy_dir($from, $to) { 
     252    global $wp_filesystem; 
     253 
     254    $dirlist = $wp_filesystem->dirlist($from); 
     255 
     256    $from = trailingslashit($from); 
     257    $to = trailingslashit($to); 
     258 
     259    foreach ( (array) $dirlist as $filename => $fileinfo ) { 
     260        if ( 'file' == $fileinfo['type'] ) { 
     261            $wp_filesystem->copy($from . $filename, $to . $filename, true); 
     262        } elseif ( 'folder' == $fileinfo['type'] ) { 
     263            $wp_filesystem->mkdir($to . $filename); 
     264            copy_dir($from . $filename, $to . $filename); 
     265        } 
     266    } 
     267} 
     268 
     269function WP_Filesystem( $args = false, $preference = false ) { 
     270    global $wp_filesystem; 
     271 
     272    $method = get_filesystem_method($preference); 
     273    if ( ! $method ) 
     274        return false; 
     275 
     276    require_once('class-wp-filesystem-'.$method.'.php'); 
     277    $method = "WP_Filesystem_$method"; 
     278 
     279    $wp_filesystem = new $method($args); 
     280 
     281    if ( $wp_filesystem->errors->get_error_code() ) 
     282        return false; 
     283 
     284    if ( !$wp_filesystem->connect() ) 
     285        return false; //There was an erorr connecting to the server. 
     286 
     287    return true; 
     288} 
     289 
     290function get_filesystem_method() { 
     291    $tempFile = tempnam('/tmp', 'WPU'); 
     292 
     293    if ( getmyuid() == fileowner($tempFile) ) { 
     294        unlink($tempFile); 
     295        //return 'direct'; 
     296    } else { 
     297        unlink($tempFile); 
     298    } 
     299 
     300    if ( extension_loaded('ftp') ) return 'ftpext'; 
     301    if ( extension_loaded('sockets') ) return 'ftpsockets'; 
     302    return false; 
     303} 
     304 
    174305?> 
  • trunk/wp-admin/includes/update.php

    r6551 r6779  
    115115 
    116116    echo "<tr><td colspan='5' class='plugin-update'>"; 
    117     printf( __('There is a new version of %s available. <a href="%s">Download version %s here</a>.'), $plugin_data['Name'], $r->url, $r->new_version ); 
     117    printf( __('There is a new version of %1$s available. <a href="%2$s">Download version %3$s here</a> or <a href="%4$s">upgrade automatically</a>.'), $plugin_data['Name'], $r->url, $r->new_version, "update.php?action=upgrade-plugin&amp;plugin=$file" ); 
    118118    echo "</td></tr>"; 
    119119} 
    120120add_action( 'after_plugin_row', 'wp_plugin_update_row' ); 
    121121 
     122function wp_update_plugin($plugin, $feedback = '') { 
     123    global $wp_filesystem; 
     124 
     125    if ( !empty($feedback) ) 
     126        add_filter('update_feedback', $feedback); 
     127 
     128    // Is an update available? 
     129    $current = get_option( 'update_plugins' ); 
     130    if ( !isset( $current->response[ $plugin ] ) ) 
     131        return new WP_Error('up_to_date', __('The plugin is at the latest version.')); 
     132 
     133    // Is a filesystem accessor setup? 
     134    if ( ! $wp_filesystem || !is_object($wp_filesystem) ) 
     135        WP_Filesystem(); 
     136 
     137    if ( ! is_object($wp_filesystem) ) 
     138        return new WP_Error('fs_unavailable', __('Could not access filesystem.')); 
     139 
     140    if ( $wp_filesystem->errors->get_error_code() )  
     141        return new WP_Error('fs_error', __('Filesystem error'), $wp_filesystem->errors); 
     142 
     143    // Get the URL to the zip file 
     144    $r = $current->response[ $plugin ]; 
     145 
     146    if ( empty($r->package) ) 
     147        return new WP_Error('no_package', __('Upgrade package not available.')); 
     148 
     149    // Download the package 
     150    $package = $r->package; 
     151    apply_filters('update_feedback', __("Downloading update from $package")); 
     152    $file = download_url($package); 
     153 
     154    if ( !$file ) 
     155        return new WP_Error('download_failed', __('Download failed.')); 
     156 
     157    $name = basename($plugin, '.php'); 
     158    $working_dir = ABSPATH . 'wp-content/upgrade/' . $name; 
     159 
     160    // Clean up working directory 
     161    $wp_filesystem->delete($working_dir, true); 
     162 
     163    apply_filters('update_feedback', __("Unpacking the update")); 
     164    // Unzip package to working directory 
     165    $result = unzip_file($file, $working_dir); 
     166    if ( is_wp_error($result) ) { 
     167        unlink($file); 
     168        $wp_filesystem->delete($working_dir, true); 
     169        return $result; 
     170    } 
     171 
     172    // Once installed, delete the package 
     173    unlink($file); 
     174     
     175    // Remove the existing plugin. 
     176    apply_filters('update_feedback', __("Removing the old version of the plugin")); 
     177    $wp_filesystem->delete(ABSPATH . PLUGINDIR . "/$plugin"); 
     178    $plugin_dir = dirname(ABSPATH . PLUGINDIR . "/$plugin"); 
     179 
     180    // If plugin is in its own directory, recursively delete the directory. 
     181    if ( '.' != $plugin_dir ) 
     182        $wp_filesystem->delete($plugin_dir, true); 
     183 
     184    apply_filters('update_feedback', __("Installing the latest version")); 
     185    // Copy new version of plugin into place. 
     186    copy_dir($working_dir, ABSPATH . PLUGINDIR); 
     187 
     188    // Remove working directory 
     189    $wp_filesystem->delete($working_dir, true); 
     190 
     191    // Force refresh of plugin update information 
     192    delete_option('update_plugins'); 
     193} 
     194 
    122195?>