Source for file mvblog_upgrade.php

Documentation is available at mvblog_upgrade.php

  1. <?php
  2. /**
  3.  * MvBlog -- An open source no-nosense blogtool
  4.  *
  5.  * Copyright (C) 2005-2007, Michiel van Baak
  6.  * Michiel van Baak <mvanbaak@users.sourceforge.net>
  7.  *
  8.  * See http://dev.mvblog.org for more information on MvBlog.
  9.  * That page also provides Bugtrackers, Filereleases etc.
  10.  *
  11.  * This program is free software, distributed under the terms of
  12.  * the GNU General Public License Version 2. See the LICENSE file
  13.  * at the top of the source tree.
  14.  *
  15.  * @package MvBlog
  16.  * @author Michiel van Baak
  17.  * @version %%VERSION%%
  18.  * @copyright 2005-2007 Michiel van Baak
  19.  */
  20. /*
  21.  * Start the autoloader, so we never have to include anything
  22.  */
  23. require_once("mvblog_autoloader.php");
  24. $mvblog_AutoLoader new mvblog_AutoLoader();
  25.  
  26. $pathInfo pathinfo(__FILE__);
  27. $mvblog_AutoLoader->registerPath($pathInfo["dirname"]"%s.php"mvblog_AutoLoader::OPT_LOWERCASE);
  28.  
  29. // Register the AutoLoader object as the autoloader.
  30. function __autoload($className{
  31.   global $mvblog_AutoLoader;
  32.   $mvblog_AutoLoader->autoload($className);
  33. }
  34.  
  35. /* Start heavy error reporting if we're on a dev site */
  36.  
  37. /* Read the configuration file */
  38. $configfile dirname(dirname(__FILE__)."../")."/conf/mvblog.ini";
  39. $availSettings array(
  40.     "general" => array(
  41.         "debug"    => array("type" => mvblog_IniFileReader::TYPE_BOOL,   "default" => "no"),
  42.     ),
  43.     "database" => array(
  44.         "database" => array("type" => mvblog_IniFileReader::TYPE_STRING"default" => "mvblog"),
  45.         "hostname" => array("type" => mvblog_IniFileReader::TYPE_STRING"default" => "localhost"),
  46.         "username" => array("type" => mvblog_IniFileReader::TYPE_STRING"default" => "mvblog"),
  47.         "password" => array("type" => mvblog_IniFileReader::TYPE_STRING"default" => "mvblog"),
  48.         "type"     => array("type" => mvblog_IniFileReader::TYPE_STRING"default" => "mysql"),
  49.     ),
  50. );
  51. $config new mvblog_IniFileReader($availSettings$configfile);
  52. /**
  53.  * Uprade mvblog to the latest version
  54.  */
  55. Class Mvblog_upgrade extends Mvblog_common {
  56.     /* variables */
  57.     public $lastpatch = 0;
  58.     public $lang;
  59.     /* methods */
  60.     /* __construct {{{ */
  61.     /**
  62.      * Class constructor
  63.      */
  64.     public function __construct({
  65.         parent::__construct("plugins/"01);
  66.     }
  67.     /* }}} */
  68.     /* get_patchfiles {{{ */
  69.     /**
  70.      * Find out what patchfiles we need to commit.
  71.      *
  72.      * @param string $mode Can be svn or release and is used to pick the filenameformat.
  73.      * @return array Patchfiles that should be applied to the database
  74.      */
  75.     public function get_patchfiles($mode "release"{
  76.         /* get current database version */
  77.         if (!array_key_exists("dbversion"$this->settings))
  78.             $current_version 0;
  79.         else
  80.             $current_version $this->settings["dbversion"];
  81.         /* read the db patchfiles into an array */
  82.         $patchfiles array();
  83.         if ($dh opendir(sprintf("upgrades/%s"$this->db->phptype))) {
  84.             while (false !== ($v readdir($dh))) {
  85.                 if (!is_dir($v&& $v != "README"{
  86.                     if ($mode == "release"{
  87.                         if (strpos($v"to"&& substr($v0strpos($v"to")) >= $current_version)
  88.                             $patchfiles[$v;
  89.                     else {
  90.                         if (!strpos($v"to"&& basename($v".php"$current_version)
  91.                             $patchfiles[$v;
  92.                     }
  93.                 }
  94.             }
  95.         }
  96.         return $patchfiles;
  97.     }
  98.     /* }}} */
  99.     /* sql_addslashes {{{ */
  100.     /**
  101.      * Better addslashes for SQL queries.
  102.      * Taken from phpMyAdmin and modified by me.
  103.      */
  104.     function sql_addslashes($a_string ''$is_like FALSE{
  105.         if ($is_like)
  106.             $a_string str_replace('\\''\\\\\\\\'$a_string);
  107.         else
  108.             $a_string str_replace('\\''\\\\'$a_string);
  109.         $a_string str_replace('\"''\\\"'$a_string);
  110.         return str_replace('\'''\\\''$a_string);
  111.     
  112.     /* }}} */
  113.     /* create_backups {{{ */
  114.     /**
  115.      * Create a database backup before running the pathes against it so we can rollback when something goes wrong
  116.      */
  117.     public function create_backups({
  118.         $backuplocation "backups/";
  119.         $dbname         $this->db->database_name;
  120.         if (!is_dir($backuplocation&& !is_writable($backuplocation))
  121.             die("Backupdir not available. Please create a directory 'backups' and give the webserver user write permissions on it.");
  122.         // make backup
  123.         switch ($this->db->phptype{
  124.         case "sqlite" :
  125.             //copy old database
  126.             $src sprintf("db/%s.db"$dbname);
  127.             $dst sprintf("backups/%s-%s.db"$dbnamedate("YmdHi"));
  128.             if (copy($src$dst))
  129.                 return true;
  130.             else
  131.                 return false;
  132.             break;
  133.         case "mysql" :
  134.             //create database dump
  135.             return $this->_mysql_backup_db($dbname$backuplocation);
  136.             break;
  137.         case "pgsql" :
  138.             //create database dump
  139.             return $this->_psql_backup_db($dbname$backuplocation);
  140.             break;
  141.         default :
  142.             die("unknown database type. Please report on http://dev.mvblog.org");
  143.             break;
  144.         }
  145.     }
  146.     /* }}} */
  147.     /* _mysql_backup_db {{{ */
  148.     /**
  149.      * Create mysql backup
  150.      *
  151.      * @param string $database The database name to backup
  152.      * @param string $backuplocation The directory to store the backup in
  153.      * @return bool true on success, false on failure
  154.      */
  155.     private function _mysql_backup_db($database$backuplocation{
  156.         //variable to hold the database
  157.         $dbdata  "-- MvBlog upgrade backup dump\n";
  158.         $dbdata .= "--\n";
  159.         $dbdata .= sprintf("-- Host: %s\n"$this->db->dsn["hostspec"]);
  160.         $dbdata .= sprintf("-- Database: %s\n"$database);
  161.         $dbdata .= sprintf("-- Dump started on %s\n\n"date("Y-m-d H:i:s"));
  162.         $dbdata .= "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n";
  163.         $dbdata .= "/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\n";
  164.         $dbdata .= "/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\n";
  165.         $dbdata .= "/*!40101 SET NAMES utf8 */;\n";
  166.         $dbdata .= "/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;\n";
  167.         $dbdata .= "/*!40103 SET TIME_ZONE='+00:00' */;\n";
  168.         $dbdata .= "/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n";
  169.         $dbdata .= "/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n";
  170.         $dbdata .= "/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n";
  171.         $dbdata .= "/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\n\n";
  172.         // get the tables in the database
  173.         $sql "SHOW TABLES";
  174.         $res $this->db->query($sql);
  175.         while ($row $res->fetchRow()) {
  176.             $table $row[0];
  177.             $dbdata .= sprintf("--\n-- Table structure for table '%s'\n--\n\n"$table);
  178.             $dbdata .= sprintf("DROP TABLE IF EXISTS %s;\n"$table);
  179.             $q sprintf("SHOW CREATE TABLE %s"$table);
  180.             $r $this->db->query($q);
  181.             while ($tabledata $r->fetchRow()) {
  182.                 $dbdata .= $tabledata[1].";\n\n";
  183.             }
  184.             $dbdata .= sprintf("--\n-- Dumping data for table '%s'\n--\n\n"$table);
  185.             $dbdata .= sprintf("LOCK TABLES `%s` WRITE;\n"$table);
  186.             $dbdata .= sprintf("/*!40000 ALTER TABLE `%s` DISABLE KEYS */;\n"$table);
  187.  
  188.             // get table structure
  189.             $q sprintf("DESCRIBE %s"$table);
  190.             $r $this->db->query($q);
  191.             $tablestruct array();
  192.             while ($ts $r->fetchRow(MDB2_FETCHMODE_ASSOC)) {
  193.                 $tablestruct[$ts;
  194.             }
  195.             // find fields that dont need ' as data enclosure
  196.             $ints array();
  197.             foreach ($tablestruct as $struct{
  198.                 if (strpos($struct["type"]"bigint"=== ||
  199.                     strpos($struct["type"]"int"=== || 
  200.                     strpos($struct["type"]"mediumint"=== ||
  201.                     strpos($struct["type"]"smallint"=== ||
  202.                     strpos($struct["type"]"tinyint"=== ||
  203.                     strpos($struct["type"]"timestamp"=== 0)
  204.                         $ints[strtolower($struct["field"])1;
  205.             }
  206.             $q sprintf("SELECT * FROM %s"$table);
  207.             $r $this->db->query($q);
  208.             // \x08\\x09, not required
  209.             $search array("\x00""\x0a""\x0d""\x1a");
  210.             $replace array('\0''\n''\r''\Z');
  211.             while ($tabledata $r->fetchRow(MDB2_FETCHMODE_ASSOC)) {
  212.                 $dbdata .= sprintf("INSERT INTO `%s` VALUES ("$table);
  213.                 $values array();
  214.                 foreach ($tabledata as $k=>$v{
  215.                     if (array_key_exists($k$ints))
  216.                         $values[$v;
  217.                     else
  218.                         $values["'".str_replace($search$replace$this->sql_addslashes($v))."'";
  219.                 }
  220.                 $dbdata .= implode(","$values);
  221.                 $dbdata .= ");\n";
  222.             }
  223.             $dbdata .= sprintf("/*!40000 ALTER TABLE `%s` ENABLE KEYS */;\n"$table);
  224.             $dbdata .= "UNLOCK TABLES;\n\n";
  225.         }
  226.         $dbdata .= "/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;\n\n";
  227.         $dbdata .= "/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n";
  228.         $dbdata .= "/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n";
  229.         $dbdata .= "/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n";
  230.         $dbdata .= "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n";
  231.         $dbdata .= "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n";
  232.         $dbdata .= "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n";
  233.         $dbdata .= "/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n\n";
  234.         $dbdata .= sprintf("-- Dump completed on %s"date("Y-m-d H:i:s"));
  235.  
  236.         $backupfile sprintf($backuplocation."%s-%s.mysql"$databasedate("YmdHi"));
  237.         return file_put_contents($backupfile$dbdata);
  238.     }
  239.     /* }}} */
  240.     /* _psql_backup_db {{{ */
  241.     /**
  242.      * Create postgresql backup. Code and ideas borrowed from phpPgAdmin.
  243.      *
  244.      * @param string $database The database name to backup
  245.      * @param string $backuplocation The directory to store the backup in
  246.      * @return bool true on success, false on failure
  247.      */
  248.     private function _psql_backup_db($database$backuplocation{
  249.         // set enviroment vars needed by pg_dump
  250.         $server_info array();
  251.         $server_info["username"$this->db->dsn["username"];
  252.         $server_info["password"$this->db->dsn["password"];
  253.         $server_info["host"]     $this->db->dsn["hostspec"];
  254.         $server_info["port"]     $this->db->dsn["port"];
  255.  
  256.         putenv('PGPASSWORD=' $server_info['password']);
  257.         putenv('PGUSER=' $server_info['username']);
  258.         $hostname $server_info['host'];
  259.         if ($hostname !== null && $hostname != ''{
  260.             putenv('PGHOST=' $hostname);
  261.         }
  262.         $port $server_info['port'];
  263.         if ($port !== null && $port != ''{
  264.             putenv('PGPORT=' $port);
  265.         }
  266.  
  267.         $backupfile sprintf($backuplocation."%s-%s.psql"$databasedate("YmdHi"));
  268.         $cmd "pg_dump -i ";
  269.         $cmd .= sprintf("-f %s %s"$backupfile$database);
  270.         $output system($cmd$retval);
  271.         if ($retval === 0)
  272.             return true;
  273.         else
  274.             return false;
  275.     }
  276.     /* }}} */
  277.     /* set_latest_version {{{ */
  278.     /**
  279.      * Update/create dbversion setting in the database
  280.      *
  281.      * @param int $version The latest patchlevel we applied to the database
  282.      */
  283.     public function set_latest_version($version=0{
  284.         if (array_key_exists("dbversion"$this->settings&& $this->settings["dbversion"]{
  285.             /* update the entry */
  286.             $sql sprintf("UPDATE settings SET settingvalue = '%s' WHERE settingname = 'dbversion'"$version);
  287.         else {
  288.             /* create the entry */
  289.             $sql sprintf("INSERT INTO settings (settingname, settingvalue) VALUES ('dbversion', '%s')"$version);
  290.         }
  291.         $res $this->db->exec($sql);
  292.         if (PEAR::isError($res))
  293.             return false;
  294.         else
  295.             return true;
  296.     }
  297.     /* }}} */
  298.     /* apply_dbpatch {{{ */
  299.     /**
  300.      * Apply a specific database patch
  301.      *
  302.      * @param int $patch The patch to apply
  303.      */
  304.     public function apply_dbpatch($patch$mode "release"{
  305.         $patchfile sprintf("upgrades/%s/%s"$this->db->phptype$patch);
  306.         if (file_exists($patchfile)) {
  307.             require_once($patchfile);
  308.             foreach ($sql as $query{
  309.                 $res $this->db->exec($query);
  310.                 if (PEAR::isError($res))
  311.                     return false;
  312.             }
  313.         }
  314.         if ($mode == "release")
  315.             $this->lastpatch = substr(basename($patch".php")strpos($patch"to")+2);
  316.         else
  317.             $this->lastpatch = basename($patch".php");
  318.         return true;
  319.     }
  320.     /* }}} */
  321. }
  322. ?>

Documentation generated on Fri, 28 Dec 2007 13:17:41 +0100 by phpDocumentor 1.4.1