<?php

namespace Topxia\Service\Util;


class MySQLDumper
{



    public $target = '';
    private $dbSettings = array();
    private $internelSetting = array(
        'exclude' => array(),
        'isDropTable' => true,
        'hasTransaction' => true,
        'lockread' => true,
        'lockwrite' => true,
        'isextend' => true
        );

    private $connection;

    public function __construct ($connection, $settings = array())
    {
        $this->connection = $connection;
        $this->dbSettings = $settings;
        $this->connection->exec("SET NAMES utf8");
 
    }

    private function getSet($key){
        if(array_key_exists($key, $this->dbSettings)){
            return $this->dbSettings[$key];
        }else{
            return $this->internelSetting[$key];
        }
    }


 
    public function export($target)
    {
       $target .=  ".gz";

       if ( !is_writable( dirname($target)) ) {
             throw new \Exception("无导出目录写权限，无法导出数据库", 1);
       }

        $tables = array();
        foreach ($this->connection->query("SHOW TABLES") as $table) {
            $tables[] = current($table);
        }
 
        $file =  gzopen($target, "wb");

        $this->lineWrite($file, "-- --------------------------------------------------\n");
        $this->lineWrite($file, "-- ---------------- 导出数据库\n");
        $this->lineWrite($file, "-- ---------------- 时间:". date('Y-m-d H:i:s')."\n\n");
        $this->lineWrite($file, "-- ---------------- 数据库:{$this->connection->getDatabase()} \n\n");
        $this->lineWrite($file, "-- ---------------- 主机:{$this->connection->getHost()} \n\n");
        $this->lineWrite($file, "-- --------------------------------------------------\n\n\n");

        foreach ($tables as $table) {
            if ($this->exportTableCreateSql($file,$table)) {
                if ( in_array($table, $this->getSet('exclude'), true) ) {
                    continue;
                }                
                try{
                    $this->exportValues($file,$table);
                }catch(\Exception $e){
                    $this->connection->rollback();
                    if ( $this->getSet('lockread') ) {
                        $this->connection->exec("UNLOCK TABLES");
                    }
                    throw new \Exception($e->getMessage());
                }
            }
        }
       gzclose($file);
       return $target;
    }

    private function lineWrite($file,$line)
    {
        gzwrite($file, $line);
    }


    private function exportTableCreateSql($file,$table)
    {
        $sql = "SHOW CREATE TABLE {$table}";
        foreach ($this->connection->query($sql) as $row) {
            if (isset($row['Create Table']) ) {
                $line  = "-- --------------------------------------------------\n\n";
                $line .= "-- -------------- 表:{$table} 的表结构  -------------- \n\n";
                $line .= "-- --------------------------------------------------\n\n";

                if ( $this->getSet('isDropTable') ) {
                    $line .= " DROP TABLE IF EXISTS {$table} ; \n";
                }
                $line .= $row['Create Table'];
                $line .= ";\n\n";
                $this->lineWrite($file,$line);
                return true;
            }
            if ( isset($row['Create View']) ) {
                $line  = "-- --------------------------------------------------\n\n";
                $line .= "-- -------------- 视图:{$table} 的表结构  -------------- \n\n";
                $line .= "-- --------------------------------------------------\n\n";
                $line .= $row['Create View'];
                $line .= ";\n\n";
                               
                $this->lineWrite($file,$line);

                return false;
            }
        }
    }


    private function exportValues($file,$table)
    {
        $this->lineWrite($file,"-- ----------- {$table} 的数据 ---------\n\n");

        if ( $this->getSet('hasTransaction') ) {
            $this->connection->setTransactionIsolation(3);
            $this->connection->beginTransaction();
        }
        if ( $this->getSet('lockread') ) {
            $this->connection->exec("LOCK TABLES `$table` READ LOCAL");
        }

        if ( $this->getSet('lockwrite') ) {
            $this->lineWrite($file,"LOCK TABLES `$table` WRITE;\n");
        }

        $insertExclude = true; 
        $sql = "SELECT * FROM `$table`";
        foreach ($this->connection->query($sql, \PDO::FETCH_NUM) as $row) {
            $vals = array();
            foreach ($row as $val) {
                $vals[] = is_null($val) ? "NULL" :
                    $this->connection->quote($val);
            }
            if ($insertExclude || !$this->getSet('isextend') ) {
                $this->lineWrite($file,
                    "INSERT INTO {$table} VALUES (" .implode(",", $vals) . ")");
                $insertExclude = false;
            } else {
                $this->lineWrite($file,",(" .implode(",", $vals) . ")");
            }
        }
        if ( !$insertExclude ) {
           $this->lineWrite($file,";\n\n");
        }
        if ( $this->getSet('lockwrite') ) {
            $this->lineWrite($file,"UNLOCK TABLES;\n");
        }
        if ( $this->getSet('hasTransaction') ) {
            $this->connection->commit();
        }
        if ( $this->getSet('lockread') ) {
            $this->connection->exec("UNLOCK TABLES");
        }
        $this->lineWrite($file,"\n\n");
        $this->lineWrite($file,"-- ----------- {$table} 的数据结束 ---------\n\n");
    }
}

