Export.php
authorAlan Knowles <alan@akbkhome.com>
Tue, 26 Apr 2011 02:35:27 +0000 (10:35 +0800)
committerAlan Knowles <alan@akbkhome.com>
Tue, 26 Apr 2011 02:35:27 +0000 (10:35 +0800)
Export.php [new file with mode: 0644]

diff --git a/Export.php b/Export.php
new file mode 100644 (file)
index 0000000..c8d601f
--- /dev/null
@@ -0,0 +1,335 @@
+<?php
+
+
+/**
+ * This should allow you to dump a series of data, so it could be restored later...
+ * The format will be an SQL file...
+ *
+ * usage:
+ *    php index.php  Admin/Dump --table=Project --where="id=123"
+ *              --dump-dir=/directory_to_put_sql+shell files
+ *
+ *    outputs list of generated files.
+ *    
+ *     RESTORE FILES:
+ *      {DATE}.sql - the recreate sql including all dependancies, run with mysql DB -f  < ....
+ *      {DATE}.restore.sh - shell script to recreate files that where removed (excluding thumgs)
+ *      
+ *     BACKUP
+ *      {DATE}.copy.sh - shell script that backs up all the related files.
+ *      
+ *     DESTROY
+ *      {DATE}.delete.sql - the delete data sql.
+ *      {DATE}.delete.sh - shell script to delete the files related to these records
+ *    
+ *  Basically it has to output all the records and their dependants. (parent and children)
+ *
+ *  Then when deleting it deletes record + children..
+ *
+ *
+ *  Each ouput is simple insert statement..
+ *
+ *
+ *  TODO - handle Images table (or similar) where we use tablename=XXXX, tid=.... etc..
+ *
+ *
+ *  INTERFACES :
+ *
+ *      DataObjects->archivePaths() - returns array ( sourcedirectory, remainder of path to dependant file )
+ *      DataObjects->listThumbs() - returns array ( list of full path to thumbnail urls. )
+ *
+ *
+ *  DISCOVERY
+ *    
+ *
+ * 
+ */
+
+require_once 'Pman.php';
+
+class Pman_Admin_Export extends Pman_Admin_Dump {
+    
+    function getAuth()
+    {
+        
+        if (!HTML_FlexyFramework::get()->cli) {
+            die("Access only permitted from cli");
+        }
+        
+    }
+    var $args = array();
+    var $deps = array(); // list of dependants
+    var $out = array(); // list of created sql/shell scripts.
+    
+    var $uid = array();
+    
+    function get($path )
+    {
+        ini_set('memory_limit', '256M'); // we need alot of memory
+        set_time_limit(0);
+        
+        $argv = $_SERVER['argv'];
+        array_shift($argv);
+        array_shift($argv);
+        
+        $opts = explode(',', 'table==,where==,dump-dir==,debug=');
+        require_once 'Console/Getopt.php';
+        $go = Console_Getopt::getopt2($argv, '', $opts );
+        if (is_object($go)) {
+            die($go->toString());
+        }
+         
+        foreach($go[0] as $ar) {
+            $args[substr($ar[0],2)] = $ar[1];
+        }
+        $errs = array();
+        foreach($opts as $req) {
+            if (substr($req,-2, 2) != '==') { // skip optional arguments
+                continue;
+            }
+            if (empty($args[substr($req,0, -2)])) {
+                $errs[] = "--".substr($req,0, -2) . ' is required';
+            }
+        }
+        if (!empty($errs)) {
+            die(print_R($errs,true));
+        }
+        if (!empty($args['debug'])) {
+            DB_DataObject::debugLevel($args['debug']);
+        }
+        $this->args = $args;
+        $this->out = array();
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        $this->discoverChildren($this->args['table'], $this->args['where'], true);
+        //print_R($this->deletes);
+        //print_r($this->dumps);
+        //exit;
+        
+        $this->discover($this->args['table'], $this->args['where'], true);
+         
+        
+        if (!file_exists($args['dump-dir'])) {
+            mkdir($args['dump-dir'], 0777, true);
+        }
+          
+          
+          // create uid's
+        
+        // dump items..
+        
+        
+          
+        echo "GENERATED FILES:\n";
+        // summary
+        echo "    ". implode("\n    ", $this->out). "\n";
+        
+        
+        exit;
+        
+      
+         
+    }
+     
+    var $deletes = array(); // TABLE => [key] => TRUE|FALSE
+    var $dumps = array(); // TABLE => [key] => TRUE|FALSE - if it's been scanned..
+    var $dscan = array(); // TABLE:COL => [value => TRUE|FALSE] - if its been scanned..
+    var $childfiles = array(); // array of [ 'sourcedirectory' , 'subdirectory(s) and filename' ]
+    var $childthumbs = array(); // array of [ 'filename', 'filename' ,......]
+    var $filesize = 0; // size of files to be saved. (not total deletd..)
+    var $filetotal = 0; // number of distinct files to be saved (not total deleted)
+    /**
+     * scan table for
+     * a) what depends on it (eg. child elements) - which will be deleted.
+     * b) what it depends on it (eg. parent elements) - which will be dumped..
+     */
+      
+    
+    
+    function generateDelete() {  
+        $target = $this->args['dump-dir'] .'/'. date('Y-m-d').'.delete.sql';
+        $this->out[] = $target;
+        $fh = fopen($target, 'w');
+        
+        
+        
+        foreach($this->deletes as $tbl=>$ar) {
+            
+            $do = DB_DataObject::factory($tbl);
+            $tbl = $do->tableName();
+            $keys = $do->keys();
+            $key = $keys[0];
+            $do->whereAddIn($keys[0] , array_keys($ar), 'int');
+            $do->find();
+            $archivePaths = method_exists($do,'archivePaths');
+            $listThumbs = method_exists($do,'listThumbs');
+            while ($do->fetch()) {
+                
+                if ($archivePaths) {
+                    $ct = $do->archivePaths();
+                    if ($ct) {
+                        $this->childfiles[] = $ct;
+                    }
+                }
+                if ($listThumbs) {
+                    $ct = $do->listThumbs();
+                    if($ct) {
+                        $this->childthumbs[] = $ct;
+                    }
+                }
+                $id = $do->$key;
+                
+                fwrite($fh, "DELETE FROM `$tbl` WHERE `$key` = $id;\n"); // we assume id's and nice column names...
+            }
+            $do->free();
+        }
+        fclose($fh);
+    }
+    function generateShell() {
+        
+        if (empty($this->childfiles) && empty($this->childthumbs)) {
+            return;
+        }
+        $target = $this->args['dump-dir'] .'/'. date('Y-m-d').'.copy.sh';
+        $this->out[] = $target;
+        $fh = fopen($target, 'w');
+        
+        $target = $this->args['dump-dir'] .'/'. date('Y-m-d').'.delete.sh';
+        $this->out[] = $target;
+        $fh2 = fopen($target, 'w');
+        
+        $target = $this->args['dump-dir'] .'/'. date('Y-m-d').'.restore.sh';
+        $this->out[] = $target;
+        $fh3 = fopen($target, 'w');
+        
+      
+        $done = array();
+        $donedir  = array();
+        foreach($this->childfiles as  $v) {
+            
+            if (isset($done[$v[1]])) {
+                continue;
+            }
+            
+            $done[$v[1]] = true;
+            
+            $this->filesize += filesize($v[0].'/'.$v[1]);
+            $this->filetotal++;
+            $fdir = dirname($this->args['dump-dir'] .'/'.$v[1]);
+            if (!isset($donedir[$fdir])) { 
+                fwrite($fh,"mkdir -p " . escapeshellarg(dirname($this->args['dump-dir'] .'/'.$v[1])) ."\n" );
+            }
+            fwrite($fh,"cp " . escapeshellarg($v[0].'/'.$v[1]) . ' ' . escapeshellarg($this->args['dump-dir'] .'/'.$v[1]) ."\n" );
+            if (!isset($donedir[$fdir])) { 
+                fwrite($fh3,"mkdir -p " . escapeshellarg(dirname($v[0].'/'.$v[1])) ."\n" );
+            }
+            $donedir[$fdir] = true;
+            
+            fwrite($fh3,"cp " .  escapeshellarg($this->args['dump-dir'] .'/'.$v[1]) . ' ' . escapeshellarg($v[0].'/'.$v[1]) . "\n" );
+            fwrite($fh2,"rm " . escapeshellarg($v[0].'/'.$v[1]) ."\n" );
+        }
+        fclose($fh);
+        fclose($fh3); // restore does not need to bother with thumbnails.
+         
+        
+        
+        foreach($this->childthumbs as  $v) {
+            foreach($v as $vv) { 
+                fwrite($fh2,"rm " . escapeshellarg($vv). "\n");
+            }
+        }
+        fclose($fh2);
+    }
+     
+    function generateInsert()
+    {
+        $target = $this->args['dump-dir'] .'/'. date('Y-m-d').'.sql';
+        $this->out[] = $target;
+        $fh = fopen($target,'w');
+         
+         
+        
+        foreach($this->dumps as $tbl => $ar) {
+            if (empty($ar)) {
+                continue;
+            }
+            $do = DB_DataObject::factory($tbl);
+             
+            $keys = $do->keys();
+         
+            $do->whereAddIn($keys[0] , array_keys($ar), 'int');
+            $do->find();
+            while ($do->fetch()) {
+                fwrite($fh,$this->toInsert($do));
+            }
+             $do->free();
+            
+        }
+        fclose($fh);
+        
+        
+    }
+
+    
+      
+    /**
+     * toInsert - does not handle NULLS... 
+     */
+    function toInsert($do)
+    {
+        $kcol = array_shift($do->keys());
+         
+        // for auto_inc column we need to use a 'set argument'...
+        $items = $do->table();
+        //print_R($items);
+        
+        // for
+        $leftq     = '';
+        $rightq    = '';
+        
+        $table = $do->tableName();
+        
+         
+        foreach(  $items  as $k=>$v)
+        {
+            if ($leftq) {
+                $leftq  .= ', ';
+                $rightq .= ', ';
+            }
+            
+            $leftq .= '`' . $k . '`';
+            
+             
+            
+            
+            if ($v & DB_DATAOBJECT_STR) {
+                $rightq .= $do->_quote((string) (
+                        ($v & DB_DATAOBJECT_BOOL) ? 
+                            // this is thanks to the braindead idea of postgres to 
+                            // use t/f for boolean.
+                            (($do->$k === 'f') ? 0 : (int)(bool) $do->$k) :  
+                            $do->$k
+                    )) . " ";
+                continue;
+            }
+            if (is_numeric($do->$k)) {
+                $rightq .=" {$do->$k} ";
+                continue;
+            }
+            $rightq .= ' ' . intval($do->$k) . ' ';
+        }
+        
+        return "INSERT INTO `{$table}` ($leftq) VALUES ($rightq);\n";
+        
+    }
+    
+    
+}