cs-webdbupgrade-commits Mailing List for CS Web DB Upgrade (Page 2)
Status: Inactive
Brought to you by:
crazedsanity
You can subscribe to this list here.
2009 |
Jan
(7) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
(13) |
Aug
(18) |
Sep
|
Oct
|
Nov
|
Dec
|
---|
From: <cra...@us...> - 2009-07-16 18:55:13
|
Revision: 15 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=15&view=rev Author: crazedsanity Date: 2009-07-16 18:55:06 +0000 (Thu, 16 Jul 2009) Log Message: ----------- Removed some missed debug printing. /cs_webdbupgrade.class.php: * perform_upgrade(): -- remove debug_print on details (they're logged) * is_higher_version(): -- remove debug_print about checking suffixes. * get_upgrade_list(): -- remove debug_print about adding an entry from the MATCHING array. * fix_xml_config(): -- remove commented-out debug print. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-16 18:46:43 UTC (rev 14) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-16 18:55:06 UTC (rev 15) @@ -279,7 +279,6 @@ foreach($upgradeList as $fromVersion=>$toVersion) { $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; - $this->gfObj->debug_print($details); $this->logsObj->log_by_class($details, 'system'); $this->do_single_upgrade($fromVersion); $this->get_database_version(); @@ -687,7 +686,6 @@ // the "$checkIfHigher" is actually higher, don't bother (i.e. suffixes don't matter when // we already know there's a major, minor, or maintenance version that's also higher. if($retval === FALSE) { - $this->gfObj->debug_print(__METHOD__ .": checking suffixes... "); //EXAMPLE: $version="1.0.0-BETA3", $checkIfHigher="1.1.0" // Moving from a non-suffixed version to a suffixed version isn't supported, but the inverse is: // i.e. (1.0.0-BETA3 to 1.0.0) is okay, but (1.0.0 to 1.0.0-BETA3) is NOT. @@ -777,7 +775,6 @@ $retval[$this->databaseVersion] = $matchVersion; } //the MATCHING version is NOT higher than the version file's version, looks ok. - $this->gfObj->debug_print(__METHOD__ .": adding (". $matchVersion .")"); $lastVersion = $data['TARGET_VERSION']; $retval[$matchVersion] = $data['TARGET_VERSION']; } @@ -841,7 +838,6 @@ //========================================================================= private function fix_xml_config($config, $path=null) { - #$this->gfObj->debug_print(__METHOD__ .": path=(". $path ."):: ". $this->gfObj->debug_print($config,0)); $this->xmlLoops++; if($this->xmlLoops > 1000) { throw new exception(__METHOD__ .": infinite loop detected..."); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-16 18:46:51
|
Revision: 14 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=14&view=rev Author: crazedsanity Date: 2009-07-16 18:46:43 +0000 (Thu, 16 Jul 2009) Log Message: ----------- Remove debug printing when upgrade runs, more logging. /cs_webdbupgrade.class.php: * __construct(): -- check if DEBUGPRINTOPT is a defined constant before using it. -- use constant() when getting value of DEBUGPRINTOPT constant to avoid PHP warnings/notices. * perform_upgrade(): -- log stuff as debug instead of debug_print()ing. * check_for_version_conflict(): -- log a debugging message instead of using debug_print() * do_single_upgrade(): -- remove debug printing -- log completion of the upgrade. * update_database_version(): -- remove some debug printing * check_database_version(): -- remove debug printing of data -- log version check failure as FATAL * do_scripted_upgrade(): -- log when the script is about to start -- log when the script is done. * is_higher_version(): -- log a debug message if the new version looks lower than current -- remove TONS of possible debug printing. -- log if target version has a suffix & current doesn't (i.e. 'upgrading' from 1.0.0 to 1.0.0-BETA1). * get_upgrade_list(): -- log a warning when it encounters an odd entry (this is most often a problem with the XML file's format... there is probably a better way to explain the problem, but I don't know what that would be right now: this error is incredibly rare in my experience). -- log debug message about skipping an entry. -- remove a very unuseful debug message -- log debug message for no intermediary version upgrades. * fix_xml_config(): -- log the cs_arrayToPath{} exceptions before throwing them (again) Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-15 20:25:11 UTC (rev 13) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-16 18:46:43 UTC (rev 14) @@ -99,7 +99,9 @@ $this->fsObj = new cs_fileSystem(constant('SITE_ROOT')); $this->gfObj = new cs_globalFunctions; - $this->gfObj->debugPrintOpt = DEBUGPRINTOPT; + if(defined('DEBUGPRINTOPT')) { + $this->gfObj->debugPrintOpt = constant('DEBUGPRINTOPT'); + } if(!defined('DBTYPE')) { throw new exception(__METHOD__ .": required constant 'DBTYPE' not set"); @@ -260,7 +262,7 @@ throw new exception(__METHOD__ .": failed to set 'upgrade in progress'"); } else { - $this->gfObj->debug_print(__METHOD__ .": result of setting 'upgrade in progress': (". $lockConfig .")"); + $this->logsObj->log_by_class(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug'); //push data into our internal "config" array. $this->read_upgrade_config_file(); @@ -272,7 +274,7 @@ $upgradeList = $this->get_upgrade_list(); $i=0; - $this->gfObj->debug_print(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion .")..."); + $this->logsObj->log_by_class(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion .")...", 'debug'); $this->db->beginTrans(__METHOD__); foreach($upgradeList as $fromVersion=>$toVersion) { @@ -284,12 +286,11 @@ $i++; $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; - $this->gfObj->debug_print($details); $this->logsObj->log_by_class($details, 'system'); } if($this->databaseVersion == $this->versionFileVersion) { - $this->gfObj->debug_print(__METHOD__ .": finished upgrading after performing (". $i .") upgrades!!!"); + $this->logsObj->log_by_class(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); $this->newVersion = $this->databaseVersion; } else { @@ -421,8 +422,7 @@ } if($retval !== false) { - $this->logsObj->log_by_class('Upgrading '. $retval .', db version is ('. $dbVersion['version_string'] .'), versionFile is ('. $versionFileData['version_string'] .')', 'DEBUG'); - $this->gfObj->debug_print(__METHOD__ .": upgrading ". $retval ." versions, from (". $this->databaseVersion .") to (". $this->versionFileVersion .")"); + $this->logsObj->log_by_class("Upgrading ". $retval ." versions, from (". $this->databaseVersion .") to (". $this->versionFileVersion .")", 'debug'); } return($retval); @@ -477,7 +477,6 @@ private function do_single_upgrade($targetVersion) { //Use the "matching_syntax" data in the upgrade.xml file to determine the filename. $versionIndex = "V". $this->get_full_version_string($targetVersion); - $this->gfObj->debug_print(__METHOD__ .": versionIndex=(". $versionIndex ."), config MATCHING::: ". $this->gfObj->debug_print($this->config['UPGRADELIST']['MATCHING'],0)); if(!isset($this->config['UPGRADELIST']['MATCHING'][$versionIndex])) { //version-only upgrade. $this->newVersion = $this->versionFileVersion; @@ -504,7 +503,7 @@ throw new exception(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); } } - $this->gfObj->debug_print(__METHOD__ .": done... "); + $this->logsObj->log_by_class("Finished upgrade to ". $targetVersion); }//end do_single_upgrade() //========================================================================= @@ -516,7 +515,6 @@ * so the version there is consistent with all the others. */ protected function update_database_version($newVersionString) { - $this->gfObj->debug_print(__METHOD__ .": setting (". $newVersionString .")"); $versionArr = $this->parse_version_string($newVersionString); $queryArr = array(); @@ -569,8 +567,7 @@ } if(!$retval) { - $this->gfObj->debug_print($data); - $this->gfObj->debug_print(__METHOD__ .": versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")"); + $this->logsObj->log_by_class("Version check failed, versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")", 'FATAL'); } } @@ -588,7 +585,7 @@ private function do_scripted_upgrade(array $upgradeData) { $myConfigFile = $upgradeData['SCRIPT_NAME']; - $this->gfObj->debug_print(__METHOD__ .": script name=(". $myConfigFile .")"); + $this->logsObj->log_by_class("Preparing to run script '". $myConfigFile ."'", 'debug'); //we've got the filename, see if it exists. if(isset($this->config['UPGRADE_SCRIPTS_DIR'])) { @@ -619,7 +616,7 @@ else { throw new exception(__METHOD__ .": upgrade failed (". $upgradeResult .")"); } - $this->gfObj->debug_print(__METHOD__ .": finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")"); + $this->logsObj->log_by_class("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug'); } else { throw new exception(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod @@ -677,7 +674,7 @@ } else { //TODO: should there maybe be an option to throw an exception (freak out) here? - debug_print(__METHOD__ .": while checking ". $index .", realized the new version (". $checkIfHigher .") is LOWER than current (". $version .")",1); + $this->logsObj->log_by_class(__METHOD__ .": while checking ". $index .", realized the new version (". $checkIfHigher .") is LOWER than current (". $version .")",'debug'); } } else { @@ -697,7 +694,6 @@ // Also: (1.0.0-BETA3 to 1.0.0-BETA4) is okay, but (1.0.0-BETA4 to 1.0.0-BETA3) is NOT. if(strlen($curVersionSuffix) && strlen($checkVersionSuffix) && $curVersionSuffix == $checkVersionSuffix) { //matching suffixes. - $this->gfObj->debug_print(__METHOD__ .": suffixes match"); } elseif(strlen($curVersionSuffix) || strlen($checkVersionSuffix)) { //we know the suffixes are there and DO match. @@ -707,19 +703,15 @@ $checkVersionData = $this->parse_suffix($checkVersionSuffix); if($curVersionData['type'] == $checkVersionData['type']) { - $this->gfObj->debug_print(__METHOD__ .": got the same type..."); //got the same suffix type (like "BETA"), check the number. if($checkVersionData['number'] > $curVersionData['number']) { - $this->gfObj->debug_print(__METHOD__ .": new version's suffix number higher than current... "); $retval = TRUE; } elseif($checkVersionData['number'] == $curVersionData['number']) { - $this->gfObj->debug_print(__METHOD__ .": new version's suffix number is EQUAL TO current... "); $retval = FALSE; } else { //umm... they're identical??? LOGIC HAS FAILED ME ALTOGETHER!!! - $this->gfObj->debug_print(__METHOD__ .": new version's suffix number is LESS THAN current... "); $retval = FALSE; } } @@ -729,9 +721,6 @@ if($suffixValues[$checkVersionData['type']] > $suffixValues[$curVersionData['type']]) { $retval = TRUE; } - else { - $this->gfObj->debug_print(__METHOD__ .": current suffix type is higher... "); - } } } @@ -741,17 +730,12 @@ } elseif(!strlen($curVersionSuffix) && strlen($checkVersionSuffix)) { //i.e. "1.0.0" to "1.0.0-BETA1" --->>> NOT ACCEPTABLE! - $this->gfObj->debug_print(__METHOD__ .": from (". $version .") to (". $checkIfHigher .") isn't acceptable...?"); + $this->logsObj->log_by_class(__METHOD__ .": from (". $version .") to (". $checkIfHigher .") isn't acceptable...?", 'debug'); } } - else { - $this->gfObj->debug_print(__METHOD__ .": no suffix to care about"); - } } } - $this->gfObj->debug_print(__METHOD__ .": ('". $version ."', '". $checkIfHigher ."') retval=(". $retval .")", 1); - return($retval); }//end is_higher_version() @@ -798,22 +782,21 @@ $retval[$matchVersion] = $data['TARGET_VERSION']; } else { - $this->gfObj->debug_print(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")"); + $this->logsObj->log_by_class(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")", 'warning'); } } else { - $this->gfObj->debug_print(__METHOD__ .": SKIPPING (". $matchVersion .")"); + $this->logsObj->log_by_class(__METHOD__ .": SKIPPING (". $matchVersion .")", 'debug'); } } if($lastVersion !== $newVersion && (!isset($retval[$lastVersion]) || $retval[$lastVersion] != $newVersion)) { - $this->gfObj->debug_print(__METHOD__ .": <b>ALSO (". $lastVersion .") => (". $newVersion .")</b>"); $retval[$lastVersion] = $newVersion; } } else { //no intermediary upgrades: just pass back the latest version. - $this->gfObj->debug_print(__METHOD__ .": no intermediary upgrades"); + $this->logsObj->log_by_class(__METHOD__ .": no intermediary upgrades", 'debug'); $retval[$dbVersion] = $this->versionFileVersion; } @@ -868,8 +851,8 @@ $a2p = new cs_arrayToPath($config); } catch(exception $e) { - $this->gfObj->debug_print($config); - exit("died on #1"); + $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); + throw new exception($e->getMessage()); } if(!is_array($this->tempXmlConfig)) { $this->tempXmlConfig = array(); @@ -878,8 +861,8 @@ $myA2p = new cs_arrayToPath(&$this->tempXmlConfig); } catch(exception $e) { - - exit("died on #2"); + $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); + throw new exception($e->getMessage()); } $myData = $a2p->get_data($path); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-15 20:25:19
|
Revision: 13 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=13&view=rev Author: crazedsanity Date: 2009-07-15 20:25:11 +0000 (Wed, 15 Jul 2009) Log Message: ----------- Fix version-only upgrades. /cs_webdbupgrade.class.php: * do_single_upgrade(): -- comments for which is version-only and which is scripted. -- remove some debugging statements. -- set newVersion before updating database version (so the check called from update_database_version() succeeds). Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-15 19:01:11 UTC (rev 12) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-15 20:25:11 UTC (rev 13) @@ -479,16 +479,12 @@ $versionIndex = "V". $this->get_full_version_string($targetVersion); $this->gfObj->debug_print(__METHOD__ .": versionIndex=(". $versionIndex ."), config MATCHING::: ". $this->gfObj->debug_print($this->config['UPGRADELIST']['MATCHING'],0)); if(!isset($this->config['UPGRADELIST']['MATCHING'][$versionIndex])) { - $this->gfObj->debug_print(__METHOD__ .": doing version-only upgrade..."); - - $this->gfObj->debug_print($this->config['UPGRADELIST']['MATCHING']); - exit; //version-only upgrade. - $this->update_database_version($this->versionFileVersion); $this->newVersion = $this->versionFileVersion; + $this->update_database_version($this->versionFileVersion); } else { - $this->gfObj->debug_print(__METHOD__ .": doing scripted upgrade..."); + //scripted upgrade... $scriptIndex = $versionIndex; $upgradeData = $this->config['UPGRADELIST']['MATCHING'][$versionIndex]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-15 19:01:18
|
Revision: 12 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=12&view=rev Author: crazedsanity Date: 2009-07-15 19:01:11 +0000 (Wed, 15 Jul 2009) Log Message: ----------- Scripted upgrades, use lockfile (not system config), explain system. NOTE:: this system handles a LOT of database-side logging: that should be wrapped in a local method, so each time it can check to see if certain things should be logged, and if the cs_webdblogger system is setup at all. NOTE2::: this system should log the exceptions before throwing them. Consider an internal method (preferrably that uses reflection to figure out which method called it, instead of passing that as an argument) /cs_webdbupgrade.class.php: * MAIN::: -- ADDED HEADERS TO VARS: + fsObj + gfObj + db + logsObj + versionFileVersion -- new private var, $lockfile * __construct(): -- require SITE_ROOT to be a defined constant -- require the cs_phpxmlCreator class -- use SITE_ROOT as the root directory for fsObj -- require RWDIR to be in the configuration. -- set internal lockfile location -- throw an exception if there is an existing lockfile: same basic functionality as using the WORKINGONIT index of the site's configuration, except this way doesn't require the code to deal with anything in order to stop touching the database (or whatever). * check_versions(): -- remove unnecessary redundant logic -- updated logic for updated return values from check_for_version_conflict() (returns false) * read_version_file(): -- call get_full_version_string() when setting internal versionFileVersion to avoid conflicts between strings that are technically identical (i.e. "1.0-ALPHA1" and "1.0.0-ALPHA1") * read_upgrade_file(): -- use the configured UPGRADE_CONFIG_FILE setting to locate the upgrade XML file instead of hard-coding it. -- set 'UPGRADELIST' into the internal configuration array, or throw an exception if something looks wrong. * perform_upgrade(): -- don't bother checking if the config file is writable -- handle lockfile instead of modifying the site-wide config file. * upgrade_in_progress(): -- put details into a lockfile instead of updating the config file. * parse_version_string(): -- fix logic problem (version always loses the suffix) -- always add 'version_suffix' index. * check_for_version_conflict(): -- returns false if no conflict -- log stuff if it doesn't return false * do_single_upgrade(): -- call get_full_version_string() to ensure the version string will ALWAYS be in the proper form. -- debug saying it is a scripted upgrade -- different location for upgradeData. * update_database_version(): -- converted into a single SQL statement instead of multiple. -- use cs_phpDB::run_update() instead of (non-existent) internal method run_sql() * check_database_version(): -- ARG CHANGE: ARG DELETED: #1 ($checkThisVersion) -- use internal 'newVersion' variable for checking against. * do_scripted_upgrade(): -- use configured UPGRADE_SCRIPTS_DIR, or derive it (log a warning if it has to be derived) -- log that it is a scripted upgrade. * run_sql() [DELETED]: -- superceded by cs_phpDB::run_query(), cs_phpDB::run_update(), and cs_phpDB::run_insert(). * update_config_file() [DELETED]: -- uses a lock file instead of touching the site's configuration file. * get_num_users_to_convert() [DELETED]: -- something with CS-Project and converting user passwords... * update_num_users_to_convert() [DELETED]: -- see above * check_lockfile() [NEW]: -- check if the lockfile exists. * create_lockfile() [NEW]: -- create lockfile on the filesystem that contains information regarding why it exists. * remove_lockfile() [NEW]: -- delete ("unlink()") the lockfile * get_full_verison_string()[NEW]: -- translates a version string into the FULL version to avoid logic problems and discrepancies (i.e. "1.0-ALPHA1" becomes "1.0.0-ALPHA1", while "1.0" becomes "1.0.0"... and so on). /README.txt [NEW]: * explains how the system works (or is supposed to work). * caveats say why using MySQL might suck. * work flow should help give better understanding. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Added Paths: ----------- trunk/0.1/README.txt Added: trunk/0.1/README.txt =================================================================== --- trunk/0.1/README.txt (rev 0) +++ trunk/0.1/README.txt 2009-07-15 19:01:11 UTC (rev 12) @@ -0,0 +1,50 @@ + +$Id$ + +This system is built to make upgrading a database-driven app seemless. No need +to coordinate SQL or schema changes with the code updates: previously, one would +have to take the entire website down, run the schema/SQL change, update the code, +and (if you're lucky) check a "test" website to ensure it works before unleashing +it upon your users.... if you're unlucky, they both must be run in unison, and +if the SQL or schema change fails, you're in for a lot of sweating and praying. + +Meet your saviour! This system adds the ability to allow your system to upgrade +itself. Whenever you increment the version in your VERSION file, it can run a +custom script that will do everything you need AND keep others out until it is +done. Once the system is updated, the next thing to touch the code containing +the upgrade system will cause it to run. + +CAVEATS: while this system will work with MySQL, I **STRONGLY** recommend +against it. It was built using PostgreSQL, which has a rock solid transaction +system: if the upgrade fails, everything rolls-back and it is up to a developer +to figure out what went wrong--but the system is left in a CONSISTENT STATE. +With MySQL, this will only work with InnoDB tables--and only if ALL AFFECTED +TABLES ARE InnoDB! On a database that doesn't use transaction-ready tables +(i.e. InnoDB tables), part of the upgrade could succeed, but another part +could fail, leaving the system in an inconsistent state... and this time, it +is up to you to fix those problems before removing the lock file that keeps +the site from working. + +WORK FLOW: + + --> Is there an existing LOCK file? + YES:: + --> HALT (tell the user there's an upgrade in progress). + NO::: + --> System checks VERSION file vs. version in database + --> Does version file's version match database version? + YES::: + -- good to go. + -- CONTINUE + NO::: + --> CREATE LOCK FILE + --> find named script in upgrade.xml file + --> include script, create new class, call method (in upgrade.xml file) + --> did upgrade succeed? + YES::: + --> remove LOCK file + --> CONTINUE + NO::: + --> stop upgrade process. + --> HALT + --> (continues as before) \ No newline at end of file Property changes on: trunk/0.1/README.txt ___________________________________________________________________ Added: svn:keywords + Id Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-14 21:32:27 UTC (rev 11) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-15 19:01:11 UTC (rev 12) @@ -14,18 +14,33 @@ class cs_webdbupgrade { + /** cs_fileSystem{} object: for filesystem read/write operations. */ private $fsObj; + + /** cs_globalFunctions{} object: debugging, array, and string operations. */ private $gfObj; + + /** Array of configuration parameters. */ private $config = NULL; + + /** Database object. */ protected $db; + + /** Object used to log activity. */ protected $logsObj; /** Name of the project as referenced in the database. */ protected $projectName; + /** Internal cache of the version string from the VERSION file. */ private $versionFileVersion = NULL; + + /** Stored database version. */ private $databaseVersion = NULL; + /** Name (absolute location) of *.lock file that indicates an upgrade is running. */ + private $lockfile; + /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ private $suffixList = array( @@ -68,17 +83,21 @@ if(!defined('LIBDIR')) { throw new exception(__METHOD__ .": required constant 'LIBDIR' not set"); } + if(!defined('SITE_ROOT')) { + throw new exception(__METHOD__ .": required constant 'SITE_ROOT' not set"); + } require_once(constant('LIBDIR') .'/cs-content/cs_globalFunctions.class.php'); require_once(constant('LIBDIR') .'/cs-content/cs_fileSystem.class.php'); require_once(constant('LIBDIR') .'/cs-content/cs_phpDB.class.php'); require_once(constant('LIBDIR') .'/cs-webdblogger/cs_webdblogger.class.php'); require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlParser.class.php'); + require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlCreator.class.php'); require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php'); $this->versionFileLocation = $versionFileLocation; - $this->fsObj = new cs_fileSystem(dirname($this->versionFileLocation)); + $this->fsObj = new cs_fileSystem(constant('SITE_ROOT')); $this->gfObj = new cs_globalFunctions; $this->gfObj->debugPrintOpt = DEBUGPRINTOPT; @@ -91,6 +110,10 @@ if(!strlen($versionFileLocation) || !file_exists($versionFileLocation)) { throw new exception(__METHOD__ .": unable to locate version file (". $versionFileLocation .")"); } + if(!isset($this->config['RWDIR']) || !is_dir($this->config['RWDIR']) || !is_readable($this->config['RWDIR']) || !is_writable($this->config['RWDIR'])) { + throw new exception(__METHOD__ .": missing RWDIR (". $this->config['RWDIR'] .") or isn't readable/writable"); + } + $this->lockfile = $this->config['RWDIR'] .'/upgrade.lock'; $this->db = new cs_phpDB(constant('DBTYPE')); try { @@ -101,6 +124,11 @@ throw new exception(__METHOD__ .": failed to connect to database or logger error: ". $e->getMessage()); } + if($this->check_lockfile()) { + //there is an existing lockfile... + throw new exception(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); + } + $this->check_versions(false); }//end __construct() //========================================================================= @@ -126,13 +154,6 @@ $this->logsObj->log_by_class("Upgrade in progress", 'notice'); throw new exception(__METHOD__ .": upgrade in progress"); } - elseif(!file_exists($this->config['CONFIG_FILE_LOCATION'])) { - throw new exception(__METHOD__ .": config file (". $this->config['CONFIG_FILE_LOCATION'] .") missing"); - } - elseif(!file_exists($this->versionFileLocation)) { - $this->logsObj->log_by_class("VERSION file missing", 'error'); - throw new exception(__METHOD__ .": VERSION file missing"); - } else { //okay, all files present: check the version in the VERSION file. $versionFileVersion = $this->read_version_file(); @@ -141,7 +162,7 @@ $versionsDiffer = TRUE; $retval = FALSE; - if($this->check_for_version_conflict() == 0) { + if($this->check_for_version_conflict() == false) { $versionsDiffer = false; $performUpgrade = false; } @@ -176,7 +197,7 @@ preg_match_all('/\nVERSION: (.*)\n/', $versionFileContents, $versionMatches); if(count($versionMatches) == 2 && count($versionMatches[1]) == 1) { $retval = trim($versionMatches[1][0]); - $this->versionFileVersion = $retval; + $this->versionFileVersion = $this->get_full_version_string($retval); //now retrieve the PROJECT name. $projectMatches = array(); @@ -203,13 +224,20 @@ * Read information from our config file, so we know what to expect. */ private function read_upgrade_config_file() { - $xmlString = $this->fsObj->read("upgrade/upgrade.xml"); + $xmlString = $this->fsObj->read($this->config['UPGRADE_CONFIG_FILE']); //parse the file. - $xmlParser = new xmlParser($xmlString); + $xmlParser = new cs_phpxmlParser($xmlString); $config = $xmlParser->get_tree(TRUE); - $this->config = $config['UPGRADE']; + + if(is_array($config['UPGRADE']) && count($config['UPGRADE'])) { + $this->config['UPGRADELIST'] = $config['UPGRADE']; + } + else { + throw new exception(__METHOD__ .": failed to retrieve 'UPGRADE' section; " . + "make sure upgrade.xml's ROOT element is 'UPGRADE'"); + } }//end read_upgrade_config_file() //========================================================================= @@ -234,11 +262,6 @@ else { $this->gfObj->debug_print(__METHOD__ .": result of setting 'upgrade in progress': (". $lockConfig .")"); - //check to see if our config file is writable. - if(!$this->fsObj->is_writable(CONFIG_FILE_LOCATION)) { - throw new exception(__METHOD__ .": config file isn't writable!"); - } - //push data into our internal "config" array. $this->read_upgrade_config_file(); $this->get_database_version(); @@ -272,8 +295,7 @@ else { throw new exception(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); } - $this->update_config_file('version_string', $this->newVersion); - $this->update_config_file('workingonit', "0"); + $this->remove_lockfile(); $this->db->commitTrans(); } @@ -288,8 +310,8 @@ $retval = FALSE; if($makeItSo === TRUE) { $this->get_database_version(); - $details = 'Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s'); - $this->update_config_file('WORKINGONIT', $details); + $details = $this->projectName .': Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s'); + $this->create_lockfile($details); $retval = TRUE; } elseif(preg_match('/^upgrade/i', $this->mainConfig['WORKINGONIT'])) { @@ -309,12 +331,13 @@ } $suffix = ""; + $explodeThis = $versionString; if(preg_match('/-[A-Z]{2,5}[0-9]{1,}/', $versionString)) { $bits = explode('-', $versionString); $suffix = $bits[1]; - $versionString = $bits[0]; + $explodeThis = $bits[0]; } - $tmp = explode('.', $versionString); + $tmp = explode('.', $explodeThis); if(is_numeric($tmp[0]) && is_numeric($tmp[1])) { @@ -329,6 +352,8 @@ else { $retval['version_maintenance'] = 0; } + + $retval['version_suffix'] = $suffix; } else { throw new exception(__METHOD__ .": invalid version string format, requires MAJOR.MINOR syntax (". $versionString .")"); @@ -359,7 +384,7 @@ if($versionFileData['version_string'] == $dbVersion['version_string']) { //good to go: no upgrade needed. - $retval = 0; + $retval = false; } else { //NOTE: this seems very convoluted, but it works. @@ -395,7 +420,8 @@ } } - if(!is_null($retval) && $retval !== 0) { + if($retval !== false) { + $this->logsObj->log_by_class('Upgrading '. $retval .', db version is ('. $dbVersion['version_string'] .'), versionFile is ('. $versionFileData['version_string'] .')', 'DEBUG'); $this->gfObj->debug_print(__METHOD__ .": upgrading ". $retval ." versions, from (". $this->databaseVersion .") to (". $this->versionFileVersion .")"); } @@ -450,18 +476,22 @@ //========================================================================= private function do_single_upgrade($targetVersion) { //Use the "matching_syntax" data in the upgrade.xml file to determine the filename. - $versionIndex = "V". $targetVersion; - $this->gfObj->debug_print(__METHOD__ .": versionIndex=(". $versionIndex ."), config MATCHING::: ". $this->gfObj->debug_print($this->config['MATCHING'],0)); - if(!isset($this->config['MATCHING'][$versionIndex])) { + $versionIndex = "V". $this->get_full_version_string($targetVersion); + $this->gfObj->debug_print(__METHOD__ .": versionIndex=(". $versionIndex ."), config MATCHING::: ". $this->gfObj->debug_print($this->config['UPGRADELIST']['MATCHING'],0)); + if(!isset($this->config['UPGRADELIST']['MATCHING'][$versionIndex])) { + $this->gfObj->debug_print(__METHOD__ .": doing version-only upgrade..."); + + $this->gfObj->debug_print($this->config['UPGRADELIST']['MATCHING']); + exit; //version-only upgrade. $this->update_database_version($this->versionFileVersion); $this->newVersion = $this->versionFileVersion; - $this->gfObj->debug_print(__METHOD__ .": doing version-only upgrade..."); } else { + $this->gfObj->debug_print(__METHOD__ .": doing scripted upgrade..."); $scriptIndex = $versionIndex; - $upgradeData = $this->config['MATCHING'][$versionIndex]; + $upgradeData = $this->config['UPGRADELIST']['MATCHING'][$versionIndex]; if(isset($upgradeData['TARGET_VERSION']) && count($upgradeData) > 1) { $this->newVersion = $upgradeData['TARGET_VERSION']; @@ -498,12 +528,19 @@ $queryArr[$index] = "SELECT internal_data_set_value('". $index ."', '". $value ."');"; } - $retval = NULL; - foreach($queryArr as $name=>$sql) { - if($this->run_sql($sql, 1)) { - $retval++; - } + $updateData = $versionArr; + $sql = "UPDATE ". $this->config['DB_TABLE'] ." SET ". + $this->gfObj->string_from_array($updateData, 'update', null, 'sql') ." WHERE " . + "project_name='". $this->gfObj->cleanString($this->projectName, 'sql') ."'"; + + + $updateRes = $this->db->run_update($sql,false); + if($updateRes == 1) { + $retval = $updateRes; } + else { + throw new exception(__METHOD__ .": invalid result (". $updateRes .") "); + } //okay, now check that the version string matches the updated bits. if(!$this->check_database_version($this->newVersion)) { @@ -522,43 +559,30 @@ * Checks consistency of version information in the database, and optionally * against a given version string. */ - private function check_database_version($checkThisVersion=NULL) { + private function check_database_version() { //retrieve the internal version information. - $sql = "select internal_data_get_value('version_string') as version_string, (" . - "internal_data_get_value('version_major') || '.' || " . - "internal_data_get_value('version_minor') || '.' || " . - "internal_data_get_value('version_maintenance')) as check_version, " . - "internal_data_get_value('version_suffix') AS version_suffix"; - - $retval = NULL; - if($this->run_sql($sql,1)) { - $data = $this->db->farray_fieldnames(); + if(!is_null($this->newVersion)) { + $data = $this->get_database_version(); $versionString = $data['version_string']; - $checkVersion = $data['check_version']; - if(strlen($data['version_suffix'])) { - //the version string already would have this, but the checked version wouldn't. - $checkVersion .= "-". $data['version_suffix']; - } - - if($versionString == $checkVersion) { + if($versionString == $this->newVersion) { $retval = TRUE; } else { $retval = FALSE; } + + if(!$retval) { + $this->gfObj->debug_print($data); + $this->gfObj->debug_print(__METHOD__ .": versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")"); + } + } else { - $retval = FALSE; + throw new exception(__METHOD__ .": no version string given (". $this->newVersion .")"); } - if(!$retval) { - $this->gfObj->debug_print($data); - $this->gfObj->debug_print(__METHOD__ .": versionString=(". $versionString ."), checkVersion=(". $checkVersion .")"); - } - return($retval); - }//end check_database_version() //========================================================================= @@ -571,9 +595,17 @@ $this->gfObj->debug_print(__METHOD__ .": script name=(". $myConfigFile .")"); //we've got the filename, see if it exists. - $fileName = UPGRADE_DIR .'/'. $myConfigFile; + if(isset($this->config['UPGRADE_SCRIPTS_DIR'])) { + $scriptsDir = $this->config['UPGRADE_SCRIPTS_DIR']; + } + else { + $this->logsObj->log_by_class("No UPGRADE_SCRIPTS_DIR config setting", 'warning'); + $scriptsDir = dirname($this->config['UPGRADE_CONFIG_FILE']); + } + $fileName = $scriptsDir .'/'. $myConfigFile; if(file_exists($fileName)) { - $this->gfObj->debug_print(__METHOD__ .": file exists... "); + + $this->logsObj->log_by_class("Performing scripted upgrade (". $myConfigFile .")", 'DEBUG'); $createClassName = $upgradeData['CLASS_NAME']; $classUpgradeMethod = $upgradeData['CALL_METHOD']; require_once($fileName); @@ -583,6 +615,14 @@ $upgradeObj = new $createClassName($this->db); if(method_exists($upgradeObj, $classUpgradeMethod)) { $upgradeResult = $upgradeObj->$classUpgradeMethod(); + + if($upgradeResult === true) { + //yay, it worked! + $this->logsObj->log_by_class("Upgrade succeeded (". $upgradeResult .")", 'success'); + } + else { + throw new exception(__METHOD__ .": upgrade failed (". $upgradeResult .")"); + } $this->gfObj->debug_print(__METHOD__ .": finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")"); } else { @@ -603,93 +643,6 @@ //========================================================================= - protected function run_sql($sql, $expectedNumrows=1) { - if(!$this->db->is_connected()) { - $this->db->connect(get_config_db_params()); - } - $numrows = $this->db->exec($sql); - $dberror = $this->db->errorMsg(); - - if(strlen($dberror)) { - $details = "DBERROR::: ". $dberror; - throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: ". $details); - } - elseif(!is_null($expectedNumrows) && $numrows != $expectedNumrows) { - throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: " . - "rows affected didn't match expectation (". $numrows ." != ". $expectedNumrows .")"); - } - elseif(is_null($expectedNumrows) && $numrows < 1) { - throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: " . - "invalid number of rows affected (". $numrows .")"); - } - else { - $retval = TRUE; - } - - return($retval); - }//end run_sql() - //========================================================================= - - - - //========================================================================= - private function update_config_file($index, $value) { - $gf = new cs_globalFunctions; - $myConfigFile = CONFIG_FILE_LOCATION; - $fs = new cs_fileSystemClass(dirname(__FILE__) .'/../'); - $xmlParser = new XMLParser($fs->read($myConfigFile)); - $xmlCreator = new XMLCreator; - $xmlCreator->load_xmlparser_data($xmlParser); - - //update the given index. - $xmlCreator->add_tag($index, $value, $xmlParser->get_attribute('/CONFIG/'. strtoupper($index))); - $this->mainConfig[strtoupper($index)] = $value; - - $xmlString = $xmlCreator->create_xml_string(); - - //truncate the file, to avoid problems with extra data at the end... - $fs->closeFile(); - $fs->create_file($myConfigFile,TRUE); - $fs->openFile($myConfigFile); - - //now write the new configuration. - $fs->write($xmlString, $myConfigFile); - }//end update_config_file() - //========================================================================= - - - - //========================================================================= - protected function get_num_users_to_convert() { - - $retval = 0; - try { - //if this generates an error, there are no users... - $this->run_sql("SELECT internal_data_get_value('users_to_convert')"); - $data = $this->db->farray(); - $retval = $data[0]; - } - catch(exception $e) { - $this->gfObj->debug_print(__METHOD__ .": failed to retrieve users to convert: "); - } - - return($retval); - - }//end get_num_users_to_convert() - //========================================================================= - - - - //========================================================================= - protected function update_num_users_to_convert() { - $retval = $this->run_sql("SELECT internal_data_set_value('users_to_convert', (select count(*) FROM user_table WHERE length(password) != 32))"); - return($retval); - }//end update_num_users_to_convert() - //========================================================================= - - - - //========================================================================= protected function is_higher_version($version, $checkIfHigher) { $retval = FALSE; if(!is_string($version) || !is_string($checkIfHigher)) { @@ -1005,6 +958,90 @@ //========================================================================= + + //========================================================================= + public function check_lockfile() { + $status = false; + if(file_exists($this->lockfile)) { + $status = true; + } + + return($status); + }//end check_lockfile() + //========================================================================= + + + + //========================================================================= + /** + * Create a *.lock file that indicates the system is in the process of + * performing an upgrade (safer than always updating the site's configuration + * file). + */ + public function create_lockfile($contents) { + if(!$this->check_lockfile()) { + if($this->fsObj->create_file($this->lockfile)) { + if(!preg_match('/\n$/', $contents)) { + $contents .= "\n"; + } + $writeRes = $this->fsObj->write($contents); + if(is_numeric($writeRes) && $writeRes > 0) { + $this->fsObj->closeFile(); + } + else { + throw new exception(__METHOD__ .": failed to write contents (". $contents .") to lockfile"); + } + } + else { + throw new exception(__METHOD__ .": failed to create lockfile (". $this->lockfile .")"); + } + } + else { + throw new exception(__METHOD__ .": failed to create lockfile, one already exists (". $this->lockfile .")"); + } + }//end create_lockfile() + //========================================================================= + + + + //========================================================================= + /** + * Destroy the *.lock file that indicates an upgrade is underway. + */ + private function remove_lockfile() { + if($this->check_lockfile()) { + if(!$this->fsObj->rm($this->lockfile)) { + throw new exception(__METHOD__ .": failed to remove lockfile (". $this->lockfile .")"); + } + } + else { + throw new exception(__METHOD__ .": no lockfile (". $this->lockfile .")"); + } + }//end remove_lockfile() + //========================================================================= + + + + //========================================================================= + private function get_full_version_string($versionString) { + if(strlen($versionString)) { + $bits = $this->parse_version_string($versionString); + + $fullVersion = $bits['version_major'] .'.'. $bits['version_minor'] .'.'. + $bits['version_maintenance']; + if(strlen($bits['version_suffix'])) { + $fullVersion .= '-'. $bits['version_suffix']; + } + } + else { + throw new exception(__METHOD__ .": no version string given"); + } + + return($fullVersion); + }//end get_full_version_string() + //========================================================================= + + }//end upgrade{} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-14 21:32:35
|
Revision: 11 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=11&view=rev Author: crazedsanity Date: 2009-07-14 21:32:27 +0000 (Tue, 14 Jul 2009) Log Message: ----------- Load the initial version string properly. NOTE::: the current system assumes cs_webdblogger is being setup & used; that may not always be the case... also, keep in mind that this will ALWAYS assume that if there is no existing version table, then the current version will be set in the database and no upgrades will be attempted. /cs_webdbupgrade.class.php: * check_versions(): -- read the version file BEFORE checking database version, so the initial version can be loaded properly. * read_version_file(): -- use preg_match_all() to simplify matching and to remove the requirement that version string be on line 2 (now it can be almost anywhere). -- set internal projectName similar to setting versionFileVersion. * parse_version_string(): -- rip off the suffix immediately (if it exists) -- handle non-existent version_maintenance index -- always add version_suffix * fix_xml_config(): -- remove commented-out debugging code. * load_table(): -- set the initial version information and log that fact. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-14 20:37:21 UTC (rev 10) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-14 21:32:27 UTC (rev 11) @@ -135,8 +135,8 @@ } else { //okay, all files present: check the version in the VERSION file. + $versionFileVersion = $this->read_version_file(); $dbVersion = $this->get_database_version(); - $versionFileVersion = $this->read_version_file(); $versionsDiffer = TRUE; $retval = FALSE; @@ -169,15 +169,24 @@ $retval = NULL; //okay, all files present: check the version in the VERSION file. - $versionFileContents = $this->fsObj->read('VERSION'); + $versionFileContents = $this->fsObj->read($this->versionFileLocation); - //okay, rip it into bits. NOTE: this *depends* on "VERSION: " being on the third line. - $lines = explode("\n", $versionFileContents); - $versionLine = $lines[2]; - if(preg_match('/^VERSION: /', $versionLine)) { + + $versionMatches = array(); + preg_match_all('/\nVERSION: (.*)\n/', $versionFileContents, $versionMatches); + if(count($versionMatches) == 2 && count($versionMatches[1]) == 1) { + $retval = trim($versionMatches[1][0]); + $this->versionFileVersion = $retval; - $retval = trim(preg_replace('/VERSION: /', '', $versionLine)); - $this->versionFileVersion = $retval; + //now retrieve the PROJECT name. + $projectMatches = array(); + preg_match_all('/\nPROJECT: (.*)\n/', $versionFileContents, $projectMatches); + if(count($projectMatches) == 2 && count($projectMatches[1]) == 1) { + $this->projectName = trim($projectMatches[1][0]); + } + else { + throw new exception(__METHOD__ .": failed to find PROJECT name"); + } } else { throw new exception(__METHOD__ .": could not find VERSION data"); @@ -298,51 +307,31 @@ if(is_null($versionString) || !strlen($versionString)) { throw new exception(__METHOD__ .": invalid version string ($versionString)"); } - $tmp = explode('.', $versionString); - //NOTE: the order of the array MUST be major, then minor, then maintenance, so is_higher_version() can check it easily. - $retval = array( - 'version_string' => $versionString, - 'version_major' => $tmp[0], - 'version_minor' => $tmp[1] - ); - if(count($tmp) == 3) { - $retval['version_maintenance'] = $tmp[2]; + $suffix = ""; + if(preg_match('/-[A-Z]{2,5}[0-9]{1,}/', $versionString)) { + $bits = explode('-', $versionString); + $suffix = $bits[1]; + $versionString = $bits[0]; } - else { - $retval['version_maintenance'] = "0"; - } + $tmp = explode('.', $versionString); - //check for a prefix or a suffix. - if(preg_match('/-/', $versionString)) { - //make sure there's only ONE dash. - $tmp = explode('-', $versionString); - if(count($tmp) == 2) { - if(preg_match('/-/', $retval['version_major'])) { - //example: BETA-3.3.0 - - throw new exception(__METHOD__ .": versions that contain prefixes cannot be upgraded"); - - #$tmp = explode('-', $retval['version_major']); - #$retval['version_major'] = $tmp[1]; - #$retval['prefix'] = $tmp[0]; - } - elseif(preg_match('/-/', $retval['version_maintenance'])) { - //example: 1.0.0-ALPHA1 - $tmp = explode('-', $retval['version_maintenance']); - $retval['version_maintenance'] = $tmp[0]; - $retval['version_suffix'] = $tmp[1]; - } - else { - throw new exception(__METHOD__ .": invalid location of prefix/suffix in (". $versionString .")"); - } + + if(is_numeric($tmp[0]) && is_numeric($tmp[1])) { + $retval = array( + 'version_string' => $versionString, + 'version_major' => $tmp[0], + 'version_minor' => $tmp[1], + ); + if(isset($tmp[2])) { + $retval['version_maintenance'] = $tmp[2]; } else { - throw new exception(__METHOD__ .": too many dashes in version string (". $versionString .")"); + $retval['version_maintenance'] = 0; } } else { - $retval['version_suffix'] = ""; + throw new exception(__METHOD__ .": invalid version string format, requires MAJOR.MINOR syntax (". $versionString .")"); } return($retval); @@ -956,9 +945,6 @@ $oldData = $myA2p->get_data(); $myA2p->set_data($path, $val); $this->tempXmlConfig = $myA2p->get_data(); - #$this->gfObj->debug_print(__METHOD__ .": set data, path=(". $path ."), val=(". $val ."), current data::: " . - # $this->gfObj->debug_print($myA2p->get_data(),0) .", OLD DATA::: " . - # $this->gfObj->debug_print($oldData,0)); } else { throw new exception(__METHOD__ .": invalid type (". $myData['type'] .")"); @@ -992,6 +978,20 @@ $loadTableResult = true; $logRes = 'Successfully loaded '; $logType = 'initialize'; + + //now set the initial version information... + if(strlen($this->projectName) && strlen($this->versionFileVersion)) { + $insertData = $this->parse_version_string($this->versionFileVersion); + $insertData['project_name'] = $this->projectName; + + $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); + if($this->db->run_insert($sql)) { + $this->logsObj->log_by_class('Created initial version info ('. $insertData['version_string'] .')', $logType); + } + else { + $this->logsObj->log_by_class('Failed to create version info ('. $insertData['version_string'] .')', 'error'); + } + } } else { $logRes = 'Failed to load '; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-14 20:37:24
|
Revision: 10 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=10&view=rev Author: crazedsanity Date: 2009-07-14 20:37:21 +0000 (Tue, 14 Jul 2009) Log Message: ----------- Update use appropriate classes, attempt to auto-load table into DB. NOTE::: work is still in progress, as this version pukes if it tries to create the table in the database... the table is created, but the version isn't loaded, so get_database_version() fails. /cs_webdbupgrade.class.php: * MAIN::: -- new protected var $projectName -- deleted $configVersion -- deleted $mainConfig * __CONSTRUCT(): -- ARG CHANGE: NEW ARG: #1 ($versionFileLocation) -- ARG CHANGE: NEW ARG: #2 (array $config) -- extra parsing of $config if it looks like XML from cs-phpxmlParser that isn't the "simple" format (contains 'type', 'value', etc). -- check for LIBDIR, then require_once() on lots of stuff -- set internal versionFileLocation -- set fsObj to root in the directory of the config file... -- require constant 'DBTYPE'... -- CONFIG_FILE_LOCATION now should be in passed $config array -- create cs_phpDB with appropriate db type. -- use cs_webdblogger for the logsObj. -- call check_versions(false) to ensure some vars are set... * check_versions(): -- set $performUpgrade if the passed value isn't boolean. -- log all errors before throwing an exception -- use CONFIG_FILE_LOCATION from the internal config array. -- simplify logic, remove stuff referring to a version existing in the config file (that is a CS-Project thing). * read_config_version() [DELETED]: -- this system doesn't deal with a version being in the main config file; if there is one and it needs to be maintained, then something needs to extend this class to add that functionality. * check_for_version_conflict(): -- don't call deleted method, remove misleading comment -- remove logic regarding version in config file * get_database_version(): -- change query to not use stored procedures (the stored procedures are actually completely unnecessary and just add unneeded complexity). -- if the database error says something like "doesn't exist", the system will attempt to load the required database from a schema file. * fix_xml_config() [NEW]: -- method to alter the given configuration so it is in the format expected by the code. -- NOTE::: this needs to throw an exception when one is caught by cs_arrayToPath{}. * load_table() [NEW]: -- load the table containing version information into the database. -- NOTE::: this method is public so a custom upgrade script can run be written for the transition from the old way to using this system. /schema/schema.sql [NEW]: * generic schema file for loading the expected table into the database (tested on PostgreSQL v8.2 and MySQL v5.0.22, YMMV) Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Added Paths: ----------- trunk/0.1/schema/ trunk/0.1/schema/schema.sql Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-06-30 18:22:58 UTC (rev 9) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-14 20:37:21 UTC (rev 10) @@ -20,12 +20,12 @@ protected $db; protected $logsObj; + /** Name of the project as referenced in the database. */ + protected $projectName; + private $versionFileVersion = NULL; - private $configVersion = NULL; private $databaseVersion = NULL; - private $mainConfig = NULL; - /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ private $suffixList = array( @@ -35,20 +35,73 @@ ); //========================================================================= - public function __construct() { - $this->fsObj = new cs_fileSystemClass(dirname(__FILE__) .'/../'); + public function __construct($versionFileLocation, array $config) { + + //Handle the config array (cope with XML-ish array) + if(is_array($config)) { + //check if it is in the complex XML array style... + $keys = array_keys($config); + if(isset($config[$keys[0]]['type'])) { + $this->fix_xml_config($config); + $this->config = $this->tempXmlConfig; + } + else { + $this->config = $config; + } + } + else { + throw new exception(__METHOD__ .": no configuration available"); + } + + //cope with problems in CS-Content v1.0-ALPHA9 (or before)--see http://project.crazedsanity.com/extern/helpdesk/view?ID=281 + if(isset($this->config['DBPARMLINKER'])) { + $this->config['DBPARAMS'] = array(); + foreach($this->config['DBPARMLINKER'] as $i=>$loc) { + $this->config['DBPARAMS'][strtolower($i)] = $this->config[$loc]; + unset($this->config[$loc]); + } + unset($this->config['DBPARMLINKER']); + } + + //Check for some required constants. + $requisiteConstants = array('LIBDIR'); + if(!defined('LIBDIR')) { + throw new exception(__METHOD__ .": required constant 'LIBDIR' not set"); + } + + require_once(constant('LIBDIR') .'/cs-content/cs_globalFunctions.class.php'); + require_once(constant('LIBDIR') .'/cs-content/cs_fileSystem.class.php'); + require_once(constant('LIBDIR') .'/cs-content/cs_phpDB.class.php'); + require_once(constant('LIBDIR') .'/cs-webdblogger/cs_webdblogger.class.php'); + require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlParser.class.php'); + require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php'); + + $this->versionFileLocation = $versionFileLocation; + + $this->fsObj = new cs_fileSystem(dirname($this->versionFileLocation)); $this->gfObj = new cs_globalFunctions; $this->gfObj->debugPrintOpt = DEBUGPRINTOPT; - clearstatcache(); - $this->db = new cs_phpDB; - $this->db->connect(get_config_db_params()); + if(!defined('DBTYPE')) { + throw new exception(__METHOD__ .": required constant 'DBTYPE' not set"); + } + if(!isset($this->config['CONFIG_FILE_LOCATION'])) { + throw new exception(__METHOD__ .": required setting 'CONFIG_FILE_LOCATION' not found"); + } + if(!strlen($versionFileLocation) || !file_exists($versionFileLocation)) { + throw new exception(__METHOD__ .": unable to locate version file (". $versionFileLocation .")"); + } - $this->logsObj = new logsClass($this->db, "Upgrade"); + $this->db = new cs_phpDB(constant('DBTYPE')); + try { + $this->db->connect($this->config['DBPARAMS']); + $this->logsObj = new cs_webdblogger($this->db, "Upgrade"); + } + catch(exception $e) { + throw new exception(__METHOD__ .": failed to connect to database or logger error: ". $e->getMessage()); + } - //define some things for upgrades. - define("UPGRADE_LOCKFILE", dirname(__FILE__) ."/../UPGRADING_VERSION"); //relative to the directory beneath lib. - define("UPGRADE_DIR", dirname(__FILE__) ."/../upgrade"); + $this->check_versions(false); }//end __construct() //========================================================================= @@ -61,43 +114,40 @@ * listed in the database. */ public function check_versions($performUpgrade=TRUE) { + if(!is_bool($performUpgrade) || is_null($performUpgrade)) { + $performUpgrade = true; + } + //first, check that all files exist. $retval = NULL; //check to see if the lock files for upgrading exist. if($this->upgrade_in_progress()) { + $this->logsObj->log_by_class("Upgrade in progress", 'notice'); throw new exception(__METHOD__ .": upgrade in progress"); } - elseif(!file_exists(CONFIG_FILE_LOCATION)) { - throw new exception(__METHOD__ .": config.xml file missing"); + elseif(!file_exists($this->config['CONFIG_FILE_LOCATION'])) { + throw new exception(__METHOD__ .": config file (". $this->config['CONFIG_FILE_LOCATION'] .") missing"); } - elseif(!file_exists(dirname(__FILE__) .'/../VERSION')) { + elseif(!file_exists($this->versionFileLocation)) { + $this->logsObj->log_by_class("VERSION file missing", 'error'); throw new exception(__METHOD__ .": VERSION file missing"); } - elseif(!file_exists(dirname(__FILE__) .'/../upgrade/upgrade.xml')) { - throw new exception(__METHOD__ .": upgrade.xml file missing"); - } else { //okay, all files present: check the version in the VERSION file. - $versionFileContents = $this->read_version_file(); + $dbVersion = $this->get_database_version(); + $versionFileVersion = $this->read_version_file(); - //now read data from the config. - $versionFromConfig = $this->read_config_version(); - $versionsDiffer = TRUE; $retval = FALSE; - if($versionFileContents == $versionFromConfig) { - $versionConflict = $this->check_for_version_conflict(); - if($versionConflict === 0) { - //all is good: no problems detected (all things match-up). - $versionsDiffer=FALSE; - $performUpgrade = FALSE; - } - else { - // - $versionsDiffer = TRUE; - } + + if($this->check_for_version_conflict() == 0) { + $versionsDiffer = false; + $performUpgrade = false; } + else { + $versionsDiffer = true; + } if($versionsDiffer == TRUE && $performUpgrade === TRUE) { //reset the return value, so it'll default to failure until we say otherwise. @@ -140,33 +190,6 @@ //========================================================================= - private function read_config_version() { - $configObj = new config(); - $config = $configObj->read_config_file(FALSE); - $this->mainConfig = $config; - $retval = NULL; - - if(!is_array($config) || !count($config)) { - throw new exception(__METHOD__ .": no configuration data available (missing config file?)"); - } - else { - //now, let's see if there's a "version_string" index. - if(isset($config['VERSION_STRING']) && strlen($config['VERSION_STRING'])) { - $retval = $config['VERSION_STRING']; - } - else { - throw new exception(__METHOD__ .": invalid version string found (". $config['VERSION_STRING'] .")"); - } - } - - $this->configVersion = $retval; - return($retval); - }//end read_config_version() - //========================================================================= - - - - //========================================================================= /** * Read information from our config file, so we know what to expect. */ @@ -339,19 +362,9 @@ //set a default return... $retval = NULL; - //call to ensure files have been processed. - #$this->check_versions(FALSE); - $this->read_config_version(); $this->read_version_file(); - $configVersion = NULL; //parse the version strings. - if(strlen($this->configVersion)) { - $configVersion = $this->parse_version_string($this->configVersion); - } - $versionFile = $this->parse_version_string($this->versionFileVersion); - - $dbVersion = $this->get_database_version(); $versionFileData = $this->parse_version_string($this->versionFileVersion); @@ -405,25 +418,33 @@ //========================================================================= private function get_database_version() { + $this->gfObj->debugPrintOpt=1; //create a database object & attempt to read the database version. - if(!is_object($this->db) || get_class($this->db) != 'cs_phpDB') { - $this->db = new cs_phpDB; - $this->db->connect(get_config_db_params()); - } + $sql = "SELECT * FROM ". $this->config['DB_TABLE'] ." WHERE project_name='" . + $this->gfObj->cleanString($this->projectName, 'sql') ."'"; - $sql = "SELECT " . - "internal_data_get_value('version_string') AS version_string, " . - "internal_data_get_value('version_major') AS version_major, " . - "internal_data_get_value('version_minor') AS version_minor, " . - "internal_data_get_value('version_maintenance') AS version_maintenance, " . - "internal_data_get_value('version_suffix') AS version_suffix"; $numrows = $this->db->exec($sql); $dberror = $this->db->errorMsg(); if(strlen($dberror) || $numrows != 1) { - //fail. - throw new exception(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror); + // + if(preg_match('/doesn\'t exist/', $dberror)) { + //add the table... + $loadTableResult = $this->load_table(); + if($loadTableResult === TRUE) { + //now try the SQL... + $numrows = $this->db->exec($sql); + $dberror = $this->db->errorMsg(); + } + else { + throw new exception(__METHOD__ .": no table in database, failed to create one... ORIGINAL " . + "ERROR: ". $dberror .", SCHEMA LOAD ERROR::: ". $loadTableResult); + } + } + else { + throw new exception(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror); + } } else { $data = $this->db->farray_fieldnames(); @@ -896,6 +917,94 @@ //========================================================================= + + //========================================================================= + private function fix_xml_config($config, $path=null) { + #$this->gfObj->debug_print(__METHOD__ .": path=(". $path ."):: ". $this->gfObj->debug_print($config,0)); + $this->xmlLoops++; + if($this->xmlLoops > 1000) { + throw new exception(__METHOD__ .": infinite loop detected..."); + } + + try { + $a2p = new cs_arrayToPath($config); + } + catch(exception $e) { + $this->gfObj->debug_print($config); + exit("died on #1"); + } + if(!is_array($this->tempXmlConfig)) { + $this->tempXmlConfig = array(); + } + try { + $myA2p = new cs_arrayToPath(&$this->tempXmlConfig); + } + catch(exception $e) { + + exit("died on #2"); + } + + $myData = $a2p->get_data($path); + + if(is_array($myData)) { + if(isset($myData['type']) && $myData['type'] != 'open') { + if($myData['type'] == 'complete') { + $val = null; + if(isset($myData['value'])) { + $val = $myData['value']; + } + $oldData = $myA2p->get_data(); + $myA2p->set_data($path, $val); + $this->tempXmlConfig = $myA2p->get_data(); + #$this->gfObj->debug_print(__METHOD__ .": set data, path=(". $path ."), val=(". $val ."), current data::: " . + # $this->gfObj->debug_print($myA2p->get_data(),0) .", OLD DATA::: " . + # $this->gfObj->debug_print($oldData,0)); + } + else { + throw new exception(__METHOD__ .": invalid type (". $myData['type'] .")"); + } + } + else { + foreach($myData as $i=>$d) { + if(!in_array($i, array('type', 'attributes', 'value'))) { + $this->fix_xml_config($config, $path .'/'. $i); + } + } + } + } + else { + throw new exception(__METHOD__ .": unable to fix data on path=(". $path .")::: ". $this->gfObj->debug_print($myData,0)); + } + }//end fix_xml_config() + //========================================================================= + + + + //========================================================================= + public function load_table() { + $schemaFileLocation = dirname(__FILE__) .'/schema/schema.sql'; + $schema = file_get_contents($schemaFileLocation); + $schema = str_replace('{tableName}', $this->config['DB_TABLE'], $schema); + $this->db->exec($schema); + + $loadTableResult = $this->db->errorMsg(); + if(!strlen($loadTableResult)) { + $loadTableResult = true; + $logRes = 'Successfully loaded '; + $logType = 'initialize'; + } + else { + $logRes = 'Failed to load '; + $logType = 'error'; + } + $this->logsObj->log_by_class($logRes .' table ('. $this->config['DB_TABLE'] .') into ' . + 'database::: '. $loadTableResult, $logType); + + return($loadTableResult); + }//end load_table() + //========================================================================= + + }//end upgrade{} Added: trunk/0.1/schema/schema.sql =================================================================== --- trunk/0.1/schema/schema.sql (rev 0) +++ trunk/0.1/schema/schema.sql 2009-07-14 20:37:21 UTC (rev 10) @@ -0,0 +1,23 @@ +-- +-- SVN INFORMATION::: +-- --------------- +-- SVN Signature::::::: $Id$ +-- Last Author::::::::: $Author$ +-- Current Revision:::: $Revision$ +-- Repository Location: $HeadURL$ +-- Last Updated:::::::: $Date$ +-- +-- This table create statement MUST work in PostgreSQL v8.2.x+ AND MySQL v5.0.x+: +-- otherwise separate schema files have to be created and the code will have to +-- do extra checking... +-- +-- The "{tableName}" portion will be replaced with the value of the configured +-- "DB_TABLE" setting. +CREATE TABLE {tableName} ( + project_name varchar(30) NOT NULL PRIMARY KEY, + version_string varchar(50) NOT NULL, + version_major integer NOT NULL, + version_minor integer NOT NULL, + version_maintenance integer NOT NULL, + version_suffix varchar(20) NOT NULL +); \ No newline at end of file Property changes on: trunk/0.1/schema/schema.sql ___________________________________________________________________ Added: svn:keywords + Id Author Revision HeadURL Date This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-06-30 18:23:05
|
Revision: 9 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=9&view=rev Author: crazedsanity Date: 2009-06-30 18:22:58 +0000 (Tue, 30 Jun 2009) Log Message: ----------- Rename class to meet current CS coding standards. Added Paths: ----------- trunk/0.1/cs_webdbupgrade.class.php Removed Paths: ------------- trunk/0.1/upgradeClass.php Copied: trunk/0.1/cs_webdbupgrade.class.php (from rev 8, trunk/0.1/upgradeClass.php) =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php (rev 0) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-06-30 18:22:58 UTC (rev 9) @@ -0,0 +1,902 @@ +<?php +/* + * Created on Jul 2, 2007 + * + * SVN INFORMATION::: + * ------------------ + * SVN Signature::::::: $Id$ + * Last Author::::::::: $Author$ + * Current Revision:::: $Revision$ + * Repository Location: $HeadURL$ + * Last Updated:::::::: $Date$ + * + */ + +class cs_webdbupgrade { + + private $fsObj; + private $gfObj; + private $config = NULL; + protected $db; + protected $logsObj; + + private $versionFileVersion = NULL; + private $configVersion = NULL; + private $databaseVersion = NULL; + + private $mainConfig = NULL; + + /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in + * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ + private $suffixList = array( + 'ALPHA', //very unstable + 'BETA', //kinda unstable, but probably useable + 'RC' //all known bugs fixed, searching for unknown ones + ); + + //========================================================================= + public function __construct() { + $this->fsObj = new cs_fileSystemClass(dirname(__FILE__) .'/../'); + $this->gfObj = new cs_globalFunctions; + $this->gfObj->debugPrintOpt = DEBUGPRINTOPT; + clearstatcache(); + + $this->db = new cs_phpDB; + $this->db->connect(get_config_db_params()); + + $this->logsObj = new logsClass($this->db, "Upgrade"); + + //define some things for upgrades. + define("UPGRADE_LOCKFILE", dirname(__FILE__) ."/../UPGRADING_VERSION"); //relative to the directory beneath lib. + define("UPGRADE_DIR", dirname(__FILE__) ."/../upgrade"); + }//end __construct() + //========================================================================= + + + + //========================================================================= + /** + * Where everything begins: checks if the version held in config.xml lines-up + * with the one in the VERSION file; if it does, then it checks the version + * listed in the database. + */ + public function check_versions($performUpgrade=TRUE) { + //first, check that all files exist. + $retval = NULL; + + //check to see if the lock files for upgrading exist. + if($this->upgrade_in_progress()) { + throw new exception(__METHOD__ .": upgrade in progress"); + } + elseif(!file_exists(CONFIG_FILE_LOCATION)) { + throw new exception(__METHOD__ .": config.xml file missing"); + } + elseif(!file_exists(dirname(__FILE__) .'/../VERSION')) { + throw new exception(__METHOD__ .": VERSION file missing"); + } + elseif(!file_exists(dirname(__FILE__) .'/../upgrade/upgrade.xml')) { + throw new exception(__METHOD__ .": upgrade.xml file missing"); + } + else { + //okay, all files present: check the version in the VERSION file. + $versionFileContents = $this->read_version_file(); + + //now read data from the config. + $versionFromConfig = $this->read_config_version(); + + $versionsDiffer = TRUE; + $retval = FALSE; + if($versionFileContents == $versionFromConfig) { + $versionConflict = $this->check_for_version_conflict(); + if($versionConflict === 0) { + //all is good: no problems detected (all things match-up). + $versionsDiffer=FALSE; + $performUpgrade = FALSE; + } + else { + // + $versionsDiffer = TRUE; + } + } + + if($versionsDiffer == TRUE && $performUpgrade === TRUE) { + //reset the return value, so it'll default to failure until we say otherwise. + $retval = NULL; + + //Perform the upgrade! + $this->perform_upgrade(); + } + } + + return($retval); + }//end check_versions() + //========================================================================= + + + + //========================================================================= + protected function read_version_file() { + $retval = NULL; + + //okay, all files present: check the version in the VERSION file. + $versionFileContents = $this->fsObj->read('VERSION'); + + //okay, rip it into bits. NOTE: this *depends* on "VERSION: " being on the third line. + $lines = explode("\n", $versionFileContents); + $versionLine = $lines[2]; + if(preg_match('/^VERSION: /', $versionLine)) { + + $retval = trim(preg_replace('/VERSION: /', '', $versionLine)); + $this->versionFileVersion = $retval; + } + else { + throw new exception(__METHOD__ .": could not find VERSION data"); + } + + return($retval); + }//end read_version_file() + //========================================================================= + + + + //========================================================================= + private function read_config_version() { + $configObj = new config(); + $config = $configObj->read_config_file(FALSE); + $this->mainConfig = $config; + $retval = NULL; + + if(!is_array($config) || !count($config)) { + throw new exception(__METHOD__ .": no configuration data available (missing config file?)"); + } + else { + //now, let's see if there's a "version_string" index. + if(isset($config['VERSION_STRING']) && strlen($config['VERSION_STRING'])) { + $retval = $config['VERSION_STRING']; + } + else { + throw new exception(__METHOD__ .": invalid version string found (". $config['VERSION_STRING'] .")"); + } + } + + $this->configVersion = $retval; + return($retval); + }//end read_config_version() + //========================================================================= + + + + //========================================================================= + /** + * Read information from our config file, so we know what to expect. + */ + private function read_upgrade_config_file() { + $xmlString = $this->fsObj->read("upgrade/upgrade.xml"); + + //parse the file. + $xmlParser = new xmlParser($xmlString); + + $config = $xmlParser->get_tree(TRUE); + $this->config = $config['UPGRADE']; + }//end read_upgrade_config_file() + //========================================================================= + + + + //========================================================================= + private function perform_upgrade() { + //make sure there's not already a lockfile. + if($this->upgrade_in_progress()) { + //ew. Can't upgrade. + throw new exception(__METHOD__ .": upgrade already in progress...????"); + } + else { + $lockConfig = $this->upgrade_in_progress(TRUE); + $this->fsObj->cd("/"); + + //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists(). + if($lockConfig === 0) { + //can't create the lockfile. Die. + throw new exception(__METHOD__ .": failed to set 'upgrade in progress'"); + } + else { + $this->gfObj->debug_print(__METHOD__ .": result of setting 'upgrade in progress': (". $lockConfig .")"); + + //check to see if our config file is writable. + if(!$this->fsObj->is_writable(CONFIG_FILE_LOCATION)) { + throw new exception(__METHOD__ .": config file isn't writable!"); + } + + //push data into our internal "config" array. + $this->read_upgrade_config_file(); + $this->get_database_version(); + + //check for version conflicts. + $this->check_for_version_conflict(); + + $upgradeList = $this->get_upgrade_list(); + + $i=0; + $this->gfObj->debug_print(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion .")..."); + $this->db->beginTrans(__METHOD__); + foreach($upgradeList as $fromVersion=>$toVersion) { + + $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; + $this->gfObj->debug_print($details); + $this->logsObj->log_by_class($details, 'system'); + $this->do_single_upgrade($fromVersion); + $this->get_database_version(); + $i++; + + $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; + $this->gfObj->debug_print($details); + $this->logsObj->log_by_class($details, 'system'); + } + + if($this->databaseVersion == $this->versionFileVersion) { + $this->gfObj->debug_print(__METHOD__ .": finished upgrading after performing (". $i .") upgrades!!!"); + $this->newVersion = $this->databaseVersion; + } + else { + throw new exception(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); + } + $this->update_config_file('version_string', $this->newVersion); + $this->update_config_file('workingonit', "0"); + + $this->db->commitTrans(); + } + } + }//end perform_upgrade() + //========================================================================= + + + + //========================================================================= + public function upgrade_in_progress($makeItSo=FALSE) { + $retval = FALSE; + if($makeItSo === TRUE) { + $this->get_database_version(); + $details = 'Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s'); + $this->update_config_file('WORKINGONIT', $details); + $retval = TRUE; + } + elseif(preg_match('/^upgrade/i', $this->mainConfig['WORKINGONIT'])) { + $retval = TRUE; + } + + return($retval); + }//end upgrade_in_progress() + //========================================================================= + + + + //========================================================================= + public function parse_version_string($versionString) { + if(is_null($versionString) || !strlen($versionString)) { + throw new exception(__METHOD__ .": invalid version string ($versionString)"); + } + $tmp = explode('.', $versionString); + + //NOTE: the order of the array MUST be major, then minor, then maintenance, so is_higher_version() can check it easily. + $retval = array( + 'version_string' => $versionString, + 'version_major' => $tmp[0], + 'version_minor' => $tmp[1] + ); + if(count($tmp) == 3) { + $retval['version_maintenance'] = $tmp[2]; + } + else { + $retval['version_maintenance'] = "0"; + } + + //check for a prefix or a suffix. + if(preg_match('/-/', $versionString)) { + //make sure there's only ONE dash. + $tmp = explode('-', $versionString); + if(count($tmp) == 2) { + if(preg_match('/-/', $retval['version_major'])) { + //example: BETA-3.3.0 + + throw new exception(__METHOD__ .": versions that contain prefixes cannot be upgraded"); + + #$tmp = explode('-', $retval['version_major']); + #$retval['version_major'] = $tmp[1]; + #$retval['prefix'] = $tmp[0]; + } + elseif(preg_match('/-/', $retval['version_maintenance'])) { + //example: 1.0.0-ALPHA1 + $tmp = explode('-', $retval['version_maintenance']); + $retval['version_maintenance'] = $tmp[0]; + $retval['version_suffix'] = $tmp[1]; + } + else { + throw new exception(__METHOD__ .": invalid location of prefix/suffix in (". $versionString .")"); + } + } + else { + throw new exception(__METHOD__ .": too many dashes in version string (". $versionString .")"); + } + } + else { + $retval['version_suffix'] = ""; + } + + return($retval); + }//end parse_version_string() + //========================================================================= + + + + //========================================================================= + /** + * Checks for issues with versions. + * 0 == No problems. + * (string) == upgrade applicable (indicates "major"/"minor"/"maintenance"). + * NULL == encountered error + */ + private function check_for_version_conflict() { + //set a default return... + $retval = NULL; + + //call to ensure files have been processed. + #$this->check_versions(FALSE); + $this->read_config_version(); + $this->read_version_file(); + $configVersion = NULL; + + //parse the version strings. + if(strlen($this->configVersion)) { + $configVersion = $this->parse_version_string($this->configVersion); + } + $versionFile = $this->parse_version_string($this->versionFileVersion); + + + $dbVersion = $this->get_database_version(); + $versionFileData = $this->parse_version_string($this->versionFileVersion); + + if($versionFileData['version_string'] == $dbVersion['version_string']) { + //good to go: no upgrade needed. + $retval = 0; + } + else { + //NOTE: this seems very convoluted, but it works. + if($versionFileData['version_major'] == $dbVersion['version_major']) { + if($versionFileData['version_minor'] == $dbVersion['version_minor']) { + if($versionFileData['version_maintenance'] == $dbVersion['version_maintenance']) { + if($versionFileData['version_suffix'] == $dbVersion['version_suffix']) { + throw new exception(__METHOD__ .": no version upgrade detected, but version strings don't match (versionFile=". $versionFileData['version_string'] .", dbVersion=". $dbVersion['version_string'] .")"); + } + else { + $retval = "suffix"; + } + } + elseif($versionFileData['version_maintenance'] > $dbVersion['version_maintenance']) { + $retval = "maintenance"; + } + else { + throw new exception(__METHOD__ .": downgrading from maintenance versions is unsupported"); + } + } + elseif($versionFileData['version_minor'] > $dbVersion['version_minor']) { + $retval = "minor"; + } + else { + throw new exception(__METHOD__ .": downgrading minor versions is unsupported"); + } + } + elseif($versionFileData['version_major'] > $dbVersion['version_major']) { + $retval = "major"; + } + else { + throw new exception(__METHOD__ .": downgrading major versions is unsupported"); + } + } + + if(!is_null($retval) && $retval !== 0) { + $this->gfObj->debug_print(__METHOD__ .": upgrading ". $retval ." versions, from (". $this->databaseVersion .") to (". $this->versionFileVersion .")"); + } + + return($retval); + }//end check_for_version_conflict() + //========================================================================= + + + + //========================================================================= + private function get_database_version() { + //create a database object & attempt to read the database version. + + if(!is_object($this->db) || get_class($this->db) != 'cs_phpDB') { + $this->db = new cs_phpDB; + $this->db->connect(get_config_db_params()); + } + + $sql = "SELECT " . + "internal_data_get_value('version_string') AS version_string, " . + "internal_data_get_value('version_major') AS version_major, " . + "internal_data_get_value('version_minor') AS version_minor, " . + "internal_data_get_value('version_maintenance') AS version_maintenance, " . + "internal_data_get_value('version_suffix') AS version_suffix"; + $numrows = $this->db->exec($sql); + $dberror = $this->db->errorMsg(); + + if(strlen($dberror) || $numrows != 1) { + //fail. + throw new exception(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror); + } + else { + $data = $this->db->farray_fieldnames(); + $this->databaseVersion = $data['version_string']; + $retval = $this->parse_version_string($data['version_string']); + } + + return($retval); + }//end get_database_version() + //========================================================================= + + + + //========================================================================= + private function do_single_upgrade($targetVersion) { + //Use the "matching_syntax" data in the upgrade.xml file to determine the filename. + $versionIndex = "V". $targetVersion; + $this->gfObj->debug_print(__METHOD__ .": versionIndex=(". $versionIndex ."), config MATCHING::: ". $this->gfObj->debug_print($this->config['MATCHING'],0)); + if(!isset($this->config['MATCHING'][$versionIndex])) { + //version-only upgrade. + $this->update_database_version($this->versionFileVersion); + $this->newVersion = $this->versionFileVersion; + $this->gfObj->debug_print(__METHOD__ .": doing version-only upgrade..."); + } + else { + $scriptIndex = $versionIndex; + + $upgradeData = $this->config['MATCHING'][$versionIndex]; + + if(isset($upgradeData['TARGET_VERSION']) && count($upgradeData) > 1) { + $this->newVersion = $upgradeData['TARGET_VERSION']; + if(isset($upgradeData['SCRIPT_NAME']) && isset($upgradeData['CLASS_NAME']) && isset($upgradeData['CALL_METHOD'])) { + //good to go; it's a scripted upgrade. + $this->do_scripted_upgrade($upgradeData); + $this->update_database_version($upgradeData['TARGET_VERSION']); + } + else { + throw new exception(__METHOD__ .": not enough information to run scripted upgrade for ". $versionIndex); + } + } + else { + throw new exception(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); + } + } + $this->gfObj->debug_print(__METHOD__ .": done... "); + }//end do_single_upgrade() + //========================================================================= + + + + //========================================================================= + /** + * Updates information that's stored in the database, internal to cs-project, + * so the version there is consistent with all the others. + */ + protected function update_database_version($newVersionString) { + $this->gfObj->debug_print(__METHOD__ .": setting (". $newVersionString .")"); + $versionArr = $this->parse_version_string($newVersionString); + + $queryArr = array(); + foreach($versionArr as $index=>$value) { + $queryArr[$index] = "SELECT internal_data_set_value('". $index ."', '". $value ."');"; + } + + $retval = NULL; + foreach($queryArr as $name=>$sql) { + if($this->run_sql($sql, 1)) { + $retval++; + } + } + + //okay, now check that the version string matches the updated bits. + if(!$this->check_database_version($this->newVersion)) { + throw new exception(__METHOD__ .": database version information is invalid: (". $this->newVersion .")"); + } + + return($retval); + + }//end update_database_version() + //========================================================================= + + + + //========================================================================= + /** + * Checks consistency of version information in the database, and optionally + * against a given version string. + */ + private function check_database_version($checkThisVersion=NULL) { + //retrieve the internal version information. + $sql = "select internal_data_get_value('version_string') as version_string, (" . + "internal_data_get_value('version_major') || '.' || " . + "internal_data_get_value('version_minor') || '.' || " . + "internal_data_get_value('version_maintenance')) as check_version, " . + "internal_data_get_value('version_suffix') AS version_suffix"; + + $retval = NULL; + if($this->run_sql($sql,1)) { + $data = $this->db->farray_fieldnames(); + $versionString = $data['version_string']; + $checkVersion = $data['check_version']; + + if(strlen($data['version_suffix'])) { + //the version string already would have this, but the checked version wouldn't. + $checkVersion .= "-". $data['version_suffix']; + } + + if($versionString == $checkVersion) { + $retval = TRUE; + } + else { + $retval = FALSE; + } + } + else { + $retval = FALSE; + } + + if(!$retval) { + $this->gfObj->debug_print($data); + $this->gfObj->debug_print(__METHOD__ .": versionString=(". $versionString ."), checkVersion=(". $checkVersion .")"); + } + + return($retval); + + }//end check_database_version() + //========================================================================= + + + + //========================================================================= + private function do_scripted_upgrade(array $upgradeData) { + $myConfigFile = $upgradeData['SCRIPT_NAME']; + + $this->gfObj->debug_print(__METHOD__ .": script name=(". $myConfigFile .")"); + + //we've got the filename, see if it exists. + $fileName = UPGRADE_DIR .'/'. $myConfigFile; + if(file_exists($fileName)) { + $this->gfObj->debug_print(__METHOD__ .": file exists... "); + $createClassName = $upgradeData['CLASS_NAME']; + $classUpgradeMethod = $upgradeData['CALL_METHOD']; + require_once($fileName); + + //now check to see that the class we need actually exists. + if(class_exists($createClassName)) { + $upgradeObj = new $createClassName($this->db); + if(method_exists($upgradeObj, $classUpgradeMethod)) { + $upgradeResult = $upgradeObj->$classUpgradeMethod(); + $this->gfObj->debug_print(__METHOD__ .": finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")"); + } + else { + throw new exception(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod + ."), unable to perform upgrade "); + } + } + else { + throw new exception(__METHOD__ .": unable to locate upgrade class name (". $createClassName .")"); + } + } + else { + throw new exception(__METHOD__ .": upgrade filename (". $fileName .") does not exist"); + } + }//end do_scripted_upgrade() + //========================================================================= + + + + //========================================================================= + protected function run_sql($sql, $expectedNumrows=1) { + if(!$this->db->is_connected()) { + $this->db->connect(get_config_db_params()); + } + $numrows = $this->db->exec($sql); + $dberror = $this->db->errorMsg(); + + if(strlen($dberror)) { + $details = "DBERROR::: ". $dberror; + throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: ". $details); + } + elseif(!is_null($expectedNumrows) && $numrows != $expectedNumrows) { + throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: " . + "rows affected didn't match expectation (". $numrows ." != ". $expectedNumrows .")"); + } + elseif(is_null($expectedNumrows) && $numrows < 1) { + throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: " . + "invalid number of rows affected (". $numrows .")"); + } + else { + $retval = TRUE; + } + + return($retval); + }//end run_sql() + //========================================================================= + + + + //========================================================================= + private function update_config_file($index, $value) { + $gf = new cs_globalFunctions; + $myConfigFile = CONFIG_FILE_LOCATION; + $fs = new cs_fileSystemClass(dirname(__FILE__) .'/../'); + $xmlParser = new XMLParser($fs->read($myConfigFile)); + $xmlCreator = new XMLCreator; + $xmlCreator->load_xmlparser_data($xmlParser); + + //update the given index. + $xmlCreator->add_tag($index, $value, $xmlParser->get_attribute('/CONFIG/'. strtoupper($index))); + $this->mainConfig[strtoupper($index)] = $value; + + $xmlString = $xmlCreator->create_xml_string(); + + //truncate the file, to avoid problems with extra data at the end... + $fs->closeFile(); + $fs->create_file($myConfigFile,TRUE); + $fs->openFile($myConfigFile); + + //now write the new configuration. + $fs->write($xmlString, $myConfigFile); + }//end update_config_file() + //========================================================================= + + + + //========================================================================= + protected function get_num_users_to_convert() { + + $retval = 0; + try { + //if this generates an error, there are no users... + $this->run_sql("SELECT internal_data_get_value('users_to_convert')"); + $data = $this->db->farray(); + $retval = $data[0]; + } + catch(exception $e) { + $this->gfObj->debug_print(__METHOD__ .": failed to retrieve users to convert: "); + } + + return($retval); + + }//end get_num_users_to_convert() + //========================================================================= + + + + //========================================================================= + protected function update_num_users_to_convert() { + $retval = $this->run_sql("SELECT internal_data_set_value('users_to_convert', (select count(*) FROM user_table WHERE length(password) != 32))"); + return($retval); + }//end update_num_users_to_convert() + //========================================================================= + + + + //========================================================================= + protected function is_higher_version($version, $checkIfHigher) { + $retval = FALSE; + if(!is_string($version) || !is_string($checkIfHigher)) { + throw new exception(__METHOD__ .": didn't get strings... ". debug_print(func_get_args(),0)); + } + elseif($version == $checkIfHigher) { + $retval = FALSE; + } + else { + $curVersionArr = $this->parse_version_string($version); + $checkVersionArr = $this->parse_version_string($checkIfHigher); + + unset($curVersionArr['version_string'], $checkVersionArr['version_string']); + + + $curVersionSuffix = $curVersionArr['version_suffix']; + $checkVersionSuffix = $checkVersionArr['version_suffix']; + + + unset($curVersionArr['version_suffix']); + + foreach($curVersionArr as $index=>$versionNumber) { + $checkThis = $checkVersionArr[$index]; + + if(is_numeric($checkThis) && is_numeric($versionNumber)) { + //set them as integers. + settype($versionNumber, 'int'); + settype($checkThis, 'int'); + + if($checkThis > $versionNumber) { + $retval = TRUE; + break; + } + elseif($checkThis == $versionNumber) { + //they're equal... + } + else { + //TODO: should there maybe be an option to throw an exception (freak out) here? + debug_print(__METHOD__ .": while checking ". $index .", realized the new version (". $checkIfHigher .") is LOWER than current (". $version .")",1); + } + } + else { + throw new exception(__METHOD__ .": ". $index ." is not numeric in one of the strings " . + "(versionNumber=". $versionNumber .", checkThis=". $checkThis .")"); + } + } + + //now deal with those damnable suffixes, but only if the versions are so far identical: if + // the "$checkIfHigher" is actually higher, don't bother (i.e. suffixes don't matter when + // we already know there's a major, minor, or maintenance version that's also higher. + if($retval === FALSE) { + $this->gfObj->debug_print(__METHOD__ .": checking suffixes... "); + //EXAMPLE: $version="1.0.0-BETA3", $checkIfHigher="1.1.0" + // Moving from a non-suffixed version to a suffixed version isn't supported, but the inverse is: + // i.e. (1.0.0-BETA3 to 1.0.0) is okay, but (1.0.0 to 1.0.0-BETA3) is NOT. + // Also: (1.0.0-BETA3 to 1.0.0-BETA4) is okay, but (1.0.0-BETA4 to 1.0.0-BETA3) is NOT. + if(strlen($curVersionSuffix) && strlen($checkVersionSuffix) && $curVersionSuffix == $checkVersionSuffix) { + //matching suffixes. + $this->gfObj->debug_print(__METHOD__ .": suffixes match"); + } + elseif(strlen($curVersionSuffix) || strlen($checkVersionSuffix)) { + //we know the suffixes are there and DO match. + if(strlen($curVersionSuffix) && strlen($checkVersionSuffix)) { + //okay, here's where we do some crazy things... + $curVersionData = $this->parse_suffix($curVersionSuffix); + $checkVersionData = $this->parse_suffix($checkVersionSuffix); + + if($curVersionData['type'] == $checkVersionData['type']) { + $this->gfObj->debug_print(__METHOD__ .": got the same type..."); + //got the same suffix type (like "BETA"), check the number. + if($checkVersionData['number'] > $curVersionData['number']) { + $this->gfObj->debug_print(__METHOD__ .": new version's suffix number higher than current... "); + $retval = TRUE; + } + elseif($checkVersionData['number'] == $curVersionData['number']) { + $this->gfObj->debug_print(__METHOD__ .": new version's suffix number is EQUAL TO current... "); + $retval = FALSE; + } + else { + //umm... they're identical??? LOGIC HAS FAILED ME ALTOGETHER!!! + $this->gfObj->debug_print(__METHOD__ .": new version's suffix number is LESS THAN current... "); + $retval = FALSE; + } + } + else { + //not the same suffix... see if the new one is higher. + $suffixValues = array_flip($this->suffixList); + if($suffixValues[$checkVersionData['type']] > $suffixValues[$curVersionData['type']]) { + $retval = TRUE; + } + else { + $this->gfObj->debug_print(__METHOD__ .": current suffix type is higher... "); + } + } + + } + elseif(strlen($curVersionSuffix) && !strlen($checkVersionSuffix)) { + //i.e. "1.0.0-BETA1" to "1.0.0" --->>> OKAY! + $retval = TRUE; + } + elseif(!strlen($curVersionSuffix) && strlen($checkVersionSuffix)) { + //i.e. "1.0.0" to "1.0.0-BETA1" --->>> NOT ACCEPTABLE! + $this->gfObj->debug_print(__METHOD__ .": from (". $version .") to (". $checkIfHigher .") isn't acceptable...?"); + } + } + else { + $this->gfObj->debug_print(__METHOD__ .": no suffix to care about"); + } + } + } + + $this->gfObj->debug_print(__METHOD__ .": ('". $version ."', '". $checkIfHigher ."') retval=(". $retval .")", 1); + + return($retval); + + }//end is_higher_version() + //========================================================================= + + + + //========================================================================= + /** + * Determines list of upgrades to perform. + * + * If the current version is 1.0.1, the version file is 1.0.5, and there's a + * scripted upgrade at 1.0.4, this will update the database version to 1.0.3, + * run the scripted upgrade at 1.0.4, then update the database version to + * 1.0.5 (keeps from skipping the upgrade at 1.0.4) + */ + private function get_upgrade_list() { + $this->get_database_version(); + $dbVersion = $this->databaseVersion; + $newVersion = $this->versionFileVersion; + + $retval = array(); + if(!$this->is_higher_version($dbVersion, $newVersion)) { + throw new exception(__METHOD__ .": version (". $newVersion .") isn't higher than (". $dbVersion .")... something is broken"); + } + elseif(is_array($this->config['MATCHING'])) { + $lastVersion = $dbVersion; + foreach($this->config['MATCHING'] as $matchVersion=>$data) { + + $matchVersion = preg_replace('/^V/', '', $matchVersion); + if($matchVersion == $data['TARGET_VERSION']) { + throw new exception(__METHOD__ .": detected invalid TARGET_VERSION in (". $matchVersion ."): make sure TARGET_VERSION is higher than matching!"); + } + elseif($this->databaseVersion == $matchVersion || $this->is_higher_version($this->databaseVersion, $matchVersion)) { + //the version in MATCHING is equal to or HIGHER than our database version... make sure it is NOT + // higher than the version in our versionFile. + if(!$this->is_higher_version($this->versionFileVersion, $matchVersion)) { + if(!count($retval) && $matchVersion != $this->databaseVersion) { + $retval[$this->databaseVersion] = $matchVersion; + } + //the MATCHING version is NOT higher than the version file's version, looks ok. + $this->gfObj->debug_print(__METHOD__ .": adding (". $matchVersion .")"); + $lastVersion = $data['TARGET_VERSION']; + $retval[$matchVersion] = $data['TARGET_VERSION']; + } + else { + $this->gfObj->debug_print(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")"); + } + } + else { + $this->gfObj->debug_print(__METHOD__ .": SKIPPING (". $matchVersion .")"); + } + } + + if($lastVersion !== $newVersion && (!isset($retval[$lastVersion]) || $retval[$lastVersion] != $newVersion)) { + $this->gfObj->debug_print(__METHOD__ .": <b>ALSO (". $lastVersion .") => (". $newVersion .")</b>"); + $retval[$lastVersion] = $newVersion; + } + } + else { + //no intermediary upgrades: just pass back the latest version. + $this->gfObj->debug_print(__METHOD__ .": no intermediary upgrades"); + $retval[$dbVersion] = $this->versionFileVersion; + } + + return($retval); + + }//end get_upgrade_list() + //========================================================================= + + + + //========================================================================= + protected function parse_suffix($suffix) { + $retval = NULL; + if(strlen($suffix)) { + //determine what kind it is. + foreach($this->suffixList as $type) { + if(preg_match('/^'. $type .'/', $suffix)) { + $checkThis = preg_replace('/^'. $type .'/', '', $suffix); + if(strlen($checkThis) && is_numeric($checkThis)) { + //oooh... it's something like "BETA3" + $retval = array( + 'type' => $type, + 'number' => $checkThis + ); + } + else { + throw new exception(__METHOD__ .": invalid suffix (". $suffix .")"); + } + break; + } + } + } + else { + throw new exception(__METHOD__ .": invalid suffix (". $suffix .")"); + } + + return($retval); + }//end parse_suffix() + //========================================================================= + + +}//end upgrade{} + + +?> \ No newline at end of file Deleted: trunk/0.1/upgradeClass.php =================================================================== --- trunk/0.1/upgradeClass.php 2009-06-30 18:21:09 UTC (rev 8) +++ trunk/0.1/upgradeClass.php 2009-06-30 18:22:58 UTC (rev 9) @@ -1,902 +0,0 @@ -<?php -/* - * Created on Jul 2, 2007 - * - * SVN INFORMATION::: - * ------------------ - * SVN Signature::::::: $Id$ - * Last Author::::::::: $Author$ - * Current Revision:::: $Revision$ - * Repository Location: $HeadURL$ - * Last Updated:::::::: $Date$ - * - */ - -class upgrade { - - private $fsObj; - private $gfObj; - private $config = NULL; - protected $db; - protected $logsObj; - - private $versionFileVersion = NULL; - private $configVersion = NULL; - private $databaseVersion = NULL; - - private $mainConfig = NULL; - - /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in - * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ - private $suffixList = array( - 'ALPHA', //very unstable - 'BETA', //kinda unstable, but probably useable - 'RC' //all known bugs fixed, searching for unknown ones - ); - - //========================================================================= - public function __construct() { - $this->fsObj = new cs_fileSystemClass(dirname(__FILE__) .'/../'); - $this->gfObj = new cs_globalFunctions; - $this->gfObj->debugPrintOpt = DEBUGPRINTOPT; - clearstatcache(); - - $this->db = new cs_phpDB; - $this->db->connect(get_config_db_params()); - - $this->logsObj = new logsClass($this->db, "Upgrade"); - - //define some things for upgrades. - define("UPGRADE_LOCKFILE", dirname(__FILE__) ."/../UPGRADING_VERSION"); //relative to the directory beneath lib. - define("UPGRADE_DIR", dirname(__FILE__) ."/../upgrade"); - }//end __construct() - //========================================================================= - - - - //========================================================================= - /** - * Where everything begins: checks if the version held in config.xml lines-up - * with the one in the VERSION file; if it does, then it checks the version - * listed in the database. - */ - public function check_versions($performUpgrade=TRUE) { - //first, check that all files exist. - $retval = NULL; - - //check to see if the lock files for upgrading exist. - if($this->upgrade_in_progress()) { - throw new exception(__METHOD__ .": upgrade in progress"); - } - elseif(!file_exists(CONFIG_FILE_LOCATION)) { - throw new exception(__METHOD__ .": config.xml file missing"); - } - elseif(!file_exists(dirname(__FILE__) .'/../VERSION')) { - throw new exception(__METHOD__ .": VERSION file missing"); - } - elseif(!file_exists(dirname(__FILE__) .'/../upgrade/upgrade.xml')) { - throw new exception(__METHOD__ .": upgrade.xml file missing"); - } - else { - //okay, all files present: check the version in the VERSION file. - $versionFileContents = $this->read_version_file(); - - //now read data from the config. - $versionFromConfig = $this->read_config_version(); - - $versionsDiffer = TRUE; - $retval = FALSE; - if($versionFileContents == $versionFromConfig) { - $versionConflict = $this->check_for_version_conflict(); - if($versionConflict === 0) { - //all is good: no problems detected (all things match-up). - $versionsDiffer=FALSE; - $performUpgrade = FALSE; - } - else { - // - $versionsDiffer = TRUE; - } - } - - if($versionsDiffer == TRUE && $performUpgrade === TRUE) { - //reset the return value, so it'll default to failure until we say otherwise. - $retval = NULL; - - //Perform the upgrade! - $this->perform_upgrade(); - } - } - - return($retval); - }//end check_versions() - //========================================================================= - - - - //========================================================================= - protected function read_version_file() { - $retval = NULL; - - //okay, all files present: check the version in the VERSION file. - $versionFileContents = $this->fsObj->read('VERSION'); - - //okay, rip it into bits. NOTE: this *depends* on "VERSION: " being on the third line. - $lines = explode("\n", $versionFileContents); - $versionLine = $lines[2]; - if(preg_match('/^VERSION: /', $versionLine)) { - - $retval = trim(preg_replace('/VERSION: /', '', $versionLine)); - $this->versionFileVersion = $retval; - } - else { - throw new exception(__METHOD__ .": could not find VERSION data"); - } - - return($retval); - }//end read_version_file() - //========================================================================= - - - - //========================================================================= - private function read_config_version() { - $configObj = new config(); - $config = $configObj->read_config_file(FALSE); - $this->mainConfig = $config; - $retval = NULL; - - if(!is_array($config) || !count($config)) { - throw new exception(__METHOD__ .": no configuration data available (missing config file?)"); - } - else { - //now, let's see if there's a "version_string" index. - if(isset($config['VERSION_STRING']) && strlen($config['VERSION_STRING'])) { - $retval = $config['VERSION_STRING']; - } - else { - throw new exception(__METHOD__ .": invalid version string found (". $config['VERSION_STRING'] .")"); - } - } - - $this->configVersion = $retval; - return($retval); - }//end read_config_version() - //========================================================================= - - - - //========================================================================= - /** - * Read information from our config file, so we know what to expect. - */ - private function read_upgrade_config_file() { - $xmlString = $this->fsObj->read("upgrade/upgrade.xml"); - - //parse the file. - $xmlParser = new xmlParser($xmlString); - - $config = $xmlParser->get_tree(TRUE); - $this->config = $config['UPGRADE']; - }//end read_upgrade_config_file() - //========================================================================= - - - - //========================================================================= - private function perform_upgrade() { - //make sure there's not already a lockfile. - if($this->upgrade_in_progress()) { - //ew. Can't upgrade. - throw new exception(__METHOD__ .": upgrade already in progress...????"); - } - else { - $lockConfig = $this->upgrade_in_progress(TRUE); - $this->fsObj->cd("/"); - - //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists(). - if($lockConfig === 0) { - //can't create the lockfile. Die. - throw new exception(__METHOD__ .": failed to set 'upgrade in progress'"); - } - else { - $this->gfObj->debug_print(__METHOD__ .": result of setting 'upgrade in progress': (". $lockConfig .")"); - - //check to see if our config file is writable. - if(!$this->fsObj->is_writable(CONFIG_FILE_LOCATION)) { - throw new exception(__METHOD__ .": config file isn't writable!"); - } - - //push data into our internal "config" array. - $this->read_upgrade_config_file(); - $this->get_database_version(); - - //check for version conflicts. - $this->check_for_version_conflict(); - - $upgradeList = $this->get_upgrade_list(); - - $i=0; - $this->gfObj->debug_print(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion .")..."); - $this->db->beginTrans(__METHOD__); - foreach($upgradeList as $fromVersion=>$toVersion) { - - $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; - $this->gfObj->debug_print($details); - $this->logsObj->log_by_class($details, 'system'); - $this->do_single_upgrade($fromVersion); - $this->get_database_version(); - $i++; - - $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; - $this->gfObj->debug_print($details); - $this->logsObj->log_by_class($details, 'system'); - } - - if($this->databaseVersion == $this->versionFileVersion) { - $this->gfObj->debug_print(__METHOD__ .": finished upgrading after performing (". $i .") upgrades!!!"); - $this->newVersion = $this->databaseVersion; - } - else { - throw new exception(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); - } - $this->update_config_file('version_string', $this->newVersion); - $this->update_config_file('workingonit', "0"); - - $this->db->commitTrans(); - } - } - }//end perform_upgrade() - //========================================================================= - - - - //========================================================================= - public function upgrade_in_progress($makeItSo=FALSE) { - $retval = FALSE; - if($makeItSo === TRUE) { - $this->get_database_version(); - $details = 'Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s'); - $this->update_config_file('WORKINGONIT', $details); - $retval = TRUE; - } - elseif(preg_match('/^upgrade/i', $this->mainConfig['WORKINGONIT'])) { - $retval = TRUE; - } - - return($retval); - }//end upgrade_in_progress() - //========================================================================= - - - - //========================================================================= - public function parse_version_string($versionString) { - if(is_null($versionString) || !strlen($versionString)) { - throw new exception(__METHOD__ .": invalid version string ($versionString)"); - } - $tmp = explode('.', $versionString); - - //NOTE: the order of the array MUST be major, then minor, then maintenance, so is_higher_version() can check it easily. - $retval = array( - 'version_string' => $versionString, - 'version_major' => $tmp[0], - 'version_minor' => $tmp[1] - ); - if(count($tmp) == 3) { - $retval['version_maintenance'] = $tmp[2]; - } - else { - $retval['version_maintenance'] = "0"; - } - - //check for a prefix or a suffix. - if(preg_match('/-/', $versionString)) { - //make sure there's only ONE dash. - $tmp = explode('-', $versionString); - if(count($tmp) == 2) { - if(preg_match('/-/', $retval['version_major'])) { - //example: BETA-3.3.0 - - throw new exception(__METHOD__ .": versions that contain prefixes cannot be upgraded"); - - #$tmp = explode('-', $retval['version_major']); - #$retval['version_major'] = $tmp[1]; - #$retval['prefix'] = $tmp[0]; - } - elseif(preg_match('/-/', $retval['version_maintenance'])) { - //example: 1.0.0-ALPHA1 - $tmp = explode('-', $retval['version_maintenance']); - $retval['version_maintenance'] = $tmp[0]; - $retval['version_suffix'] = $tmp[1]; - } - else { - throw new exception(__METHOD__ .": invalid location of prefix/suffix in (". $versionString .")"); - } - } - else { - throw new exception(__METHOD__ .": too many dashes in version string (". $versionString .")"); - } - } - else { - $retval['version_suffix'] = ""; - } - - return($retval); - }//end parse_version_string() - //========================================================================= - - - - //========================================================================= - /** - * Checks for issues with versions. - * 0 == No problems. - * (string) == upgrade applicable (indicates "major"/"minor"/"maintenance"). - * NULL == encountered error - */ - private function check_for_version_conflict() { - //set a default return... - $retval = NULL; - - //call to ensure files have been processed. - #$this->check_versions(FALSE); - $this->read_config_version(); - $this->read_version_file(); - $configVersion = NULL; - - //parse the version strings. - if(strlen($this->configVersion)) { - $configVersion = $this->parse_version_string($this->configVersion); - } - $versionFile = $this->parse_version_string($this->versionFileVersion); - - - $dbVersion = $this->get_database_version(); - $versionFileData = $this->parse_version_string($this->versionFileVersion); - - if($versionFileData['version_string'] == $dbVersion['version_string']) { - //good to go: no upgrade needed. - $retval = 0; - } - else { - //NOTE: this seems very convoluted, but it works. - if($versionFileData['version_major'] == $dbVersion['version_major']) { - if($versionFileData['version_minor'] == $dbVersion['version_minor']) { - if($versionFileData['version_maintenance'] == $dbVersion['version_maintenance']) { - if($versionFileData['version_suffix'] == $dbVersion['version_suffix']) { - throw new exception(__METHOD__ .": no version upgrade detected, but version strings don't match (versionFile=". $versionFileData['version_string'] .", dbVersion=". $dbVersion['version_string'] .")"); - } - else { - $retval = "suffix"; - } - } - elseif($versionFileData['version_maintenance'] > $dbVersion['version_maintenance']) { - $retval = "maintenance"; - } - else { - throw new exception(__METHOD__ .": downgrading from maintenance versions is unsupported"); - } - } - elseif($versionFileData['version_minor'] > $dbVersion['version_minor']) { - $retval = "minor"; - } - else { - throw new exception(__METHOD__ .": downgrading minor versions is unsupported"); - } - } - elseif($versionFileData['version_major'] > $dbVersion['version_major']) { - $retval = "major"; - } - else { - throw new exception(__METHOD__ .": downgrading major versions is unsupported"); - } - } - - if(!is_null($retval) && $retval !== 0) { - $this->gfObj->debug_print(__METHOD__ .": upgrading ". $retval ." versions, from (". $this->databaseVersion .") to (". $this->versionFileVersion .")"); - } - - return($retval); - }//end check_for_version_conflict() - //========================================================================= - - - - //========================================================================= - private function get_database_version() { - //create a database object & attempt to read the database version. - - if(!is_object($this->db) || get_class($this->db) != 'cs_phpDB') { - $this->db = new cs_phpDB; - $this->db->connect(get_config_db_params()); - } - - $sql = "SELECT " . - "internal_data_get_value('version_string') AS version_string, " . - "internal_data_get_value('version_major') AS version_major, " . - "internal_data_get_value('version_minor') AS version_minor, " . - "internal_data_get_value('version_maintenance') AS version_maintenance, " . - "internal_data_get_value('version_suffix') AS version_suffix"; - $numrows = $this->db->exec($sql); - $dberror = $this->db->errorMsg(); - - if(strlen($dberror) || $numrows != 1) { - //fail. - throw new exception(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror); - } - else { - $data = $this->db->farray_fieldnames(); - $this->databaseVersion = $data['version_string']; - $retval = $this->parse_version_string($data['version_string']); - } - - return($retval); - }//end get_database_version() - //========================================================================= - - - - //========================================================================= - private function do_single_upgrade($targetVersion) { - //Use the "matching_syntax" data in the upgrade.xml file to determine the filename. - $versionIndex = "V". $targetVersion; - $this->gfObj->debug_print(__METHOD__ .": versionIndex=(". $versionIndex ."), config MATCHING::: ". $this->gfObj->debug_print($this->config['MATCHING'],0)); - if(!isset($this->config['MATCHING'][$versionIndex])) { - //version-only upgrade. - $this->update_database_version($this->versionFileVersion); - $this->newVersion = $this->versionFileVersion; - $this->gfObj->debug_print(__METHOD__ .": doing version-only upgrade..."); - } - else { - $scriptIndex = $versionIndex; - - $upgradeData = $this->config['MATCHING'][$versionIndex]; - - if(isset($upgradeData['TARGET_VERSION']) && count($upgradeData) > 1) { - $this->newVersion = $upgradeData['TARGET_VERSION']; - if(isset($upgradeData['SCRIPT_NAME']) && isset($upgradeData['CLASS_NAME']) && isset($upgradeData['CALL_METHOD'])) { - //good to go; it's a scripted upgrade. - $this->do_scripted_upgrade($upgradeData); - $this->update_database_version($upgradeData['TARGET_VERSION']); - } - else { - throw new exception(__METHOD__ .": not enough information to run scripted upgrade for ". $versionIndex); - } - } - else { - throw new exception(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); - } - } - $this->gfObj->debug_print(__METHOD__ .": done... "); - }//end do_single_upgrade() - //========================================================================= - - - - //========================================================================= - /** - * Updates information that's stored in the database, internal to cs-project, - * so the version there is consistent with all the others. - */ - protected function update_database_version($newVersionString) { - $this->gfObj->debug_print(__METHOD__ .": setting (". $newVersionString .")"); - $versionArr = $this->parse_version_string($newVersionString); - - $queryArr = array(); - foreach($versionArr as $index=>$value) { - $queryArr[$index] = "SELECT internal_data_set_value('". $index ."', '". $value ."');"; - } - - $retval = NULL; - foreach($queryArr as $name=>$sql) { - if($this->run_sql($sql, 1)) { - $retval++; - } - } - - //okay, now check that the version string matches the updated bits. - if(!$this->check_database_version($this->newVersion)) { - throw new exception(__METHOD__ .": database version information is invalid: (". $this->newVersion .")"); - } - - return($retval); - - }//end update_database_version() - //========================================================================= - - - - //========================================================================= - /** - * Checks consistency of version information in the database, and optionally - * against a given version string. - */ - private function check_database_version($checkThisVersion=NULL) { - //retrieve the internal version information. - $sql = "select internal_data_get_value('version_string') as version_string, (" . - "internal_data_get_value('version_major') || '.' || " . - "internal_data_get_value('version_minor') || '.' || " . - "internal_data_get_value('version_maintenance')) as check_version, " . - "internal_data_get_value('version_suffix') AS version_suffix"; - - $retval = NULL; - if($this->run_sql($sql,1)) { - $data = $this->db->farray_fieldnames(); - $versionString = $data['version_string']; - $checkVersion = $data['check_version']; - - if(strlen($data['version_suffix'])) { - //the version string already would have this, but the checked version wouldn't. - $checkVersion .= "-". $data['version_suffix']; - } - - if($versionString == $checkVersion) { - $retval = TRUE; - } - else { - $retval = FALSE; - } - } - else { - $retval = FALSE; - } - - if(!$retval) { - $this->gfObj->debug_print($data); - $this->gfObj->debug_print(__METHOD__ .": versionString=(". $versionString ."), checkVersion=(". $checkVersion .")"); - } - - return($retval); - - }//end check_database_version() - //========================================================================= - - - - //========================================================================= - private function do_scripted_upgrade(array $upgradeData) { - $myConfigFile = $upgradeData['SCRIPT_NAME']; - - $this->gfObj->debug_print(__METHOD__ .": script name=(". $myConfigFile .")"); - - //we've got the filename, see if it exists. - $fileName = UPGRADE_DIR .'/'. $myConfigFile; - if(file_exists($fileName)) { - $this->gfObj->debug_print(__METHOD__ .": file exists... "); - $createClassName = $upgradeData['CLASS_NAME']; - $classUpgradeMethod = $upgradeData['CALL_METHOD']; - require_once($fileName); - - //now check to see that the class we need actually exists. - if(class_exists($createClassName)) { - $upgradeObj = new $createClassName($this->db); - if(method_exists($upgradeObj, $classUpgradeMethod)) { - $upgradeResult = $upgradeObj->$classUpgradeMethod(); - $this->gfObj->debug_print(__METHOD__ .": finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")"); - } - else { - throw new exception(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod - ."), unable to perform upgrade "); - } - } - else { - throw new exception(__METHOD__ .": unable to locate upgrade class name (". $createClassName .")"); - } - } - else { - throw new exception(__METHOD__ .": upgrade filename (". $fileName .") does not exist"); - } - }//end do_scripted_upgrade() - //========================================================================= - - - - //========================================================================= - protected function run_sql($sql, $expectedNumrows=1) { - if(!$this->db->is_connected()) { - $this->db->connect(get_config_db_params()); - } - $numrows = $this->db->exec($sql); - $dberror = $this->db->errorMsg(); - - if(strlen($dberror)) { - $details = "DBERROR::: ". $dberror; - throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: ". $details); - } - elseif(!is_null($expectedNumrows) && $numrows != $expectedNumrows) { - throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: " . - "rows affected didn't match expectation (". $numrows ." != ". $expectedNumrows .")"); - } - elseif(is_null($expectedNumrows) && $numrows < 1) { - throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: " . - "invalid number of rows affected (". $numrows .")"); - } - else { - $retval = TRUE; - } - - return($retval); - }//end run_sql() - //========================================================================= - - - - //========================================================================= - private function update_config_file($index, $value) { - $gf = new cs_globalFunctions; - $myConfigFile = CONFIG_FILE_LOCATION; - $fs = new cs_fileSystemClass(dirname(__FILE__) .'/../'); - $xmlParser = new XMLParser($fs->read($myConfigFile)); - $xmlCreator = new XMLCreator; - $xmlCreator->load_xmlparser_data($xmlParser); - - //update the given index. - $xmlCreator->add_tag($index, $value, $xmlParser->get_attribute('/CONFIG/'. strtoupper($index))); - $this->mainConfig[strtoupper($index)] = $value; - - $xmlString = $xmlCreator->create_xml_string(); - - //truncate the file, to avoid problems with extra data at the end... - $fs->closeFile(); - $fs->create_file($myConfigFile,TRUE); - $fs->openFile($myConfigFile); - - //now write the new configuration. - $fs->write($xmlString, $myConfigFile); - }//end update_config_file() - //========================================================================= - - - - //========================================================================= - protected function get_num_users_to_convert() { - - $retval = 0; - try { - //if this generates an error, there are no users... - $this->run_sql("SELECT internal_data_get_value('users_to_convert')"); - $data = $this->db->farray(); - $retval = $data[0]; - } - catch(exception $e) { - $this->gfObj->debug_print(__METHOD__ .": failed to retrieve users to convert: "); - } - - return($retval); - - }//end get_num_users_to_convert() - //========================================================================= - - - - //========================================================================= - protected function update_num_users_to_convert() { - $retval = $this->run_sql("SELECT internal_data_set_value('users_to_convert', (select count(*) FROM user_table WHERE length(password) != 32))"); - return($retval); - }//end update_num_users_to_convert() - //========================================================================= - - - - //========================================================================= - protected function is_higher_version($version, $checkIfHigher) { - $retval = FALSE; - if(!is_string($version) || !is_string($checkIfHigher)) { - throw new exception(__METHOD__ .": didn't get strings... ". debug_print(func_get_args(),0)); - } - elseif($version == $checkIfHigher) { - $retval = FALSE; - } - else { - $curVersionArr = $this->parse_version_string($version); - $checkVersionArr = $this->parse_version_string($checkIfHigher); - - unset($curVersionArr['version_string'], $checkVersionArr['version_string']); - - - $curVersionSuffix = $curVersionArr['version_suffix']; - $checkVersionSuffix = $checkVersionArr['version_suffix']; - - - unset($curVersionArr['version_suffix']); - - foreach($curVersionArr as $index=>$versionNumber) { - $checkThis = $checkVersionArr[$index]; - - if(is_numeric($checkThis) && is_numeric($versionNumber)) { - //set them as integers. - settype($versionNumber, 'int'); - settype($checkThis, 'int'); - - if($checkThis > $versionNumber) { - $retval = TRUE; - break; - } - elseif($checkThis == $versionNumber) { - //they're equal... - } - else { - //TODO: should there maybe be an option to throw an exception (freak out) here? - debug_print(__METHOD__ .": while checking ". $index .", realized the new version (". $checkIfHigher .") is LOWER than current (". $version .")",1); - } - } - else { - throw new exception(__METHOD__ .": ". $index ." is not numeric in one of the strings " . - "(versionNumber=". $versionNumber .", checkThis=". $checkThis .")"); - } - } - - //now deal with those damnable suffixes, but only if the versions are so far identical: if - // the "$checkIfHigher" is actually higher, don't bother (i.e. suffixes don't matter when - // we already know there's a major, minor, or maintenance version that's also higher. - if($retval === FALSE) { - $this->gfObj->debug_print(__METHOD__ .": checking suffixes... "); - ... [truncated message content] |
From: <cra...@us...> - 2009-06-30 18:21:16
|
Revision: 8 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=8&view=rev Author: crazedsanity Date: 2009-06-30 18:21:09 +0000 (Tue, 30 Jun 2009) Log Message: ----------- Add "svn:keywords" to the main upgradeClass.php file, so it shows the correct SVN info. Modified Paths: -------------- trunk/0.1/upgradeClass.php Property Changed: ---------------- trunk/0.1/upgradeClass.php Modified: trunk/0.1/upgradeClass.php =================================================================== --- trunk/0.1/upgradeClass.php 2009-01-16 15:26:06 UTC (rev 7) +++ trunk/0.1/upgradeClass.php 2009-06-30 18:21:09 UTC (rev 8) @@ -4,11 +4,11 @@ * * SVN INFORMATION::: * ------------------ - * SVN Signature::::::: $Id: upgradeClass.php 894 2008-05-16 03:26:15Z crazedsanity $ - * Last Author::::::::: $Author: crazedsanity $ - * Current Revision:::: $Revision: 894 $ - * Repository Location: $HeadURL: https://cs-project.svn.sourceforge.net/svnroot/cs-project/trunk/1.2/lib/upgradeClass.php $ - * Last Updated:::::::: $Date: 2008-05-15 22:26:15 -0500 (Thu, 15 May 2008) $ + * SVN Signature::::::: $Id$ + * Last Author::::::::: $Author$ + * Current Revision:::: $Revision$ + * Repository Location: $HeadURL$ + * Last Updated:::::::: $Date$ * */ Property changes on: trunk/0.1/upgradeClass.php ___________________________________________________________________ Added: svn:keywords + Id Author Revision HeadURL Date This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-01-16 15:26:16
|
Revision: 7 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=7&view=rev Author: crazedsanity Date: 2009-01-16 15:26:06 +0000 (Fri, 16 Jan 2009) Log Message: ----------- Added some example scripts & configuration for upgrading. Added Paths: ----------- trunk/0.1/exampleUpgrades/ trunk/0.1/exampleUpgrades/upgrade.xml trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php Added: trunk/0.1/exampleUpgrades/upgrade.xml =================================================================== --- trunk/0.1/exampleUpgrades/upgrade.xml (rev 0) +++ trunk/0.1/exampleUpgrades/upgrade.xml 2009-01-16 15:26:06 UTC (rev 7) @@ -0,0 +1,35 @@ +<upgrade> + <system_note>To determine which section in matching to use, heed only the information + beneath the tag that indicates the current database version (for 5.2.4, + you would find information under matching for "v5.2.4"). This section + indicates the version that it should upgrade the database to + ("target_version"), the name of the script ("script_name"), the class name + ("class_name"), and the name of the method within that class ("call_method") + to call in order to perform the upgrade. The method should return TRUE on + success: anything else would indicate failure. Upgrade failure may leave + the system in an inconsistent state. + + IMPORTANT: in order to facilitate doing multiple version upgrades, the name + of the class must be UNIQUE to all the other classes. For this reason, the + class name should be something like "v1_0_0_ALPHA1__to__v1_0_0_ALPHA2". + + REMEMBER: the "target_version" should NEVER be higher than the next item + beneath matching; this will cause horrible logic errors, causing an upgsrade + to get skipped, or an exception to be thrown, potentially leaving the system + in an unstable state. Unstable is bad, m'kay?</system_note> + + <matching> + <v1.2.0-ALPHA3> + <target_version>1.2.0-ALPHA4</target_version> + <script_name>upgradeTo1.2.0-ALPHA4.php</script_name> + <class_name>upgrade_to_1_2_0_ALPHA4</class_name> + <call_method>run_upgrade</call_method> + </v1.2.0-ALPHA3> + <v1.2.0-ALPHA6> + <target_version>1.2.0-ALPHA7</target_version> + <script_name>upgradeTo1.2.0-ALPHA7.php</script_name> + <class_name>upgrade_to_1_2_0_ALPHA7</class_name> + <call_method>run_upgrade</call_method> + </v1.2.0-ALPHA6> + </matching> +</upgrade> Added: trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php =================================================================== --- trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php (rev 0) +++ trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php 2009-01-16 15:26:06 UTC (rev 7) @@ -0,0 +1,153 @@ +<?php + +class upgrade_to_1_2_0_ALPHA4 extends dbAbstract { + + private $logsObj; + + //========================================================================= + public function __construct(cs_phpDB &$db) { + if(!$db->is_connected()) { + throw new exception(__METHOD__ .": database is not connected"); + } + $this->db = $db; + + $this->logsObj = new logsClass($this->db, 'Upgrade'); + + $this->gfObj = new cs_globalFunctions; + $this->gfObj->debugPrintOpt = 1; + }//end __construct() + //========================================================================= + + + + //========================================================================= + public function run_upgrade() { + + $this->db->beginTrans(__METHOD__); + + + $this->run_schema_changes(); + $this->update_tag_icons(); + $this->update_config_file(); + + + $this->db->commitTrans(__METHOD__); + + return('Upgrade complete'); + }//end run_upgrade() + //========================================================================= + + + + //========================================================================= + private function run_schema_changes() { + + $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); + $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA2.sql'); + + $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". + base64_encode($this->fsObj->read($this->lastSQLFile)); + $this->logsObj->log_by_class($details, 'system'); + + + + $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); + $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA4.sql'); + + $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". + base64_encode($this->fsObj->read($this->lastSQLFile)); + $this->logsObj->log_by_class($details, 'system'); + + }//end run_schema_changes() + //========================================================================= + + + + //========================================================================= + private function update_tag_icons() { + + $sql = "SELECT tag_name_id, name, icon_name FROM tag_name_table ORDER BY tag_name_id"; + if($this->run_sql($sql) && $this->lastNumrows > 1) { + $allTags = $this->db->farray_fieldnames('name', 'tag_name_id'); + + $iconMods = array( + 'critical' => 'red_x', + 'bug' => 'bug', + 'feature request' => 'feature_request', + 'committed' => 'check_red', + 'verified' => 'check_yellow', + 'released' => 'check_green' + ); + + $updates = 0; + foreach($iconMods as $name=>$icon) { + if(isset($allTags[$name])) { + //update. + $sql = "UPDATE tag_name_table SET icon_name='". $icon ."' WHERE tag_name_id=". $allTags[$name]['tag_name_id']; + } + else { + //insert. + $sql = "INSERT INTO tag_name_table (name, icon_name) VALUES ('". $name ."', '". $icon ."');"; + } + $this->run_sql($sql); + $updates += $this->lastNumrows; + } + } + else { + throw new exception(__METHOD__ .": failed to retrieve tag names"); + } + + }//end update_tag_modifiers() + //========================================================================= + + + + //========================================================================= + public function update_config_file() { + $fs = new cs_fileSystemClass(dirname(__FILE__) .'/../'); + $sampleXmlObj = new XMLParser($fs->read('docs/samples/sample_config.xml')); + $siteXmlObj = new XMLParser($fs->read(CONFIG_FILE_LOCATION)); + + $updateXml = new xmlCreator(); + $updateXml->load_xmlparser_data($siteXmlObj); + + + //BACKUP ORIGINAL XML CONFIG... + $backupFile = 'lib/__BACKUP__'. time() .'__'. CONFIG_FILENAME; + $fs->create_file($backupFile); + $fs->openFile($backupFile); + $fs->write($updateXml->create_xml_string()); + + $sampleIndexes = $sampleXmlObj->get_tree(TRUE); + $sampleIndexes = $sampleIndexes['CONFIG']; + + $siteConfigIndexes = $siteXmlObj->get_tree(TRUE); + $siteConfigIndexes = $siteConfigIndexes['CONFIG']; + + foreach($sampleIndexes as $indexName=>$indexValue) { + $path = '/CONFIG/'. $indexName; + $attributes = $sampleXmlObj->get_attribute($path); + #debug_print(__METHOD__ .": attributes from sample (/CONFIG/". $indexName ."::: ",1); + #debug_print($attributes,1); + debug_print(__METHOD__ .': indexName=('. $indexName .'), indexValue=('. $indexValue .'), original config value=('. $siteConfigIndexes[$indexName] .')'); + + //add tag if it's not there, update values otherwise. + $tagValue = $attributes['DEFAULT']; + if(isset($siteConfigIndexes[$indexName])) { + $tagValue = $siteConfigIndexes[$indexName]; + } + elseif($indexName == 'PHPMAILER_HOST' && isset($siteConfigIndexes['CONFIG_EMAIL_SERVER_IP'])) { + $tagValue = $siteConfigIndexes['CONFIG_EMAIL_SERVER_IP']; + $updateXml->remove_path('/CONFIG/CONFIG_EMAIL_SERVER_IP'); + } + $updateXml->add_tag($path, $tagValue, $attributes); + } + + $this->gfObj->debug_print($this->gfObj->cleanString($updateXml->create_xml_string(), 'htmlentity_plus_brackets')); + $fs->openFile(CONFIG_FILE_LOCATION); + $fs->write($updateXml->create_xml_string()); + }//end update_config_file() + //========================================================================= +} + +?> Added: trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php =================================================================== --- trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php (rev 0) +++ trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php 2009-01-16 15:26:06 UTC (rev 7) @@ -0,0 +1,54 @@ +<?php + +class upgrade_to_1_2_0_ALPHA7 extends dbAbstract { + + private $logsObj; + + //========================================================================= + public function __construct(cs_phpDB &$db) { + if(!$db->is_connected()) { + throw new exception(__METHOD__ .": database is not connected"); + } + $this->db = $db; + + $this->logsObj = new logsClass($this->db, 'Upgrade'); + + $this->gfObj = new cs_globalFunctions; + $this->gfObj->debugPrintOpt = 1; + }//end __construct() + //========================================================================= + + + + //========================================================================= + public function run_upgrade() { + + $this->db->beginTrans(__METHOD__); + + + $this->run_schema_changes(); + + + $this->db->commitTrans(__METHOD__); + + return('Upgrade complete'); + }//end run_upgrade() + //========================================================================= + + + + //========================================================================= + private function run_schema_changes() { + + $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); + $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA7.sql'); + + $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". + base64_encode($this->fsObj->read($this->lastSQLFile)); + $this->logsObj->log_by_class($details, 'system'); + + }//end run_schema_changes() + //========================================================================= +} + +?> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-01-07 18:20:20
|
Revision: 6 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=6&view=rev Author: crazedsanity Date: 2009-01-07 18:20:14 +0000 (Wed, 07 Jan 2009) Log Message: ----------- Current version of the upgrade class. Example upgrade scripts & config pending. Added Paths: ----------- trunk/0.1/CREDITS trunk/0.1/LICENSE trunk/0.1/VERSION trunk/0.1/upgradeClass.php Added: trunk/0.1/CREDITS =================================================================== --- trunk/0.1/CREDITS (rev 0) +++ trunk/0.1/CREDITS 2009-01-07 18:20:14 UTC (rev 6) @@ -0,0 +1,3 @@ + +Lead Developer: Dan Falconer (cra...@us...) + Added: trunk/0.1/LICENSE =================================================================== --- trunk/0.1/LICENSE (rev 0) +++ trunk/0.1/LICENSE 2009-01-07 18:20:14 UTC (rev 6) @@ -0,0 +1,291 @@ +NOTE: a full HTML version of this license can be found at: +http://www.opensource.org/licenses/gpl-license.php + +It has been reproduced below without any HTML. +========================================================================== + +The GNU General Public License (GPL) + +Version 2, June 1991 + + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS Added: trunk/0.1/VERSION =================================================================== --- trunk/0.1/VERSION (rev 0) +++ trunk/0.1/VERSION 2009-01-07 18:20:14 UTC (rev 6) @@ -0,0 +1,6 @@ +## Stores the current version of the cs-versionparse system, and it's source. +## Please do NOT modify this file. + +VERSION: 0.1 +PROJECT: cs-webdbupgrade +$HeadURL$ \ No newline at end of file Property changes on: trunk/0.1/VERSION ___________________________________________________________________ Added: svn:keywords + HeadURL Added: trunk/0.1/upgradeClass.php =================================================================== --- trunk/0.1/upgradeClass.php (rev 0) +++ trunk/0.1/upgradeClass.php 2009-01-07 18:20:14 UTC (rev 6) @@ -0,0 +1,902 @@ +<?php +/* + * Created on Jul 2, 2007 + * + * SVN INFORMATION::: + * ------------------ + * SVN Signature::::::: $Id: upgradeClass.php 894 2008-05-16 03:26:15Z crazedsanity $ + * Last Author::::::::: $Author: crazedsanity $ + * Current Revision:::: $Revision: 894 $ + * Repository Location: $HeadURL: https://cs-project.svn.sourceforge.net/svnroot/cs-project/trunk/1.2/lib/upgradeClass.php $ + * Last Updated:::::::: $Date: 2008-05-15 22:26:15 -0500 (Thu, 15 May 2008) $ + * + */ + +class upgrade { + + private $fsObj; + private $gfObj; + private $config = NULL; + protected $db; + protected $logsObj; + + private $versionFileVersion = NULL; + private $configVersion = NULL; + private $databaseVersion = NULL; + + private $mainConfig = NULL; + + /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in + * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ + private $suffixList = array( + 'ALPHA', //very unstable + 'BETA', //kinda unstable, but probably useable + 'RC' //all known bugs fixed, searching for unknown ones + ); + + //========================================================================= + public function __construct() { + $this->fsObj = new cs_fileSystemClass(dirname(__FILE__) .'/../'); + $this->gfObj = new cs_globalFunctions; + $this->gfObj->debugPrintOpt = DEBUGPRINTOPT; + clearstatcache(); + + $this->db = new cs_phpDB; + $this->db->connect(get_config_db_params()); + + $this->logsObj = new logsClass($this->db, "Upgrade"); + + //define some things for upgrades. + define("UPGRADE_LOCKFILE", dirname(__FILE__) ."/../UPGRADING_VERSION"); //relative to the directory beneath lib. + define("UPGRADE_DIR", dirname(__FILE__) ."/../upgrade"); + }//end __construct() + //========================================================================= + + + + //========================================================================= + /** + * Where everything begins: checks if the version held in config.xml lines-up + * with the one in the VERSION file; if it does, then it checks the version + * listed in the database. + */ + public function check_versions($performUpgrade=TRUE) { + //first, check that all files exist. + $retval = NULL; + + //check to see if the lock files for upgrading exist. + if($this->upgrade_in_progress()) { + throw new exception(__METHOD__ .": upgrade in progress"); + } + elseif(!file_exists(CONFIG_FILE_LOCATION)) { + throw new exception(__METHOD__ .": config.xml file missing"); + } + elseif(!file_exists(dirname(__FILE__) .'/../VERSION')) { + throw new exception(__METHOD__ .": VERSION file missing"); + } + elseif(!file_exists(dirname(__FILE__) .'/../upgrade/upgrade.xml')) { + throw new exception(__METHOD__ .": upgrade.xml file missing"); + } + else { + //okay, all files present: check the version in the VERSION file. + $versionFileContents = $this->read_version_file(); + + //now read data from the config. + $versionFromConfig = $this->read_config_version(); + + $versionsDiffer = TRUE; + $retval = FALSE; + if($versionFileContents == $versionFromConfig) { + $versionConflict = $this->check_for_version_conflict(); + if($versionConflict === 0) { + //all is good: no problems detected (all things match-up). + $versionsDiffer=FALSE; + $performUpgrade = FALSE; + } + else { + // + $versionsDiffer = TRUE; + } + } + + if($versionsDiffer == TRUE && $performUpgrade === TRUE) { + //reset the return value, so it'll default to failure until we say otherwise. + $retval = NULL; + + //Perform the upgrade! + $this->perform_upgrade(); + } + } + + return($retval); + }//end check_versions() + //========================================================================= + + + + //========================================================================= + protected function read_version_file() { + $retval = NULL; + + //okay, all files present: check the version in the VERSION file. + $versionFileContents = $this->fsObj->read('VERSION'); + + //okay, rip it into bits. NOTE: this *depends* on "VERSION: " being on the third line. + $lines = explode("\n", $versionFileContents); + $versionLine = $lines[2]; + if(preg_match('/^VERSION: /', $versionLine)) { + + $retval = trim(preg_replace('/VERSION: /', '', $versionLine)); + $this->versionFileVersion = $retval; + } + else { + throw new exception(__METHOD__ .": could not find VERSION data"); + } + + return($retval); + }//end read_version_file() + //========================================================================= + + + + //========================================================================= + private function read_config_version() { + $configObj = new config(); + $config = $configObj->read_config_file(FALSE); + $this->mainConfig = $config; + $retval = NULL; + + if(!is_array($config) || !count($config)) { + throw new exception(__METHOD__ .": no configuration data available (missing config file?)"); + } + else { + //now, let's see if there's a "version_string" index. + if(isset($config['VERSION_STRING']) && strlen($config['VERSION_STRING'])) { + $retval = $config['VERSION_STRING']; + } + else { + throw new exception(__METHOD__ .": invalid version string found (". $config['VERSION_STRING'] .")"); + } + } + + $this->configVersion = $retval; + return($retval); + }//end read_config_version() + //========================================================================= + + + + //========================================================================= + /** + * Read information from our config file, so we know what to expect. + */ + private function read_upgrade_config_file() { + $xmlString = $this->fsObj->read("upgrade/upgrade.xml"); + + //parse the file. + $xmlParser = new xmlParser($xmlString); + + $config = $xmlParser->get_tree(TRUE); + $this->config = $config['UPGRADE']; + }//end read_upgrade_config_file() + //========================================================================= + + + + //========================================================================= + private function perform_upgrade() { + //make sure there's not already a lockfile. + if($this->upgrade_in_progress()) { + //ew. Can't upgrade. + throw new exception(__METHOD__ .": upgrade already in progress...????"); + } + else { + $lockConfig = $this->upgrade_in_progress(TRUE); + $this->fsObj->cd("/"); + + //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists(). + if($lockConfig === 0) { + //can't create the lockfile. Die. + throw new exception(__METHOD__ .": failed to set 'upgrade in progress'"); + } + else { + $this->gfObj->debug_print(__METHOD__ .": result of setting 'upgrade in progress': (". $lockConfig .")"); + + //check to see if our config file is writable. + if(!$this->fsObj->is_writable(CONFIG_FILE_LOCATION)) { + throw new exception(__METHOD__ .": config file isn't writable!"); + } + + //push data into our internal "config" array. + $this->read_upgrade_config_file(); + $this->get_database_version(); + + //check for version conflicts. + $this->check_for_version_conflict(); + + $upgradeList = $this->get_upgrade_list(); + + $i=0; + $this->gfObj->debug_print(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion .")..."); + $this->db->beginTrans(__METHOD__); + foreach($upgradeList as $fromVersion=>$toVersion) { + + $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; + $this->gfObj->debug_print($details); + $this->logsObj->log_by_class($details, 'system'); + $this->do_single_upgrade($fromVersion); + $this->get_database_version(); + $i++; + + $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; + $this->gfObj->debug_print($details); + $this->logsObj->log_by_class($details, 'system'); + } + + if($this->databaseVersion == $this->versionFileVersion) { + $this->gfObj->debug_print(__METHOD__ .": finished upgrading after performing (". $i .") upgrades!!!"); + $this->newVersion = $this->databaseVersion; + } + else { + throw new exception(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); + } + $this->update_config_file('version_string', $this->newVersion); + $this->update_config_file('workingonit', "0"); + + $this->db->commitTrans(); + } + } + }//end perform_upgrade() + //========================================================================= + + + + //========================================================================= + public function upgrade_in_progress($makeItSo=FALSE) { + $retval = FALSE; + if($makeItSo === TRUE) { + $this->get_database_version(); + $details = 'Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s'); + $this->update_config_file('WORKINGONIT', $details); + $retval = TRUE; + } + elseif(preg_match('/^upgrade/i', $this->mainConfig['WORKINGONIT'])) { + $retval = TRUE; + } + + return($retval); + }//end upgrade_in_progress() + //========================================================================= + + + + //========================================================================= + public function parse_version_string($versionString) { + if(is_null($versionString) || !strlen($versionString)) { + throw new exception(__METHOD__ .": invalid version string ($versionString)"); + } + $tmp = explode('.', $versionString); + + //NOTE: the order of the array MUST be major, then minor, then maintenance, so is_higher_version() can check it easily. + $retval = array( + 'version_string' => $versionString, + 'version_major' => $tmp[0], + 'version_minor' => $tmp[1] + ); + if(count($tmp) == 3) { + $retval['version_maintenance'] = $tmp[2]; + } + else { + $retval['version_maintenance'] = "0"; + } + + //check for a prefix or a suffix. + if(preg_match('/-/', $versionString)) { + //make sure there's only ONE dash. + $tmp = explode('-', $versionString); + if(count($tmp) == 2) { + if(preg_match('/-/', $retval['version_major'])) { + //example: BETA-3.3.0 + + throw new exception(__METHOD__ .": versions that contain prefixes cannot be upgraded"); + + #$tmp = explode('-', $retval['version_major']); + #$retval['version_major'] = $tmp[1]; + #$retval['prefix'] = $tmp[0]; + } + elseif(preg_match('/-/', $retval['version_maintenance'])) { + //example: 1.0.0-ALPHA1 + $tmp = explode('-', $retval['version_maintenance']); + $retval['version_maintenance'] = $tmp[0]; + $retval['version_suffix'] = $tmp[1]; + } + else { + throw new exception(__METHOD__ .": invalid location of prefix/suffix in (". $versionString .")"); + } + } + else { + throw new exception(__METHOD__ .": too many dashes in version string (". $versionString .")"); + } + } + else { + $retval['version_suffix'] = ""; + } + + return($retval); + }//end parse_version_string() + //========================================================================= + + + + //========================================================================= + /** + * Checks for issues with versions. + * 0 == No problems. + * (string) == upgrade applicable (indicates "major"/"minor"/"maintenance"). + * NULL == encountered error + */ + private function check_for_version_conflict() { + //set a default return... + $retval = NULL; + + //call to ensure files have been processed. + #$this->check_versions(FALSE); + $this->read_config_version(); + $this->read_version_file(); + $configVersion = NULL; + + //parse the version strings. + if(strlen($this->configVersion)) { + $configVersion = $this->parse_version_string($this->configVersion); + } + $versionFile = $this->parse_version_string($this->versionFileVersion); + + + $dbVersion = $this->get_database_version(); + $versionFileData = $this->parse_version_string($this->versionFileVersion); + + if($versionFileData['version_string'] == $dbVersion['version_string']) { + //good to go: no upgrade needed. + $retval = 0; + } + else { + //NOTE: this seems very convoluted, but it works. + if($versionFileData['version_major'] == $dbVersion['version_major']) { + if($versionFileData['version_minor'] == $dbVersion['version_minor']) { + if($versionFileData['version_maintenance'] == $dbVersion['version_maintenance']) { + if($versionFileData['version_suffix'] == $dbVersion['version_suffix']) { + throw new exception(__METHOD__ .": no version upgrade detected, but version strings don't match (versionFile=". $versionFileData['version_string'] .", dbVersion=". $dbVersion['version_string'] .")"); + } + else { + $retval = "suffix"; + } + } + elseif($versionFileData['version_maintenance'] > $dbVersion['version_maintenance']) { + $retval = "maintenance"; + } + else { + throw new exception(__METHOD__ .": downgrading from maintenance versions is unsupported"); + } + } + elseif($versionFileData['version_minor'] > $dbVersion['version_minor']) { + $retval = "minor"; + } + else { + throw new exception(__METHOD__ .": downgrading minor versions is unsupported"); + } + } + elseif($versionFileData['version_major'] > $dbVersion['version_major']) { + $retval = "major"; + } + else { + throw new exception(__METHOD__ .": downgrading major versions is unsupported"); + } + } + + if(!is_null($retval) && $retval !== 0) { + $this->gfObj->debug_print(__METHOD__ .": upgrading ". $retval ." versions, from (". $this->databaseVersion .") to (". $this->versionFileVersion .")"); + } + + return($retval); + }//end check_for_version_conflict() + //========================================================================= + + + + //========================================================================= + private function get_database_version() { + //create a database object & attempt to read the database version. + + if(!is_object($this->db) || get_class($this->db) != 'cs_phpDB') { + $this->db = new cs_phpDB; + $this->db->connect(get_config_db_params()); + } + + $sql = "SELECT " . + "internal_data_get_value('version_string') AS version_string, " . + "internal_data_get_value('version_major') AS version_major, " . + "internal_data_get_value('version_minor') AS version_minor, " . + "internal_data_get_value('version_maintenance') AS version_maintenance, " . + "internal_data_get_value('version_suffix') AS version_suffix"; + $numrows = $this->db->exec($sql); + $dberror = $this->db->errorMsg(); + + if(strlen($dberror) || $numrows != 1) { + //fail. + throw new exception(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror); + } + else { + $data = $this->db->farray_fieldnames(); + $this->databaseVersion = $data['version_string']; + $retval = $this->parse_version_string($data['version_string']); + } + + return($retval); + }//end get_database_version() + //========================================================================= + + + + //========================================================================= + private function do_single_upgrade($targetVersion) { + //Use the "matching_syntax" data in the upgrade.xml file to determine the filename. + $versionIndex = "V". $targetVersion; + $this->gfObj->debug_print(__METHOD__ .": versionIndex=(". $versionIndex ."), config MATCHING::: ". $this->gfObj->debug_print($this->config['MATCHING'],0)); + if(!isset($this->config['MATCHING'][$versionIndex])) { + //version-only upgrade. + $this->update_database_version($this->versionFileVersion); + $this->newVersion = $this->versionFileVersion; + $this->gfObj->debug_print(__METHOD__ .": doing version-only upgrade..."); + } + else { + $scriptIndex = $versionIndex; + + $upgradeData = $this->config['MATCHING'][$versionIndex]; + + if(isset($upgradeData['TARGET_VERSION']) && count($upgradeData) > 1) { + $this->newVersion = $upgradeData['TARGET_VERSION']; + if(isset($upgradeData['SCRIPT_NAME']) && isset($upgradeData['CLASS_NAME']) && isset($upgradeData['CALL_METHOD'])) { + //good to go; it's a scripted upgrade. + $this->do_scripted_upgrade($upgradeData); + $this->update_database_version($upgradeData['TARGET_VERSION']); + } + else { + throw new exception(__METHOD__ .": not enough information to run scripted upgrade for ". $versionIndex); + } + } + else { + throw new exception(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); + } + } + $this->gfObj->debug_print(__METHOD__ .": done... "); + }//end do_single_upgrade() + //========================================================================= + + + + //========================================================================= + /** + * Updates information that's stored in the database, internal to cs-project, + * so the version there is consistent with all the others. + */ + protected function update_database_version($newVersionString) { + $this->gfObj->debug_print(__METHOD__ .": setting (". $newVersionString .")"); + $versionArr = $this->parse_version_string($newVersionString); + + $queryArr = array(); + foreach($versionArr as $index=>$value) { + $queryArr[$index] = "SELECT internal_data_set_value('". $index ."', '". $value ."');"; + } + + $retval = NULL; + foreach($queryArr as $name=>$sql) { + if($this->run_sql($sql, 1)) { + $retval++; + } + } + + //okay, now check that the version string matches the updated bits. + if(!$this->check_database_version($this->newVersion)) { + throw new exception(__METHOD__ .": database version information is invalid: (". $this->newVersion .")"); + } + + return($retval); + + }//end update_database_version() + //========================================================================= + + + + //========================================================================= + /** + * Checks consistency of version information in the database, and optionally + * against a given version string. + */ + private function check_database_version($checkThisVersion=NULL) { + //retrieve the internal version information. + $sql = "select internal_data_get_value('version_string') as version_string, (" . + "internal_data_get_value('version_major') || '.' || " . + "internal_data_get_value('version_minor') || '.' || " . + "internal_data_get_value('version_maintenance')) as check_version, " . + "internal_data_get_value('version_suffix') AS version_suffix"; + + $retval = NULL; + if($this->run_sql($sql,1)) { + $data = $this->db->farray_fieldnames(); + $versionString = $data['version_string']; + $checkVersion = $data['check_version']; + + if(strlen($data['version_suffix'])) { + //the version string already would have this, but the checked version wouldn't. + $checkVersion .= "-". $data['version_suffix']; + } + + if($versionString == $checkVersion) { + $retval = TRUE; + } + else { + $retval = FALSE; + } + } + else { + $retval = FALSE; + } + + if(!$retval) { + $this->gfObj->debug_print($data); + $this->gfObj->debug_print(__METHOD__ .": versionString=(". $versionString ."), checkVersion=(". $checkVersion .")"); + } + + return($retval); + + }//end check_database_version() + //========================================================================= + + + + //========================================================================= + private function do_scripted_upgrade(array $upgradeData) { + $myConfigFile = $upgradeData['SCRIPT_NAME']; + + $this->gfObj->debug_print(__METHOD__ .": script name=(". $myConfigFile .")"); + + //we've got the filename, see if it exists. + $fileName = UPGRADE_DIR .'/'. $myConfigFile; + if(file_exists($fileName)) { + $this->gfObj->debug_print(__METHOD__ .": file exists... "); + $createClassName = $upgradeData['CLASS_NAME']; + $classUpgradeMethod = $upgradeData['CALL_METHOD']; + require_once($fileName); + + //now check to see that the class we need actually exists. + if(class_exists($createClassName)) { + $upgradeObj = new $createClassName($this->db); + if(method_exists($upgradeObj, $classUpgradeMethod)) { + $upgradeResult = $upgradeObj->$classUpgradeMethod(); + $this->gfObj->debug_print(__METHOD__ .": finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")"); + } + else { + throw new exception(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod + ."), unable to perform upgrade "); + } + } + else { + throw new exception(__METHOD__ .": unable to locate upgrade class name (". $createClassName .")"); + } + } + else { + throw new exception(__METHOD__ .": upgrade filename (". $fileName .") does not exist"); + } + }//end do_scripted_upgrade() + //========================================================================= + + + + //========================================================================= + protected function run_sql($sql, $expectedNumrows=1) { + if(!$this->db->is_connected()) { + $this->db->connect(get_config_db_params()); + } + $numrows = $this->db->exec($sql); + $dberror = $this->db->errorMsg(); + + if(strlen($dberror)) { + $details = "DBERROR::: ". $dberror; + throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: ". $details); + } + elseif(!is_null($expectedNumrows) && $numrows != $expectedNumrows) { + throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: " . + "rows affected didn't match expectation (". $numrows ." != ". $expectedNumrows .")"); + } + elseif(is_null($expectedNumrows) && $numrows < 1) { + throw new exception(__METHOD__ .": SQL FAILED::: ". $sql ."\n\nDETAILS: " . + "invalid number of rows affected (". $numrows .")"); + } + else { + $retval = TRUE; + } + + return($retval); + }//end run_sql() + //========================================================================= + + + + //========================================================================= + private function update_config_file($index, $value) { + $gf = new cs_globalFunctions; + $myConfigFile = CONFIG_FILE_LOCATION; + $fs = new cs_fileSystemClass(dirname(__FILE__) .'/../'); + $xmlParser = new XMLParser($fs->read($myConfigFile)); + $xmlCreator = new XMLCreator; + $xmlCreator->load_xmlparser_data($xmlParser); + + //update the given index. + $xmlCreator->add_tag($index, $value, $xmlParser->get_attribute('/CONFIG/'. strtoupper($index))); + $this->mainConfig[strtoupper($index)] = $value; + + $xmlString = $xmlCreator->create_xml_string(); + + //truncate the file, to avoid problems with extra data at the end... + $fs->closeFile(); + $fs->create_file($myConfigFile,TRUE); + $fs->openFile($myConfigFile); + + //now write the new configuration. + $fs->write($xmlString, $myConfigFile); + }//end update_config_file() + //========================================================================= + + + + //========================================================================= + protected function get_num_users_to_convert() { + + $retval = 0; + try { + //if this generates an error, there are no users... + $this->run_sql("SELECT internal_data_get_value('users_to_convert')"); + $data = $this->db->farray(); + $retval = $data[0]; + } + catch(exception $e) { + $this->gfObj->debug_print(__METHOD__ .": failed to retrieve users to convert: "); + } + + return($retval); + + }//end get_num_users_to_convert() + //========================================================================= + + + + //========================================================================= + protected function update_num_users_to_convert() { + $retval = $this->run_sql("SELECT internal_data_set_value('users_to_convert', (select count(*) FROM user_table WHERE length(password) != 32))"); + return($retval); + }//end update_num_users_to_convert() + //========================================================================= + + + + //========================================================================= + protected function is_higher_version($version, $checkIfHigher) { + $retval = FALSE; + if(!is_string($version) || !is_string($checkIfHigher)) { + throw new exception(__METHOD__ .": didn't get strings... ". debug_print(func_get_args(),0)); + } + elseif($version == $checkIfHigher) { + $retval = FALSE; + } + else { + $curVersionArr = $this->parse_version_string($version); + $checkVersionArr = $this->parse_version_string($checkIfHigher); + + unset($curVersionArr['version_string'], $checkVersionArr['version_string']); + + + $curVersionSuffix = $curVersionArr['version_suffix']; + $checkVersionSuffix = $checkVersionArr['version_suffix']; + + + unset($curVersionArr['version_suffix']); + + foreach($curVersionArr as $index=>$versionNumber) { + $checkThis = $checkVersionArr[$index]; + + if(is_numeric($checkThis) && is_numeric($versionNumber)) { + //set them as integers. + settype($versionNumber, 'int'); + settype($checkThis, 'int'); + + if($checkThis > $versionNumber) { + $retval = TRUE; + break; + } + elseif($checkThis == $versionNumber) { + //they're equal... + } + else { + //TODO: should there maybe be an option to throw an exception (freak out) here? + debug_print(__METHOD__ .": while checking ". $index .", realized the new version (". $checkIfHigher .") is LOWER than current (". $version .")",1); + } + } + else { + throw new exception(__METHOD__ .": ". $index ." is not numeric in one of the strings " . + "(versionNumber=". $versionNumber .", checkThis=". $checkThis .")"); + } + } + + //now deal with those damnable suffixes, but only if the versions are so far identical: if + // the "$checkIfHigher" is actually higher, don't bother (i.e. suffixes don't matter when + // we already know there's a major, minor, or maintenance version that's also higher. + if($retval === FALSE) { + $this->gfObj->debug_print(__METHOD__ .": checking suffixes... "); + //EXAMPLE: $version="1.0.0-BETA3", $checkIfHigher="1.1.0" + // Moving from a non-suffixed version to a suffixed version isn't supported, but the inverse is: + // i.e. (1.0.0-BETA3 to 1.0.0) is okay, but (1.0.0 to 1.0.0-BETA3) is NOT. + // Also: (1.0.0-BETA3 to 1.0.0-BETA4) is okay, but (1.0.0-BETA4 to 1.0.0-BETA3) is NOT. + if(strlen($curVersionSuffix) && strlen($checkVersionSuffix) && $curVersionSuffix == $checkVersionSuffix) { + //matching suffixes. + $this->gfObj->debug_print(__METHOD__ .": suffixes match"); + } + elseif(strlen($curVersionSuffix) || strlen($checkVersionSuffix)) { + //we know the suffixes are there and DO match. + if(strlen($curVersionSuffix) && strlen($checkVersionSuffix)) { + //okay, here's where we do some crazy things... + $curVersionData = $this->parse_suffix($curVersionSuffix); + $checkVersionData = $this->parse_suffix($checkVersionSuffix); + + if($curVersionData['type'] == $checkVersionData['type']) { + $this->gfObj->debug_print(__METHOD__ .": got the same type..."); + //got the same suffix type (like "BETA"), check the number. + if($checkVersionData['number'] > $curVersionData['number']) { + $this->gfObj->debug_print(__METHOD__ .": new version's suffix number higher than current... "); + $retval = TRUE; + } + elseif($checkVersionData['number'] == $curVersionData['number']) { + $this->gfObj->debug_print(__METHOD__ .": new version's suffix number is EQUAL TO current... "); + $retval = FALSE; + } + else { + //umm... they're identical??? LOGIC HAS FAILED ME ALTOGETHER!!! + $this->gfObj->debug_print(__METHOD__ .": new version's suffix number is LESS THAN current... "); + $retval = FALSE; + } + } + else { + //not the same suffix... see if the new one is higher. + $suffixValues = array_flip($this->suffixList); + if($suffixValues[$checkVersionData['type']] > $suffixValues[$curVersionData['type']]) { + $retval = TRUE; + } + else { + $this->gfObj->debug_print(__METHOD__ .": current suffix type is higher... "); + } + } + + } + elseif(strlen($curVersionSuffix) && !strlen($checkVersionSuffix)) { + //i.e. "1.0.0-BETA1" to "1.0.0" --->>> OKAY! + $retval = TRUE; + } + elseif(!strlen($curVersionSuffix) && strlen($checkVersionSuffix)) { + //i.e. "1.0.0" to "1.0.0-BETA1" --->>> NOT ACCEPTABLE! + $this->gfObj->debug_print(__METHOD__ .": from (". $version .") to (". $checkIfHigher .") isn't acceptable...?"); + } + } + else { + $this->gfObj->debug_print(__METHOD__ .": no suffix to care about"); + } + } + } + + $this->gfObj->debug_print(__METHOD__ .": ('". $version ."', '". $checkIfHigher ."') retval=(". $retval .")", 1); + + return($retval); + + }//end is_higher_version() + //========================================================================= + + + + //========================================================================= + /** + * Determines list of upgrades to perform. + * + * If the current version is 1.0.1, the version file is 1.0.5, and there's a + * scripted upgrade at 1.0.4, this will update the database version to 1.0.3, + * run the scripted upgrade at 1.0.4, then update the database version to + * 1.0.5 (keeps from skipping the upgrade at 1.0.4) + */ + private function get_upgrade_list() { + $this->get_database_version(); + $dbVersion = $this->databaseVersion; + $newVersion = $this->versionFileVersion; + + $retval = array(); + if(!$this->is_higher_version($dbVersion, $newVersion)) { + throw new exception(__METHOD__ .": version (". $newVersion .") isn't higher than (". $dbVersion .")... something is broken"); + } + elseif(is_array($this->config['MATCHING'])) { + $lastVersion = $dbVersion; + foreach($this->config['MATCHING'] as $matchVersion=>$data) { + + $matchVersion = preg_replace('/^V/', '', $matchVersion); + if($matchVersion == $data['TARGET_VERSION']) { + throw new exception(__METHOD__ .": detected invalid TARGET_VERSION in (". $matchVersion ."): make sure TARGET_VERSION is higher than matching!"); + } + elseif($this->databaseVersion == $matchVersion || $this->is_higher_version($this->databaseVersion, $matchVersion)) { + //the version in MATCHING is equal to or HIGHER than our database version... make sure it is NOT + // higher than the version in our versionFile. + if(!$this->is_higher_version($this->versionFileVersion, $matchVersion)) { + if(!count($retval) && $matchVersion != $this->databaseVersion) { + $retval[$this->databaseVersion] = $matchVersion; + } + //the MATCHING version is NOT higher than the version file's version, looks ok. + $this->gfObj->debug_print(__METHOD__ .": adding (". $matchVersion .")"); + $lastVersion = $data['TARGET_VERSION']; + $retval[$matchVersion] = $data['TARGET_VERSION']; + } + else { + $this->gfObj->debug_print(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")"); + } + } + else { + $this->gfObj->debug_print(__METHOD__ .": SKIPPING (". $matchVersion .")"); + } + } + + if($lastVersion !== $newVersion && (!isset($retval[$lastVersion]) || $retval[$lastVersion] != $newVersion)) { + $this->gfObj->debug_print(__METHOD__ .": <b>ALSO (". $lastVersion .") => (". $newVersion .")</b>"); + $retval[$lastVersion] = $newVersion; + } + } + else { + //no intermediary upgrades: just pass back the latest version. + $this->gfObj->debug_print(__METHOD__ .": no intermediary upgrades"); + $retval[$dbVersion] = $this->versionFileVersion; + } + + return($retval); + + }//end get_upgrade_list() + //========================================================================= + + + + //========================================================================= + protected function parse_suffix($suffix) { + $retval = NULL; + if(strlen($suffix)) { + //determine what kind it is. + foreach($this->suffixList as $type) { + if(preg_match('/^'. $type .'/', $suffix)) { + $checkThis = preg_replace('/^'. $type .'/', '', $suffix); + if(strlen($checkThis) && is_numeric($checkThis)) { + //oooh... it's something like "BETA3" + $retval = array( + 'type' => $type, + 'number' => $checkThis + ); + } + else { + throw new exception(__METHOD__ .": invalid suffix (". $suffix .")"); + } + break; + } + } + } + else { + throw new exception(__METHOD__ .": invalid suffix (". $suffix .")"); + } + + return($retval); + }//end parse_suffix() + //========================================================================= + + +}//end upgrade{} + + +?> \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-01-07 18:12:33
|
Revision: 5 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=5&view=rev Author: crazedsanity Date: 2009-01-07 18:12:27 +0000 (Wed, 07 Jan 2009) Log Message: ----------- Exclude Eclipse .project files. Property Changed: ---------------- trunk/0.1/ Property changes on: trunk/0.1 ___________________________________________________________________ Added: svn:ignore + .project This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-01-02 19:45:55
|
Revision: 4 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=4&view=rev Author: crazedsanity Date: 2009-01-02 19:45:50 +0000 (Fri, 02 Jan 2009) Log Message: ----------- Initial version. Added Paths: ----------- trunk/0.1/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-01-02 19:43:23
|
Revision: 3 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=3&view=rev Author: crazedsanity Date: 2009-01-02 19:43:18 +0000 (Fri, 02 Jan 2009) Log Message: ----------- Holds publicly-available releases (subfolders indicate major.minor version) Added Paths: ----------- releases/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-01-02 19:41:25
|
Revision: 2 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=2&view=rev Author: crazedsanity Date: 2009-01-02 19:41:21 +0000 (Fri, 02 Jan 2009) Log Message: ----------- Folder to hold branch versions of a trunk folder. Added Paths: ----------- branches/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-01-02 19:40:51
|
Revision: 1 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=1&view=rev Author: crazedsanity Date: 2009-01-02 19:40:46 +0000 (Fri, 02 Jan 2009) Log Message: ----------- Bleeding-edge development; sub-folders indicate existing or new version for which the development is for. Added Paths: ----------- trunk/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |