<?php

		include_once( PLOG_CLASS_PATH."class/plugin/pluginbase.class.php" );
		include_once( PLOG_CLASS_PATH."class/plugin/pluginmanager.class.php" );
		include_once( PLOG_CLASS_PATH."class/config/config.class.php" );
		include_once( PLOG_CLASS_PATH."class/dao/model.class.php" );
		include_once( PLOG_CLASS_PATH."class/data/timestamp.class.php" );

    /**
     * plugin Backup allows users to backup their pLog journals.
     */
    class PluginBackup extends PluginBase
    {
    
        var $_includeDropDatabase;
        var $_includeDropTables;
        var $_destination;
        var $_pluginOp;

        function PluginBackup()
        {
          $this->connectDb();
	    $this->author = "Bradley Liang";
	    $this->desc   = "The plugin backs up all of LifeType's databases (including any created by plugins), but does not backup other tables.  If you are looking to restore database structure, it will be easier to purge your database and run the wizard over with a fresh installation.<br /><br />  ".
	    			    "Usage: Unfortunately, I've not much idea on how to implement plugin versatility from within LifeType's Administrative interface.  Instead, place the following command in a temporary template..<br />".
	    			    "&nbsp;&nbsp;&nbsp;&nbsp;{\$dbbackup->Backup()}<br />".
				    "A file entitled 'backup.sql' will be created in your main pLog directory.  To restore simply run the commands from the file from SQL.<br /><br />".
	    			    "TODO:<br />&nbsp;&nbsp;&nbsp;&nbsp;-Use of the admin configuration panel to back data up.<br />&nbsp;&nbsp;&nbsp;&nbsp;-Option to restore entries to DB<br />";
	    $this->pluginBase();
	  }
	  
	  //
	  // generates a very nice configuration message
	  //
	  function getConfigurationMessage()
	  {
	   // security check 
	   if( !$this->userInfo->isSiteAdmin()) {
	       $message = "<h1>Error</h1><p>Only site administrators are allowed to use this plugin</p>";
	       return $message;
	   }
	   
	   if( $this->_pluginOp == "backup" ) {
	       $backup = new PluginBackupLib( $this->_includeDropDatabase, $this->_includeDropTables );
	       $backupQuery = $backup->Backup();
	       if( $this->_destination == "1" ) {
	           // show results on the screen
	           $message = nl2br(htmlspecialchars($backupQuery));
	       }
	       else {
	           $t = new Timestamp();
	           $fileName = PLOG_CLASS_PATH."tmp/backup_".$t->getYear().$t->getMonth().$t->getDay()."-".$t->getHour().$t->getMinutes().".sql";
    	      if( !$backup->save( $fileName )) {
    	           $message .= "There was an error saving the backup to file $fileName";
    	      }
    	      else {
    	           $message .= "Backup saved to file $fileName";
	               $message .= "<br/><br/>The following tables were backed up:<br/><br/>".$backup->getMessage();
	          }
	       }
	   }
	   else {
           // otherwise, we can proceed as usual
           $savePath = PLOG_CLASS_PATH."tmp/";
           $message = "<p>This plugin will back up the whole pLog database. Enable any of the following features and then click the Backup button</p>
                       <form name=\"backupOptions\" action=\"admin.php\" method=\"post\">
                        <input type=\"checkbox\" name=\"includeDropDatabase\" value=\"1\" /> Include a DROP DATABASE command.<br/><br/>
                        <input type=\"checkbox\" name=\"includeDropTables\" value=\"1\" checked=\"checked\" /> Include a DROP TABLE IF EXISTS for every table.<br/><br/>
                        <select name=\"destination\">
                         <option value=\"1\">Show results on the screen</option>
                         <option value=\"2\">Save results to a file in $savePath</option>
                        </select><br/><br/>
                        <input type=\"submit\" name=\"Backup\" value=\"Backup\" />
                        <input type=\"hidden\" name=\"op\" value=\"updatePluginConfig\" />
                        <input type=\"hidden\" name=\"pluginOp\" value=\"backup\" />
                        <input type=\"hidden\" name=\"pluginId\" value=\"dbbackup\" />
                       </form>";
	   }
	   
	   return $message;
	  }
	  
	  function configure( $params )
	  {
	   $this->_includeDropDatabase = $params->getValue( "includeDropDatabase" );
	   $this->_includeDropTables = $params->getValue( "includeDropTables" );
	   $this->_destination = $params->getValue( "destination" );
	   $this->_pluginOp = $params->getValue( "pluginOp" );
	   
	   return true;
 	  }
	}
	
	// ---
	// class that does all the dirty work
	// ---
	class PluginBackupLib extends Model
	{
	
	 var $_message;
	 var $_includeDropDatabase;
	 var $_includeDropTables;
	 var $_result;
	
     function PluginBackupLib( $includeDropDatabase = true, $includeDropTables = true )
     {
        $this->_includeDropDatabase = $includeDropDatabase;
        $this->_includeDropTables = $includeDropTables;
        $this->Model();
    }
	  

	 function _buildInsertQuery( $table , $row_data) {
		$query = "INSERT INTO $table VALUES(\n";

		foreach ($row_data as $entry) {
			if (!isset($entry))		$query .= "     NULL,\n";
			else if ($entry != "") 	$query .= "     '".addslashes($entry)."',\n";
			else					$query .= "     '',\n";
		}

		$query = ereg_replace(",\n$","",$query);

		$query .= ");\n\n";

		return $query;
	 }

	 function _buildFieldQuery($table, $fields) {
	    	$def = "";
	    	if( $this->_includeDropTables ) $def .= "DROP TABLE IF EXISTS $table;\n";
    		$def .= "CREATE TABLE $table (\n";

    		while( $field = $fields->FetchRow() ) {
        	   $def .= "   $field[Field] $field[Type]";
        	   if ($field["Default"] != "") 	$def .= " DEFAULT '$field[Default]'";
        	   if ($field["Null"] != "YES") 	$def .= " NOT NULL";
       	   if ($field[Extra] != "") 		$def .= " $field[Extra]";
        	   						$def .= ",\n";
		}

     		$def = ereg_replace(",\n$","", $def);
     		return $def;
	 }

	function _buildKeyQuery($table, $keys)
	{
	     while($row = $keys->FetchRow()) {
	          $kname=$row[Key_name];

	          if(($kname != "PRIMARY") && ($row[Non_unique] == 0)) {
			$kname="UNIQUE|$kname";
		   }

	          if(!isset($index[$kname])) {
			$index[$kname] = array();
		   }

	          $index[$kname][] = $row[Column_name];
	     }

        // if the table has keys, then proceed to dump them to the db
        if( is_array($index)) {
	     while(list($x, $columns) = @each($index)) {
	          $def .= ",\n";
	          if ($x == "PRIMARY") 			$def .= "    PRIMARY KEY (" . implode($columns, ", ") . ")";
	          else if (substr($x,0,6) == "UNIQUE") 	$def .= "    UNIQUE ".substr($x,7)." (" . implode($columns, ", ") . ")";
	          else 						$def .= "    KEY $x (" . implode($columns, ", ") . ")";
	      }
	     }

	     $def .= "\n);";
	     return (stripslashes($def));
	}


	 function backupTable($table)
	 {
	     $content = "# begin table '$table'\n";
	     $this->_db->Execute("LOCK TABLES $table WRITE;");

	     $result = $this->_db->Execute("SHOW FIELDS FROM $table");
	     $content .= $this->_buildFieldQuery($table, $result);

	     $result = $this->_db->Execute("SHOW KEYS FROM $table");
	     $content .= $this->_buildKeyQuery($table, $result);

	     $result = $this->_db->Execute("SELECT * FROM $table");
	     $content .= "\n\n";

	     while($row = $result->FetchRow()) {
	         $content .= $this->_buildInsertQuery($table, $row);
	     }

	     $this->_db->Execute("UNLOCK TABLES;");
	     return $content."# end table '$table'\n\n";
 	 }

	 function Backup()
	 {
		$query   = "# Backup of all pLog entries in DB\n".
		 	  "# pLog.....:  http://lifetype.net\n".
			  "# Created..:  ".date("d-M-Y h:s",time())."\n\n";
			  
		$config =& Config::getConfig();	  
        if( $this->_includeDropDatabase ) $query .= "DROP DATABASE ".$config->getValue( "db_database" ).";\n";
		
		$prefix = $this->getPrefix();
		
		$result = $this->_db->MetaTables('TABLES');
		foreach ($result as $tablename) {

			if (strstr($tablename, $prefix))
			{
				$this->_message .= $tablename."<br />";
			   $query .= $this->backupTable($tablename);
			}
		}
		
		$this->_result = $query;

   		return $query;
	 }
	 
	 function getMessage()
	 {
	   return $this->_message;
	 }
	 
	 // ---
	 // save the contents of our export operation to a file
	 // ---
	 function save( $fileName )
	 {
	   $t = new Timestamp();
	   $f = new File( $fileName );
	   $f->open( "w" );
	   if( !$f->write( $this->_result ))
	       return false;
	   $f->close();
	   
	   return true;
	 }
	}
	
	PluginManager::registerPlugin( "dbbackup", "PluginBackup" );
?>
