MySQL Restore Class

Avatar of Chris Coyier
Chris Coyier on
<?php

define('MSR_VERSION', '1.0.0');
define('__SEP__', "/*sep*/" );

define('MSR_STRING', 0);
define('MSR_FILE', 1);
set_time_limit( 600 );


class MySQL_Restore {

 var $server           = 'localhost';
 var $port             = 3306;
 var $username         = 'root';
 var $password         = '';
 var $database         = '';
 var $link_id          = -1;
 var $connected        = false;
 var $queries          = array();
 var $error            = '';

 var $debug            = false;
 var $log_folder       = "";
 var $log_file_name    = "";

   function MySQL_Restore() {
       $this->log_file_name = "restore_" . date( "Ymd_his" ) . ".log";
   }

   function Execute( $param, $mode = MSR_STRING, $is_compressed = false, $split_only = false ) {
       if ( $this->debug ) {
               $this->saveLog( "[start reading file]" );
       }
           if ( $mode == MSR_FILE ) {
               if (!($sql = $this->_ReadFromFile($param, $is_compressed))) {
                   $this->error = 'Can\'t read backup file.';
                   return false;
               }
           } else {
               $sql = ($is_compressed ? gzuncompress($param) : $param);
           }
       if ( $this->debug ) {
           $this->saveLog( "[file readed]" );
       }

           return $this->_Restore( $sql, $split_only );
   }


   function _Connect() {
           $value = false;
           if ( !$this->connected ) {
               $host = $this->server . ':' . $this->port;
               $this->link_id = mysql_pconnect( $host, $this->username, $this->password );
           }
           if ( $this->link_id ) {
               if ( empty( $this->database ) ) {
                   $value = true;
               } elseif ( $this->link_id !== -1 ) {
                   $value = mysql_select_db($this->database, $this->link_id);
               } else {
                   $value = mysql_select_db($this->database);
               }
           }
           if (!$value) {
               $this->error = mysql_error();
           }
           return $value;
   }

   function _Disconnect() {
       if ( $this->link_id ) {
               mysql_close( $this->link_id );
       }
   }

   function _Query( $sql ) {
       if ( $this->link_id !== -1 ) {
           $result = mysql_query( $sql, $this->link_id );
       } else {
           $result = mysql_query( $sql );
       }
       if ( !$result ) {
           $this->error = mysql_error();
       }
       return $result;
   }


// The logic from phpMyAdmin source
   function _Decompose( &$ret, $sql ) {
       $sql = rtrim( $sql, "\n\r" );
       $sql_len = strlen( $sql );
       $char = '';
       $string_start = '';
       $in_string = false;
       $nothing = true;
       $time0 = time();
       for ( $i = 0; $i < $sql_len; ++$i ) {
           $char = $sql[$i];
           if ( $in_string ) {
               for (;;) {
                   $i = strpos( $sql, $string_start, $i );
                   if ( !$i ) {
                       $ret[] = $sql;
                       return true;
                   } elseif ( $string_start == '`' || $sql[$i - 1] != '\\' ) {
                       $string_start = '';
                       $in_string = false;
                       break;
                   } else {
                       $j = 2;
                       $escaped_backslash = false;
                       while ( $i - $j > 0 && $sql[$i - $j] == '\\' ) {
                           $escaped_backslash = !$escaped_backslash;
                           $j++;
                       }
                       if ( $escaped_backslash ) {
                           $string_start = '';
                           $in_string = false;
                           break;
                       } else {
                           $i++;
                       }
                   }
               }
           } else if ( ($char == '-' && $sql_len > $i + 2 && $sql[$i + 1] == '-' && $sql[$i + 2] <= ' ') || $char == '#' || ($char == '/' && $sql_len > $i + 1 && $sql[$i + 1] == '*') ) {
               $comm_end = ($char == '/' ? '*/' : "\n");
               $i = strpos($sql, $comm_end, $i);
               if ( $i === false ) {
                   break;
               }
               if ($char == '/') {
                   $i++;
               }
           } else if ($char == ';') {
               $ret[] = array( 'query' => substr( $sql, 0, $i ), 'empty' => $nothing );
               $nothing = true;
               $sql = ltrim(substr($sql, min($i + 1, $sql_len)));
               $sql_len = strlen($sql);
               if ( $sql_len ) {
                   $i = -1;
               } else {
                   return true;
               }
           } else if (($char == '"') || ($char == '\'') || ($char == '`')) {
               $in_string = true;
               $nothing = false;
               $string_start = $char;
           } elseif ($nothing) {
               $nothing = false;
           }
           $time1 = time();
           if ($time1 >= $time0 + 30) {
               $time0 = $time1;
               @header('X-pmaPing: Pong');
           }
       }
       if (!empty($sql) && preg_match('@[^[:space:]]+@', $sql)) {
           $ret[] = array('query' => $sql, 'empty' => $nothing);
       }
       return true;
   }


   function _Restore($sql, $split_only) {
       if ( $this->debug ) {
           $this->saveLog( "[start restoring]" );
       }
       if ( $this->debug ) {
           $this->saveLog( "[connecting to DB...]" );
       }

       if (!$this->_Connect()) {
           return false;
       }
       if ( $this->debug ) {
           $this->saveLog( "[connected to DB]" );
       }
       if ( $this->debug ) {
           $this->saveLog( "[decomposing...]" );
       }
       $queries = array();
       $errors = '';

// check if is this our backup
       if ( strpos( $sql, __SEP__ ) !== false ) {
               if ( $this->debug ) {
                   $this->saveLog( "[founding our backup file]" );
               }
           $queries = explode( __SEP__, $sql );
           if ( count( $queries ) ) {
                   if ( $this->debug ) {
                       $this->saveLog( "[decomposed]" );
                   }
                   if (!$split_only) {
                       foreach ($queries as $query) {
                               $query = trim( $query );
                               if ( !empty( $query ) ) {
                                   if (!$this->_Query( $query ) ) {
                                       $errors .= $this->error . '<br />';
                                   }
                                       if ( $this->debug ) {
                                  $this->saveLog( $query );
                           }
                               }
                       }
                   }
           }
       } else {
           if ( $this->debug ) {
               $this->saveLog( "[common sql file founded]" );
           }
               if (!$this->_Decompose( $queries, $sql ) ) {
                   return false;
               }
               if ( $this->debug ) {
                   $this->saveLog( "[decomposed]" );
               }
               foreach ($queries as $query) {
                   if (!$split_only) {
                       if (!$this->_Query( trim( $query['query'] ) ) ) {
                           $errors .= $this->error . '<br /><br />';
                       }
                   }
                   if ( $this->debug ) {
                       $this->saveLog( $query['query'] );
                   }
               }
       }
       if ( $this->debug ) {
           $this->saveLog( "[finished restoring]" );
       }
       $this->_Disconnect();

       if ( !empty( $errors ) ) {
           $this->error = $errors;
           return false;
       }
       return true;
   }


   function _ReadFromFile($fname, $is_compressed) {
          if ($is_compressed) {
              $sql = gzfile($fname);
          } else {
              $sql = file($fname);
          }
          if ($sql === false) {
             return false;
          }
          return implode('', $sql);
       }

       function saveLog( $str ) {
       $f = @fopen( $this->log_folder . $this->log_file_name, "a" );
       @fwrite( $f, "[" . date( "H:i:s" ). "] " . $str . "\n" );
               @fclose( $f );
       }
}

?>