CVS update: /cowiki/htdocs/setup/class/task/migrator/

[email protected] 12 May 2005 17:10:30 -0000
Newsgroups gmane.comp.php.cowiki.cvs
Message-ID <[email protected]>
User: dgorski 
Date: 2005/05/12 10:10:30

Modified:
   cowiki/htdocs/setup/class/task/migrator/class.Migrator_0.php

Log:
 Rewrite

File Changes:

Directory: /cowiki/htdocs/setup/class/task/migrator/
====================================================

File [changed]: class.Migrator_0.php
Url: http://cowiki.tigris.org/source/browse/cowiki/htdocs/setup/class/task/migrator/class.Migrator_0.php?r1=1.5&r2=1.6
Delta lines:  +154 -48
----------------------
--- class.Migrator_0.php	8 May 2005 00:57:51 -0000	1.5
+++ class.Migrator_0.php	12 May 2005 17:10:28 -0000	1.6
@@ -2,7 +2,7 @@
 
 /**
  *
- * $Id: class.Migrator_0.php,v 1.5 2005/05/08 00:57:51 dgorski Exp $
+ * $Id: class.Migrator_0.php,v 1.6 2005/05/12 17:10:28 dgorski Exp $
  *
  * This file is part of coWiki. coWiki is free software under the terms of
  * the GNU General Public License (GPL). Read the LICENSE file. If you did
@@ -17,7 +17,7 @@
  * @author      Daniel T. Gorski, <[email protected]>
  * @copyright   (C) Daniel T. Gorski, {@link http://www.develnet.org}
  * @license     http://www.gnu.org/licenses/gpl.html
- * @version     $Revision: 1.5 $
+ * @version     $Revision: 1.6 $
  *
  */
 
@@ -47,12 +47,13 @@
     public function getDescription() {
         $aArr = array();
 
-        if ($this->State->mustCreateNewConnectorUser()) {
-            $aArr[] = 'Initial creation of a connector user.';
+        if ($this->State->shallCreateNewConnectorUser()) {
+            $aArr[] = 'Creation (or update) of the database connector user.';
         }
 
-        if ($this->State->mustCreateNewDocumentDatabase()) {
-            $aArr[] = 'Initial creation of the document database schema.';
+        if ($this->State->shallCreateNewDocumentDatabase()) {
+            $aArr[] = 'Initial creation of the document
+                       database schema (if necessary).';
         }
 
         return $aArr;
@@ -69,18 +70,16 @@
     public function perform() {
 
         // Connect with root credentials and dispatch
-        if ($this->State->mustCreateNewConnectorUser()
-            || $this->State->mustCreateNewDocumentDatabase()) {
+        if ($this->State->shallCreateNewConnectorUser()
+            || $this->State->shallCreateNewDocumentDatabase()) {
 
             // Connect with root user
             $sResource = $this->State->getDocumentStorageRootDSN();
+            $UriInfo = new UriInfo($sResource);
 
-            $Storage = StorageFactory::getInstance()
-                          ->createDocumentStorage($sResource);
+            $Storage = StorageFactory::getInstance()->create($UriInfo);
 
             // Dispatch due to the different access schemes
-            $UriInfo = new UriInfo($sResource);
-
             switch ($UriInfo->get('scheme')) {
                 case 'mysql':
                 case 'mysql+innodb':
@@ -103,7 +102,8 @@
 
     private function createMySqlScheme($Storage) {
 
-        // Connector user data (not root user!)
+        // Get connector user data (not root user!) BUT we are connected
+        // as root user!
         $sResource = $this->State->getDocumentStorageDSN();
         $UriInfo = new UriInfo($sResource);
 
@@ -113,45 +113,114 @@
         $sDB   = $UriInfo->get('basepath');
 
         // If necessary, create a connector user
-        if ($this->State->mustCreateNewConnectorUser()) {
+        if ($this->State->shallCreateNewConnectorUser()) {
 
-            // Insert new user
-            $sQuery = " INSERT INTO mysql.user
-                           SET host     = '".$sHost."',
-                               user     = '".$sUser."',
-                               password = PASSWORD('".$sPass."')";
+            // Let the database create an encrypted password
+            $aData = $Storage->fetchArrayAndFreeResult(
+                        $Storage->query(
+                            "SELECT PASSWORD('".$sPass."') AS new_pass"
+                        )
+                     );
 
-            $Storage->query($sQuery);
+            // Fields for 'mysql.user'
+            $aFields = array(
+                'host'      =>  $sHost,
+                'user'      =>  $sUser,
+                'password'  =>  $aData['new_pass']
+            );
 
             // ---
 
-            // Define database and set privileges
-            $sQuery = " INSERT INTO mysql.db
-                           SET host                   = '".$sHost."',
-                               db                     = '".$sDB."',
-                               user                   = '".$sUser."',
-                               select_priv            = 'Y',
-                               insert_priv            = 'Y',
-                               update_priv            = 'Y',
-                               delete_priv            = 'Y',
-                               create_priv            = 'Y',
-                               drop_priv              = 'Y',
-                               references_priv        = 'Y',
-                               index_priv             = 'Y',
-                               alter_priv             = 'Y',
-                               create_tmp_table_priv  = 'Y',
-                               lock_tables_priv       = 'Y'";
+            $Storage->begin();
         
-            $Storage->query($sQuery);
+            try {
+
+                // Check if connector user is already in 'mysql.user'
+                $sQuery = "SELECT COUNT(password) AS rec_count
+                             FROM mysql.user
+                            WHERE user = '".$sUser."'";
+    
+                $aData = $Storage->fetchArrayAndFreeResult(
+                            $Storage->query($sQuery)
+                         );
+
+                // No such user yet, insert him/her
+                if ((int)$aData['rec_count'] == 0) {
+
+                    // Set further data for insert
+                    $aInsert = array(
+                        'table'  => 'mysql.user',
+                        'fields' => $aFields
+                    );
+                    $Storage->insert($aInsert);
+
+                } else {
+
+                    // User already there, set further data for update
+                    $aUpdate = array(
+                        'table'  => 'mysql.user',
+                        'fields' => $aFields,
+                        'where'  => "user = '".$sUser."'"
+                    );
+                    $Storage->update($aUpdate);
+                }
+
+                // ---
+
+                // Insert user <-> database permissions
+                $aRemove = array(
+                    'table'  => 'mysql.db',
+                    'where'  => "db = '".$sDB."'"
+                );
+                $Storage->remove($aRemove);
+
+                // Fields for 'mysql.db'
+                $aFields = array(
+                    'host'                  =>  $sHost,
+                    'user'                  =>  $sUser,
+                    'db'                    =>  $sDB,
+                    'select_priv'           =>  'Y',
+                    'insert_priv'           =>  'Y',
+                    'update_priv'           =>  'Y',
+                    'delete_priv'           =>  'Y',
+                    'create_priv'           =>  'Y',
+                    'drop_priv'             =>  'Y',
+                    'references_priv'       =>  'Y',
+                    'index_priv'            =>  'Y',
+                    'alter_priv'            =>  'Y',
+                    'create_tmp_table_priv' =>  'Y',
+                    'lock_tables_priv'      =>  'Y'
+                );
+
+                $aInsert = array(
+                    'table'  => 'mysql.db',
+                    'fields' => $aFields,
+                    'where'  => "db = '".$sDB."'"
+                );
+                $Storage->insert($aInsert);
+                
+            } catch (StorageException $se) {
+
+                // End transaction
+                $Storage->rollback();
+                throw $se;
+            }
+    
+            // End transaction
+            $Storage->commit();
+
+            // ------------------------------------------------------------
 
             // Done
-            $this->State->setMustCreateNewConnectorUser(false);
+            $this->State->setShallCreateNewConnectorUser(false);
+
+            // Reload the database, initialize settings
             $Storage->reload();
         }
 
         // ----------------------------------------------------------------
 
-        if ($this->State->mustCreateNewDocumentDatabase()) {
+        if ($this->State->shallCreateNewDocumentDatabase()) {
 
             $sPath = $this->State->getMiscPath();
             $sFile = '/database/mysql.sql';
@@ -181,6 +250,39 @@
 
             // ---
 
+            // Begin transaction
+            $Storage->begin();
+
+            // Check if database already exists
+            $aDB = $Storage->fetchRowAndFreeResult(
+                $Storage->query('SHOW DATABASES LIKE "'.$sDB.'"')
+            );
+
+            // A database with this name was found. Check if it seems to
+            // contain valid tables. Avoid accidents.
+            if (isset($aDB[0])) {
+                $Storage->useDatabase($sDB);
+
+                // Check if database contains tables that are prefixed
+                // with "cowiki_"
+                $aTable = $Storage->fetchRowAndFreeResult(
+                    $Storage->query('SHOW TABLES LIKE "cowiki_%"')
+                );
+
+                if (!is_array($aTable)) {
+                    $Storage->rollback();
+
+                    throw new MigratorException(
+                        'The selected database \''.$sDB.'\' is already there
+                        and does not seem to be a valid '.COWIKI_NAME.'
+                        database. Heck, what are you doing? Be careful,
+                        you are logged on as database administrator!'
+                    );
+                }
+            }
+
+            // No database with this name found, create it 
+            if (!isset($aDB[0])) {
             $Storage->query('CREATE DATABASE '.$sDB);
             $Storage->useDatabase($sDB);
             
@@ -188,9 +290,13 @@
             foreach ($aContent as $sQuery) {
                 $Storage->query($sQuery);
             }
+            }
+
+            // End transaction
+            $Storage->commit();
 
             // Done
-            $this->State->setMustCreateNewDocumentDatabase(false);
+            $this->State->setShallCreateNewDocumentDatabase(false);
         }
     }