Location: PHPKode > scripts > DBSync > dbsync/class.dbsync.php
<?php
	/**
     * Class DBSync
     * Sync 2 or more databases. For now it only supports structure wich
     * is the most essencial part.
     *
     * @author Diogo Resende <hide@address.com>
     * @licence GPL
     *
     * @method DBSync::SetHomeDatabase()
     * @method DBSync::AddSyncDatabase()
     * @method DBSync::Sync()
     **/
	class DBSync {
    	var $home = array();
        var $sync = array();

        /**
         * DBSync::DBSync()
		 * Class constructor
         *
         * @param	optional	string	$database	Home Database Name
         * @param	optional	string	$type		Home Database Type
         * @param	optional	string	$host		Home Host (can be diferent from localhost :D)
         * @param	optional	string	$user		Home Database Username
         * @param	optional	string	$pass		Home Database Password
         *
         * @access	public
         * @return 	void
         **/
    	function DBSync($database = '', $type = 'mysql', $host = 'localhost', $user = 'root', $pass = '') {
        	if (strlen($database) > 0) {
            	$this->SetHomeDatabase($database, $type, $host, $user, $pass);
            }
        }

        /**
         * DBSync::SetHomeDatabase()
         * Set definitions for home database. This is the database that should be
         * correct and all others will be synched with this one.
         *
         * @param				string	$database	Home Database Name
         * @param	optional	string	$type		Home Database Type
         * @param	optional	string	$host		Home Host (can be diferent from localhost :D)
         * @param	optional	string	$user		Home Database Username
         * @param	optional	string	$pass		Home Database Password
         *
         * @access	public
         * @return 	void
         **/
        function SetHomeDatabase($database, $type = 'mysql', $host = 'localhost', $user = 'root', $pass = '') {
        	if (!class_exists("DBSync_{$type}")) {
            	include dirname(__FILE__) . "/class.dbsync.{$type}.php";
            }

            $class = "DBSync_{$type}";

            $this->home = new $class($host, $user, $pass, $database);
            if (!$this->home->ok) {
            	$this->RaiseError('Home Database Error: ' . $this->home->LastError());
            }
        }

        /**
         * DBSync::AddSyncDatabase()
         * Add a database to sync with the home database. You can add as many as
         * you want.
         *
         * @param				string	$database	Database Name
         * @param	optional	string	$type		Database Type
         * @param	optional	string	$host		Host
         * @param	optional	string	$user		Database Username
         * @param	optional	string	$pass		Database Password
         *
         * @access	public
         * @return 	void
         **/
        function AddSyncDatabase($database, $type = 'mysql', $host = 'localhost', $user = 'root', $pass = '') {
        	if (!class_exists("DBSync_{$type}")) {
            	include dirname(__FILE__) . "/class.dbsync.{$type}.php";
            }

            $class = "DBSync_{$type}";

            $sync = new $class($host, $user, $pass, $database);
            if (!$sync->ok) {
            	$this->RaiseError('Sync Database Error: ' . $this->home->LastError());
            }
            $this->sync[] = $sync;
        }

        /**
         * DBSync::Sync()
         * Sync defined databases with home database
         *
         * @access	public
         * @return 	boolean		Success
         **/
        function Sync() {
        	if (count($this->sync) == 0) {
            	$this->RaiseError('No Sync Databases defined. Use AddSyncDatabase() to add Sync Databases.');
            }

            for ($i = 0; $i < count($this->sync); $i++) {
            	$this->SyncDatabases($this->home, $this->sync[$i]);
            }

            return true;
        }

        /**
         * DBSync::SyncDatabases()
         * Sync one database with home database
         *
         * @access	private
         * @return 	boolean		Success
         **/
        function SyncDatabases(&$db_home, &$db_sync) {
        	$tables_home = $db_home->ListTables();
            $tables_sync = $db_sync->ListTables();

            for ($i = 0; $i < count($tables_home); $i++) {
            	if (!in_array($tables_home[$i], $tables_sync)) {
                	$fields = $db_home->ListTableFields($tables_home[$i]);
					if (!$db_sync->CreateTable($tables_home[$i], $fields)) {
                    	$this->RaiseError("Could not create table <strong>{$tables_home[$i]}</strong> on database <strong>{$db_sync->database}</strong> at {$db_sync->user}@{$db_sync->host}: " . $db_sync->LastError());
                    }
                } else {
					$fields_home = $db_home->ListTableFields($tables_home[$i]);
                    $fields_sync = $db_sync->ListTableFields($tables_home[$i]);
                    $fieldnames_sync = $this->GetFieldNames($fields_sync);

                    $diferent_fields = 0;

                    for ($j = 0; $j < count($fields_home); $j++) {
                    	if (!in_array($fields_home[$j]['name'], $fieldnames_sync)) {
                            if (!isset($fields_home[$j - 1])) {
                            	$success = $db_sync->AddTableField($tables_home[$i], $fields_home[$j], 0);
                            } else {
	                        	$success = $db_sync->AddTableField($tables_home[$i], $fields_home[$j], $fields_home[$j - 1]['name']);
                            }
                            if (!$success) {
								$this->RaiseError("Could not add field <strong>{$fields_home[$j]['name']}</strong> to table <strong>{$tables_home[$i]}</strong> on database <strong>{$db_sync->database}</strong> at {$db_sync->user}@{$db_sync->host}: " . $db_sync->LastError());
                            }
                            $diferent_fields++;
                        } else {
                        	$k = $this->GetFieldIndex($fields_sync, $fields_home[$j]['name']);
                            if ($fields_sync[$k]['type'] != $fields_home[$j]['type'] ||
                                $fields_sync[$k]['null'] != $fields_home[$j]['null'] ||
                                $fields_sync[$k]['key'] != $fields_home[$j]['key'] ||
                                $fields_sync[$k]['default'] != $fields_home[$j]['default'] ||
                                $fields_sync[$k]['extra'] != $fields_home[$j]['extra']) {
                                if (!$db_sync->ChangeTableField($tables_home[$i], $fields_home[$j]['name'], $fields_home[$j])) {
	                                $this->RaiseError("Could not change field <strong>{$fields_home[$j]['name']}</strong> on table <strong>{$tables_home[$i]}</strong> on database <strong>{$db_sync->database}</strong> at {$db_sync->user}@{$db_sync->host}: " . $db_sync->LastError());
                                }
                                $diferent_fields++;
                            }
                        }

		                unset($fieldnames_sync[array_shift(array_keys($fieldnames_sync, $fields_home[$j]['name']))]);
                    }

                    if ($diferent_fields > 0) {
                    	/**
                         * Arrange Primary Keys
                         **/
                        $keys_home = $this->GetPrimaryKeys($fields_home);
                        $keys_sync = $this->GetPrimaryKeys($fields_sync);
                        if ($this->DiferentKeys($keys_home, $keys_sync)) {
	                        if (count($keys_home) > 0) {
    	                    	$db_sync->SetTablePrimaryKeys($tables_home[$i], $keys_home);
        	                } else {
            	            	$db_sync->ClearTablePrimaryKeys($tables_home[$i]);
                	        }
                        }
                    }

        		    foreach ($fieldnames_sync as $field) {
                    	if (!$db_sync->RemoveTableField($tables_home[$i], $field)) {
	                        $this->RaiseError("Could not change field <strong>{$field}</strong> on table <strong>{$tables_home[$i]}</strong> on database <strong>{$db_sync->database}</strong> at {$db_sync->user}@{$db_sync->host}: " . $db_sync->LastError());
                        }
		            }
                }

                unset($tables_sync[array_shift(array_keys($tables_sync, $tables_home[$i]))]);
            }

            foreach ($tables_sync as $table) {
            	if (!$db_sync->RemoveTable($table)) {
	                $this->RaiseError("Could not remove table <strong>{$table}</strong> on database <strong>{$db_sync->database}</strong> at {$db_sync->user}@{$db_sync->host}: " . $db_sync->LastError());
                }
            }

            return true;
        }

        /**
         * DBSync::GetFieldNames()
         * Return the names of the fields on the field list array
         *
         * @param	array	$fields		Field List
         *
         * @access	private
         * @return 	array		Field Names
         **/
        function GetFieldNames($fields) {
        	$names = array();
            for ($i = 0; $i < count($fields); $i++) {
            	$names[] = $fields[$i]['name'];
            }

            return $names;
        }

        /**
         * DBSync::GetFieldIndex()
         * Return the index (array key) of the field with the given name
         *
         * @param	array	$fields		Field List
         * @param	string	$name		Field Name
         *
         * @access	private
         * @return 	array		Field Index
         **/
        function GetFieldIndex($fields, $name) {
            for ($i = 0; $i < count($fields); $i++) {
            	if ($fields[$i]['name'] == $name) {
                	return $i;
                }
            }
            return false;
        }

        /**
         * DBSync::GetPrimaryKeys()
         * Returns a list of field names wich are primary keys
         *
         * @param	array	$fields		Field List
         *
         * @access	private
         * @return 	array		Primary Keys Field List
         **/
        function GetPrimaryKeys($fields) {
        	$keys = array();
            for ($i = 0; $i < count($fields); $i++) {
            	if ($fields[$i]['key'] == 'PRI') {
	            	$keys[] = $fields[$i]['name'];
                }
            }

            return $keys;
        }

        /**
         * DBSync::DiferentKeys()
         * Compares two primary keys field lists and checks if
         * they are diferent from each other.
         *
         * @param	array	$fields_home	Primary Keys Field List 1
         * @param	array	$fields_sync	Primary Keys Field List 2
         *
         * @access	private
         * @return 	boolean		"Are diferent?"
         **/
        function DiferentKeys($keys_home, $keys_sync) {
        	if (count($keys_home) != count($keys_sync)) {
            	return true;
            }

            for ($i = 0; $i < count($keys_home); $i++) {
            	if ($keys_home[$i] != $keys_sync[$i]) {
                	return true;
                }
            }

            return false;
        }

        /**
         * DBSync::RaiseError()
         * Displays error message and aborts execution of the program
         *
         * @param	string	$description	Error description
         *
         * @access	private
         * @return 	void
         **/
        function RaiseError($description) {
        	echo "<h3>Error</h3><hr />\n" .
                 $description;
			exit(1);
        }
    }
?>
Return current item: DBSync