| <?php
/**
 * DB Updater
 * 
 * Reads the structure from one database and transfers
 * it to another one using a transport file.
 * Adds missing fields to existing tables and missing
 * tables to the destination database.
 * This script doesn't delete fields, tables and data
 * from any of the databases.
 *
 * -----------------------------------------------------
 * @copyright       © 2016-2021 Spider IT Deutschland
 * @author          René Mansveld
 * @company         Spider IT Deutschland
 * @link            https://www.spider-it.de
 * @created         2016-02-18
 * -----------------------------------------------------
 * @modified
 *  2021-08-06 RM   - Switched to MySQLi
 */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<?php
    # Input Variablen auswerten
    $server   = $_POST['server'];
    $database = $_POST['database'];
    $user     = $_POST['user'];
    $password = $_POST['password'];
    $file     = $_POST['file'];
    $action   = $_POST['action'];
    
    $step     = (($action == '1') ? ' - Read out' : (($action == '2') ? ' - Update' : ''));
    $fullpath = substr($_SERVER['SCRIPT_FILENAME'], 0, strrpos($_SERVER['SCRIPT_FILENAME'], '/') + 1) . $file;
    
    function flushme(){
        // check that buffer is actually set before flushing
        if (ob_get_length()) {            
            @ob_flush();
            @flush();
            @ob_end_flush();
        }    
        @ob_start();
    }
    @ob_start();
?>
<style type="text/css">
	* {
		box-sizing: border-box;
	}
    body {
        font-family: Arial, Helvetica, sans-serif;
        font-size: 13px;
        font-weight: bold;
        color: #FFF;
        background-color: #000;
    }
    h1 {
        font-size: 18px;
        color: #F90;
    }
    h2 {
        font-size: 16px;
        color: #66F;
    }
    .clear {
        clear: both;
        height: 2px;
    }
    .red {
        color: #F00;
        padding-left: 10px;
    }
    .green {
        color: #0C0;
        padding-left: 10px;
    }
	input {
		height: 1.6em;
		border: 1px solid grey;
		border-radius: 3px;
	}
	input[type=text] {
		background-color: white;
	}
	input[type=button] {
		font-weight: bold;
		background-color: lightgrey;
		cursor: pointer;
	}
	input[type=button]:hover {
		background-color: white;
	}
</style>
<script type="text/javascript">
    function execute(action) {
        document.getElementById('action').value = action;
        document.f1.submit();
    }
</script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Spider IT Deutschland Database Updater<?php echo $step; ?></title>
</head>
<body>
    <div align="center">
        <div align="left" style="width: 520px;">
            <h1>Spider IT Deutschland Database Updater<?php echo $step; ?></h1>
            <h2>Enter data and select process ...</h2>
            <form id="f1" name="f1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
                <input type="hidden" id="action" name="action" value="" />
                
                <div style="float: left; width: 150px; padding-top: 5px;">Server:</div>
                <div style="float: right; width: 365px;"><input type="text" name="server" value="<?php echo $server; ?>" style="width: 365px;" /></div>
                <div class="clear"></div>
                
                <div style="float: left; width: 150px; padding-top: 5px;">Database:</div>
                <div style="float: right; width: 365px;"><input type="text" name="database" value="<?php echo $database; ?>" style="width: 365px;" /></div>
                <div class="clear"></div>
                
                <div style="float: left; width: 150px; padding-top: 5px;">Username:</div>
                <div style="float: right; width: 365px;"><input type="text" name="user" value="<?php echo $user; ?>" style="width: 365px;" /></div>
                <div class="clear"></div>
                
                <div style="float: left; width: 150px; padding-top: 5px;">Password:</div>
                <div style="float: right; width: 365px;"><input type="password" name="password" value="<?php echo $password; ?>" style="width: 365px;" /></div>
                <div class="clear"></div>
                
                <div style="float: left; width: 150px; padding-top: 5px;">Transport file:</div>
                <div style="float: right; width: 365px;"><input type="text" name="file" value="<?php echo $file; ?>" style="width: 365px;" /></div>
                <div class="clear"></div>
                
                <div style="float: left; width: 150px; padding-top: 5px;">Action:</div>
                <div style="float: right; width: 365px;">
                    <div style="float: left;"><input type="button" name="action1" value="Read out" onclick="execute(1)" style="width: 181px; margin: 0px;" /></div>
                    <div style="float: right;"><input type="button" name="action2" value="Update" onclick="execute(2)" style="width: 181px; margin: 0px;" /></div>
                </div>
                <div class="clear"></div>
            </form>
<?php
    switch ($action) {
        case '1':
        case '2':
            echo '<h2>Selected operation is carried out</h2>'; flushme();
            echo '<div>A connection to the MySQL server is established ...</div>'; flushme();
            if ($db = new mysqli($server, $user, $password, $database)) {
                echo '<div class="green">Connected.</div>'; flushme();
            } else {
                die('<div class="red">No connection possible!</div>');
            }
            break;
    }
    switch ($action) {
        case '1': #read
            echo '<div>The structure of the database is analyzed.<br />Step 1: list tables ...</div>'; flushme();
            if ($rec = $db->query('SHOW TABLES')) {
                while ($row = mysqli_fetch_array($rec)) {
                    $tables[] = array('name' => $row[0], 'fields' => array(), 'tabledef' => '');
                }
                echo '<div class="green">Listing successful, ' . count($tables) . ' tables.</div>'; flushme();
            } else {
                die('<div class="red">Listing failed!</div>');
            }
            echo '<div>Step 2: List columns per table ...</div>'; flushme();
            for ($i = 0; $i < count($tables); $i ++) {
                if ($rec = $db->query('SHOW COLUMNS FROM ' . $tables[$i]['name'])) {
                    if (mysqli_num_rows($rec) > 0) {
                        while ($row = mysqli_fetch_assoc($rec)) {
                            $tables[$i]['fields'][] = $row;
                        }
                    }
                    echo '<div class="green">' . count($tables[$i]['fields']) . ' columns for table' . $tables[$i]['name'] . '</div>'; flushme();
                } else {
                    die('<div class="red">Listing failed for table ' . $tables[$i]['name'] . '!</div>');
                }
            }
            echo '<div>Step 3: List table definitions ...</div>'; flushme();
            for ($i = 0; $i < count($tables); $i ++) {
                if ($rec = $db->query('SHOW CREATE TABLE ' . $tables[$i]['name'])) {
                    if (mysqli_num_rows($rec) > 0) {
                        while ($row = mysqli_fetch_assoc($rec)) {
                            $tables[$i]['tabledef'] = str_replace('
', ' ', str_replace(chr(10), ' ', str_replace(chr(13), '', $row['Create Table'])));
                        }
                    }
                    echo '<div class="green">Definition for table ' . $tables[$i]['name'] . ' successful</div>'; flushme();
                } else {
                    die('<div class="red">Definition for table ' . $tables[$i]['name'] . ' failed!</div>');
                }
            }
            echo '<div>Step 4: writing the transport file ...</div>'; flushme();
            if ($fp = fopen($fullpath, 'w')) {
                fwrite($fp, '-- Table Fields --
');
                for ($i = 0; $i < count($tables); $i ++) {
                    for ($j = 0; $j < count($tables[$i]['fields']); $j ++) {
                        fwrite($fp, $tables[$i]['name'] . '|' . $tables[$i]['fields'][$j]['Field'] . '|' . $tables[$i]['fields'][$j]['Type'] . '|' . $tables[$i]['fields'][$j]['Null'] . '|' . $tables[$i]['fields'][$j]['Key'] . '|' . $tables[$i]['fields'][$j]['Default'] . '|' . $tables[$i]['fields'][$j]['Extra'] . '
');
                    }
                }
                fwrite($fp, '-- Table Definitions --
');
                for ($i = 0; $i < count($tables); $i ++) {
                    fwrite($fp, $tables[$i]['name'] . '|' . $tables[$i]['tabledef'] . '
');
                }
                fclose($fp);
                echo '<div class="green">Transport file created successfully.</div>'; flushme();
            } else {
                die('<div class="red">Failed to create the file!</div>');
            }
            echo '<div>Path to the transport file</div>'; flushme();
            echo '<div style="padding-left: 10px;">On server: ' . $fullpath . '</div>'; flushme();
            if (!isset($_SERVER['SCRIPT_URL'])) {
                $_SERVER['SCRIPT_URL'] = $_SERVER['SCRIPT_NAME'];
            }
            echo '<div style="padding-left: 10px;">In domain: ' . substr($_SERVER['SCRIPT_URL'], 0, strrpos($_SERVER['SCRIPT_URL'], '/') + 1) . $file . '</div>'; flushme();
            if (!isset($_SERVER['SCRIPT_URI'])) {
                $_SERVER['SCRIPT_URI'] = 'http' . ((strtolower($_SERVER['HTTPS']) == 'on') ? 's' : '') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER['SCRIPT_NAME'];
            }
            echo '<div style="padding-left: 10px;">Online: <a href="' . substr($_SERVER['SCRIPT_URI'], 0, strrpos($_SERVER['SCRIPT_URI'], '/') + 1) . $file . '">' . substr($_SERVER['SCRIPT_URI'], 0, strrpos($_SERVER['SCRIPT_URI'], '/') + 1) . $file . '</a></div>'; flushme();
            echo '<div style="height: 10px;"></div>'; flushme();
            break;
        case '2': #update
            echo '<div>Update<br />Step 1: Read data from the transport file ...</div>'; flushme();
            $fields = array();
            $tabledefs = array();
            if ($fp = fopen($fullpath, 'r')) {
                $action = 'fields';
                while (!feof($fp)) {
                    $line = trim(fgets($fp));
                    if ($line == '-- Table Fields --') {
                        $action = 'fields';
                    } elseif ($line == '-- Table Definitions --') {
                        $action = 'tabledefs';
                    } else {
                        switch($action) {
                            case 'fields':
                                $line = explode('|', $line);
                                $fields[] = array('table' => $line[0], 'field' => $line[1], 'type' => $line[2], 'null' => $line[3], 'key' => $line[4], 'default' => $line[5], 'extra' => $line[6]);
                                break;
                            case 'tabledefs':
                                $tmp = explode('|', $line);
                                if (count($tmp) > 2) {
                                    $tmp[1] = implode('|', array_slice($tmp, 1));
                                }
                                $tabledefs[] = $tmp;
                                break;
                        }
                    }
                }
                echo '<div class="green">Transport file read successfully.</div>'; flushme();
            } else {
                die('<div class="red">Failed to read the file!</div>');
            }
            echo '<div>Step 2: Update the tables ...</div>'; flushme();
            $neueFelder = 0;
            $nvtabellen = array();
            for ($i = 0; $i < count($fields); $i ++) {
                if (strlen($fields[$i]['table'])) {
                    # Existiert die Tabelle? (Wenn nicht, Spalteninfo sammeln und anschließend Tabelle anlegen)
                    if (mysqli_num_rows($db->query('SHOW TABLES LIKE \'' . $fields[$i]['table'] . '\';')) == 0) {
                        if (((count($nvtabellen) > 0) && ($nvtabellen[count($nvtabellen) - 1] != $fields[$i]['table'])) || (count($nvtabellen) == 0)) {
                            $nvtabellen[] = $fields[$i]['table'];
                        }
                    } else {
                        # Existiert die Spalte?
                        if (!$db->query('SELECT `' . $fields[$i]['field'] . '` FROM `' . $fields[$i]['table'] . '` LIMIT 0, 1;')) {
                            # Spalte anlegen
                            $sql = 'ALTER TABLE `' . $fields[$i]['table'] . '` ADD `' . $fields[$i]['field'] . '` ' . $fields[$i]['type'] . (((strlen($fields[$i]['extra'])) && (substr($fields[$i]['extra'], 0, 9) == 'on update')) ? ' ' . $fields[$i]['extra'] : '') . ((strtolower($fields[$i]['null']) == 'no') ? ' NOT NULL' : '') . ((strlen($fields[$i]['default'])) ? ((strtoupper($fields[$i]['default']) == 'CURRENT_TIMESTAMP') ? ' default CURRENT_TIMESTAMP' : ' default \'' . $fields[$i]['default'] . '\'') : '') . (((strlen($fields[$i]['extra'])) && (substr($fields[$i]['extra'], 0, 9) != 'on update')) ? ' ' . $fields[$i]['extra'] : '');
                            if ($db->query($sql)) {
                                $neueFelder ++;
                                echo '<div class="green">Field ' . $fields[$i]['field'] . ' for table ' . $fields[$i]['table'] . ' successfully created.</div>'; flushme();
                            } else {
                                die('<div class="red">Creation of field ' . $fields[$i]['field'] . ' for table ' . $fields[$i]['table'] . ' failed!</div><div>' . $sql . '</div>');
                            }
                        }
                    }
                }
            }
            echo '<div>Step 3: add new tables ...</div>'; flushme();
            $neueTabellen = 0;
            for ($i = 0; $i < count($nvtabellen); $i ++) {
                for ($j = 0; $j < count($tabledefs); $j ++) {
                    if ($tabledefs[$j][0] == $nvtabellen[$i]) {
                        if ($db->query($tabledefs[$j][1])) {
                            echo '<div class="green">Table ' . $tabledefs[$j][0] . ' successfully created.</div>'; flushme();
                            $neueTabellen ++;
                        } else {
                            die('<div class="red">Create table '. $tabledefs[$j][0] . 'failed!</div><div>' . mysqli_error($db) . '</div><div>' . $sql . '</div>');
                        }
                        break;
                    }
                }
            }
            echo '<div>Update completed successfully.</div>'; flushme();
            echo '<div class="green">' . $neueFelder . ' fields added.</div>'; flushme();
            echo '<div class="green">' . $neueTabellen . ' tables added.</div>'; flushme();
            echo '<div style="height: 10px;"></div>'; flushme();
            break;
    }
?>
        </div>
    </div>
</body>
</html>
 |