Plugin Directory

Changeset 562699


Ignore:
Timestamp:
06/22/2012 09:14:28 PM (13 years ago)
Author:
hel.io
Message:

Made a lot of fixes

Location:
backup/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • backup/trunk/backup.php

    r558116 r562699  
    22/*
    33Plugin Name: Backup
    4 Version: 2.0
     4Version: 2.0.1
    55Plugin URI: http://hel.io/wordpress/backup/
    66Description: Backup your WordPress website to Google Drive.
     
    100100     * @access private
    101101     */
    102     private $docs;
     102    private $gdocs;
    103103
    104104    /**
     
    219219                'display' => __('Weekly', $this->text_domain)
    220220            ),
    221             'montly' => array(
     221            'monthly' => array(
    222222                'interval' => 2592000,
    223223                'display' => __('Monthly', $this->text_domain)
     
    791791    public function do_backup() {
    792792        // Check if the backup folder is writable
    793         if ( !( is_dir($this->local_folder) && @is_writable($this->local_folder) ) ) {
     793        if ( !( @is_writable($this->local_folder) ) ) {
    794794            $this->log('ERROR', "The directory '" . $this->local_folder . "' does not exist or it is not writable.");
     795            exit;
    795796        }
    796797
     
    807808        // Create database dump sql file.
    808809        if ( in_array('database', $this->options['source_list']) ) {
    809             $this->log('NOTICE', 'Attempting to dump database to ' . $this->dump_file);
     810            $this->log('NOTICE', "Attempting to dump database to '" . $this->dump_file . "'.");
    810811            $dump_time = db_dump($this->dump_file);
    811812
     
    830831        for ( $i = 0; $i < $count; $i++ )
    831832            for ( $j = 0; $j < $count; $j++ )
    832                 if ( $j != $i && isset($sources[$i]) && isset($sources[$j]) && is_subdir($sources[$j], $sources[$i]) )
     833                if ( $j != $i && isset($sources[$i]) && isset($sources[$j]) &&
     834                    is_subdir($sources[$j], $sources[$i]) && $this->sources['database']['path'] != $sources[$j] )
    833835                    unset($sources[$j]);
    834836
    835837        // Create archive from all enabled sources.
    836         $this->log('NOTICE', 'Attempting to create archive ' . $file_path);
     838        $this->log('NOTICE', "Attempting to create archive '" . $file_path . "'.");
    837839        $zip_time = zip($sources, $file_path, $exclude);
    838840
     
    842844        }
    843845
    844         $this->log('NOTICE', 'Archive created successfully in ' . round($zip_time, 2) . ' seconds. Archive file size is ' . size_format( filesize( $file_path ) ) ) . '.';
     846        $this->log('NOTICE', 'Archive created successfully in ' . round($zip_time, 2) . ' seconds. Archive file size is ' . size_format( filesize( $file_path ) ) . '.');
    845847        delete_path($this->dump_file);
    846848
     
    858860                $this->gdocs->set_option('time_limit', $this->options['time_limit']);
    859861
    860                 $this->log('NOTICE', 'Attempting to upload archive to Google Drive');
     862                $this->log('NOTICE', 'Attempting to upload archive to Google Drive.');
    861863                $id = $this->gdocs->upload_file($file_path, $file_name, $this->options['drive_folder']);
    862864                if ( is_wp_error($id) ) {
    863                     $this->log_wp_error($id);
    864865                    $err = $id->get_error_message('resumable');
    865                     if ( ! empty($err) ) // If we are here it means we have a chance at resuming the download so schedule resume.
     866                    if ( ! empty($err) ) { // If we are here it means we have a chance at resuming the download so schedule resume.
     867                        $this->log("WARNING", $err . ' The upload speed was around ' . size_format( $this->gdocs->get_upload_speed() ) . '/s.');
    866868                        wp_schedule_single_event($this->time, 'backup_resume');
     869                    }
     870                    else {
     871                        $this->log_wp_error($id);
     872                        delete_path( $file_path );
     873                    }
    867874                }
    868875                else {
    869                     $this->log('NOTICE', 'Archive ' . $file_name . ' uploaded to Google Drive in ' . round($this->gdocs->time_taken(), 2) . ' seconds');
     876                    $this->log('NOTICE', 'Archive ' . $file_name . ' uploaded to Google Drive in ' . round($this->gdocs->time_taken(), 2) . ' seconds at an upload speed of ' . size_format( $this->gdocs->get_upload_speed() ) . '/s.');
    870877                    $this->options['local_files'][] = $file_path;
    871878                    $this->options['drive_files'][] = $id;
     
    899906     */
    900907    public function backup_resume() {
    901         // Check if the backup folder is writable.
    902         if ( !( is_dir($this->local_folder) && @is_writable($this->local_folder) ) ) {
    903             $this->log('ERROR', "The directory '" . $this->local_folder . "' does not exist or it is not writable.");
    904         }
    905908        $access_token = $this->goauth->get_access_token();
    906         if ( is_wp_error($access_token) )
     909        if ( is_wp_error($access_token) ) {
    907910            $this->log_wp_error($access_token);
     911            exit;
     912        }
     913
     914        // We need an instance of GDocs here to talk to the Google Documents List API.
     915        if ( ! is_gdocs($this->gdocs) )
     916            $this->gdocs = new GDocs($access_token);
     917       
     918        $file = $this->gdocs->get_resume_item();
     919        if ( !$file ) {
     920            $this->log("WARNING", "There is no upload to resume.");
     921            exit;
     922        }
     923
     924        $this->gdocs->set_option('chunk_size', $this->options['chunk_size']);
     925        $this->gdocs->set_option('time_limit', $this->options['time_limit']);
     926
     927        $this->log('NOTICE', 'Resuming upload of ' . $file['title'] . '.');
     928        $id   = $this->gdocs->resume_upload();
     929        if ( is_wp_error($id) ) {
     930            $err = $id->get_error_message('resumable');
     931            if ( ! empty($err) ) {
     932                $this->log("WARNING", $err . ' The upload speed was around ' . size_format( $this->gdocs->get_upload_speed() ) . '/s.');
     933                wp_schedule_single_event($this->time, 'backup_resume');
     934            }
     935            else {
     936                $this->log_wp_error($id);
     937                delete_path( $file['path'] );
     938            }
     939        }
    908940        else {
    909             // We need an instance of GDocs here to talk to the Google Documents List API.
    910             if ( ! is_gdocs($this->gdocs) )
    911                 $this->gdocs = new GDocs($access_token);
    912             $file = $this->gdocs->get_resume_item();
    913             if ( $file )
    914                 $this->log('NOTICE', 'Resuming upload of ' . $file['title'] . '.');
    915             $id   = $this->gdocs->resume_upload();
    916             if ( is_wp_error($id) ) {
    917                 $this->log_wp_error($id);
    918                 $err = $id->get_error_message('resumable');
    919                 if ( ! empty($err) )
    920                     wp_schedule_single_event($this->time, 'backup_resume');
    921             }
    922             else {
    923                 $this->log('NOTICE', 'The archive was uploaded successfully.');
    924                 $this->options['drive_files'][] = $id;
    925                 $this->options['last_backup'] = substr($file['title'], 0, strpos($file['title'], '.')); // take the time from the title
    926                 // Update quotas if uploading to Google Drive was successful.
    927                 $this->update_quota();
    928                 $this->purge_drive_files();
    929                 delete_path($file['path']);
    930                 // Updating options in the database.
    931                 update_option('backup_options', $this->options);
    932             }
    933         }   
     941            $this->log('NOTICE', 'The archive was uploaded successfully. The upload speed was around ' . size_format( $this->gdocs->get_upload_speed() ) . '/s.');
     942            $this->options['local_files'][] = $file['path'];
     943            $this->options['drive_files'][] = $id;
     944            $this->options['last_backup'] = substr($file['title'], 0, strpos($file['title'], '.')); // take the time from the title
     945            // Update quotas if uploading to Google Drive was successful.
     946            $this->update_quota();
     947            $this->purge_local_files();
     948            $this->purge_drive_files();
     949            // Updating options in the database.
     950            update_option('backup_options', $this->options);
     951        }
    934952    }
    935953
  • backup/trunk/class-gdocs.php

    r558116 r562699  
    6161    /**
    6262     * Stores feeds to avoid requesting them again for successive use.
     63     *
    6364     * @var array
     65     * @access private
    6466     */
    6567    private $cache = array();
     68
     69    /**
     70     * Stores the handle of the file open for uploading.
     71     *
     72     * @var resource
     73     * @access private
     74     */
     75    private $file_handle;
    6676
    6777    /**
     
    103113     */
    104114    private $max_resume_attempts;
     115
     116    /**
     117     * This is true if a failed upload is resumable.
     118     *
     119     * @var boolean
     120     */
     121    private $resumable;
    105122
    106123    /**
     
    132149        $this->time_limit = 120; // 2 minutes
    133150        $this->max_resume_attempts = 5;
     151        $this->resumable = false;
    134152        $this->resume_list = get_option( 'gdocs_resume' );
    135153        $this->timer = array(
     
    339357    public function upload_file( $file, $title, $parent = '', $type = '' ) {
    340358
    341         if ( ! @is_file($file) )
    342             return new WP_Error('not_file', "The path '" . $file . "' does not point to a file.");
     359        if ( ! @is_readable($file) )
     360            return new WP_Error('not_file', "The path '" . $file . "' does not point to a readable file.");
    343361
    344362        // If a mime type wasn't passed try to guess it from the extension based on the WordPress allowed mime types
     
    383401        update_option('gdocs_resume', $this->resume_list);
    384402
    385         // Start timer
     403        // Start timer.
    386404        $this->timer['start'] = microtime( true );
    387405
    388         // Set time limit
     406        // Set time limit.
    389407        set_time_limit($this->time_limit);
     408
     409        // Open file for reading.
     410        if ( !$this->file_handle = fopen( $file, "rb" ) )
     411            return new WP_Error( 'open_error', "Could not open file '" . $file . "' for reading." );
    390412
    391413        return $this->upload_chunks( $file, 0 );         
     
    403425        if( !$id )
    404426            return new WP_Error("no_items", "There are no uploads that need to be resumed.");
    405         if ( ! @is_file($this->resume_list[$id]['path']) ) {
     427        if ( ! @is_readable($this->resume_list[$id]['path']) ) {
    406428            unset($this->resume_list[$id]);
    407429            update_option('gdocs_resume', $this->resume_list);
    408             return new WP_Error('not_file', "The path '" . $this->resume_list[$id]['path'] . "' does not point to a file. Upload has been canceled.");
     430            return new WP_Error('not_file', "The path '" . $this->resume_list[$id]['path'] . "' does not point to a readable file. Upload has been canceled.");
    409431        }
    410432
     
    416438        $headers = array( 'Content-Range' => 'bytes */' . $this->resume_list[$id]['size'] );
    417439        $result = $this->request( $this->resume_list[$id]['location'], 'PUT', $headers );
    418         if( is_wp_error( $result ) )
     440        if( is_wp_error( $result ) ) {
     441            $this->resumable = true;
    419442            return $result;
    420         if ( $result['response']['code'] != '308' )
     443        }
     444        if ( $result['response']['code'] != '308' ) {
     445            $this->resumable = true;   
    421446            return new WP_Error('bad_response', "Received response code '" . $result['response']['code'] . " " . $result['response']['message'] . "' while trying to resume the upload of file '" . $this->resume_list[$id]['title'] . "'.");
     447        }
    422448        if( isset( $result['headers']['location'] ) )
    423449            $this->resume_list[$id]['location'] = $result['headers']['location'];
     
    429455        // Set time limit
    430456        set_time_limit($this->time_limit);
     457
     458        // Open file for reading.
     459        if ( $this->file_handle = fopen( $this->resume_list[$id]['path'], "rb" ) )
     460            return new WP_Error( 'open_error', "Could not open file '" . $this->resume_list[$id]['path'] . "' for reading." );
    431461
    432462        return $this->upload_chunks($id, $pointer);
     
    459489     */
    460490    public function get_resume_item() {
    461         return $this->resume_list[$this->get_resume_item_id()];
     491        if ( $id = $this->get_resume_item_id() )
     492            return $this->resume_list[$id];
     493        return false;
    462494    }
    463495
     
    472504    private function upload_chunks( $id, $pointer ) {
    473505        $cycle_start = microtime(true);
    474         $chunk = @file_get_contents( $this->resume_list[$id]['path'], false, NULL, $pointer, $this->chunk_size );
     506        fseek( $this->file_handle, $pointer );
     507        $chunk = @fread( $this->file_handle, $this->chunk_size );
    475508        if ( $chunk === false )
    476509            return new WP_Error( 'read_error', "Failed to read from file '" . $this->resume_list[$id]['path'] . "'." );
     
    497530                $this->resume_list[$id]['used'] = false;
    498531                update_option('gdocs_resume', $this->resume_list);
    499                 return new WP_Error('resumable', "The upload process timed out but can be resumed.");
     532                $this->resumable = true;
     533                return new WP_Error('timeout', "The upload process timed out but can be resumed.");
    500534            }   
    501535            else {
     
    505539        }
    506540        if ( $result['response']['code'] == '201' ) {
     541            fclose( $this->file_handle );
    507542            $feed = @simplexml_load_string( $result['body'] );
    508543            if ( $feed === false )
     
    521556
    522557        // If we got to this point it means the upload wasn't successful.
     558        fclose( $this->file_handle );
    523559
    524560        // Give up if we tried to resume too many times
     
    527563            unset( $this->resume_list[$id] );
    528564            update_option( 'gdocs_resume', $this->resume_list );
    529             return new WP_Error( 'fail', "The upload of file '" . $temp['path'] . "' failed after trying " . $temp['attempt'] . " times." );
     565            return new WP_Error( 'permanent_fail', "The upload of file '" . $temp['path'] . "' failed after trying " . $temp['attempt'] . " times." );
    530566        }
    531567
     
    533569        $this->resume_list[$id]['used'] = false;
    534570        update_option( 'gdocs_resume', $this->resume_list );
    535         return new WP_Error( 'resumable', "Received response code '" . $result['response']['code'] . " " . $result['response']['message'] . "' while trying to upload a chunk of file '" . $this->resume_list[$id]['title'] . "'. The upload might be resumable." );
     571        $this->resumable = true;
     572        return new WP_Error( 'bad_response', "Received response code '" . $result['response']['code'] . " " . $result['response']['message'] . "' while trying to upload a chunk of file '" . $this->resume_list[$id]['title'] . "'. The upload might be resumable." );
     573    }
     574
     575    /**
     576     * Get the upload speed recorded on the last upload performed.
     577     *
     578     * @access public
     579     * @return mixed  Returns the upload speed in bytes/second or FALSE.
     580     */
     581    public function get_upload_speed() {
     582        if ( isset( $this->timer['cycle'] ) )
     583            return $this->chunk_size / $this->timer['cycle'];
     584        return false;
     585    }
     586
     587    /**
     588     * Find out if a failed upload is resumable.
     589     *
     590     * @access public
     591     * @return boolean Returns TRUE if a failed upload is resumable, FALSE otherwise.
     592     */
     593    public function is_resumable() {
     594        return $this->resumable;
    536595    }
    537596
     
    539598     * Checks if the script is nearing max execution time.
    540599     *
     600     * @access private
    541601     * @return boolean Returns TRUE if nearing max execution time, FALSE otherwise.
    542602     */
     
    548608
    549609    /**
    550      * Returns the time taken for an upload to complete
    551      *
    552      * @return float The number of seconds accurate to the microsecond it took for the upload to complete
     610     * Returns the time taken for an upload to complete.
     611     *
     612     * @access public
     613     * @return mixed  Returns a float number of seconds if an upload has been completed, FALSE otherwise.
    553614     */
    554615    public function time_taken() {
    555         return $this->timer['delta'];
     616        if ( isset( $this->timer['delta'] ) )
     617            return $this->timer['delta'];
     618        return false;
    556619    }
    557620}
  • backup/trunk/functions.php

    r558116 r562699  
    142142
    143143    foreach ( $sources as $source )
    144         if ( @is_dir($source) ) {
    145             $files = directory_list($source, true, $exclude);
    146             foreach ( $files as $file )
    147                 if ( @is_dir($file) )
    148                     $zip->addEmptyDir(str_replace(parent_dir($source) . '/', '', $file . '/'));
    149                 elseif ( @is_file($file) )
    150                     $zip->addFile($file, str_replace(parent_dir($source) . '/', '', $file));
    151         }
    152         elseif ( @is_file($source) )
    153             $zip->addFile($source, basename($source));
     144        if ( @is_readable($source) )
     145            if ( @is_dir($source) ) {
     146                $files = directory_list($source, true, $exclude);
     147                foreach ( $files as $file )
     148                    if ( @is_dir($file) && @is_readable($file) )
     149                        $zip->addEmptyDir(str_replace(parent_dir($source) . '/', '', $file . '/'));
     150                    elseif ( @is_file($file) && @is_readable($file) )
     151                        $zip->addFile($file, str_replace(parent_dir($source) . '/', '', $file));
     152            }
     153            elseif ( @is_file($source) )
     154                $zip->addFile($source, basename($source));
    154155
    155156    $zip_result = $zip->close();
     
    176177    $zip = new PclZip($destination);
    177178    foreach ( $sources as $source )
    178         if ( @is_dir($source) ) {
    179             $files = directory_list($source, true, $exclude);
    180             $res = $zip->add($files, PCLZIP_OPT_REMOVE_PATH, parent_dir($source));
    181             if ( 0 == $res )
    182                 return new WP_Error('pclzip', $zip->errorInfo(true));
    183         }
    184         elseif ( @is_file($source) ) {
    185             $res = $zip->add($source, parent_dir($source));
    186             if ( 0 == $res )
    187                 return new WP_Error('pclzip', $zip->errorInfo(true));
    188         }
     179        if ( @is_readable($source) )
     180            if ( @is_dir($source) ) {
     181                $files = directory_list($source, true, $exclude);
     182                $res = $zip->add($files, PCLZIP_OPT_REMOVE_PATH, parent_dir($source));
     183                if ( 0 == $res )
     184                    return new WP_Error('pclzip', $zip->errorInfo(true));
     185            }
     186            elseif ( @is_file($source) ) {
     187                $res = $zip->add($source, PCLZIP_OPT_REMOVE_PATH, parent_dir($source));
     188                if ( 0 == $res )
     189                    return new WP_Error('pclzip', $zip->errorInfo(true));
     190            }
    189191    return true;     
    190192}
  • backup/trunk/readme.txt

    r558121 r562699  
    4747== Changelog ==
    4848
     49= 2.0.1 =
     50* Fixed database dump not getting added to the backup archive in some circumstances.
     51* Fixed not setting the time limit and chunk size when resuming uploads.
     52* Fixed local backups not being deleted after a failed upload.
     53* Fixed some bugs in the GDocs class and optimized chunk reading.
     54* Now logging upload speeds.
     55* Other minor bug fixes.
     56
    4957= 2.0 =
    5058* Rewrote 95% of the plugin to make it more compatible with older PHP versions, more portable and cleaner. It now uses classes and functions already found in WordPress where possible.
Note: See TracChangeset for help on using the changeset viewer.