diff options
| author | Max Kremmel <xing@synapse.plus.com> | 2008-10-24 20:22:18 +0000 |
|---|---|---|
| committer | Max Kremmel <xing@synapse.plus.com> | 2008-10-24 20:22:18 +0000 |
| commit | 43286392b5f6f14f399ec330fc7569aafe42bbc9 (patch) | |
| tree | c6be61dc0954eeb9a9727794cd9e0617ae900221 /BitInstaller.php | |
| parent | d373d0dc2c3b13485ec16d582062f63b58e4a5dc (diff) | |
| download | install-43286392b5f6f14f399ec330fc7569aafe42bbc9.tar.gz install-43286392b5f6f14f399ec330fc7569aafe42bbc9.tar.bz2 install-43286392b5f6f14f399ec330fc7569aafe42bbc9.zip | |
lots more work towards package based upgrades. basics all working now. see wiki test upgrade script for details.
Diffstat (limited to 'BitInstaller.php')
| -rw-r--r-- | BitInstaller.php | 365 |
1 files changed, 217 insertions, 148 deletions
diff --git a/BitInstaller.php b/BitInstaller.php index d439036..3105053 100644 --- a/BitInstaller.php +++ b/BitInstaller.php @@ -1,6 +1,6 @@ <?php /** - * @version $Header: /cvsroot/bitweaver/_bit_install/BitInstaller.php,v 1.32 2008/10/23 19:57:07 squareing Exp $ + * @version $Header: /cvsroot/bitweaver/_bit_install/BitInstaller.php,v 1.33 2008/10/24 20:22:18 squareing Exp $ * @package install */ @@ -9,6 +9,8 @@ */ class BitInstaller extends BitSystem { + var $mPackageUpgrades = array(); + /** * Initiolize BitInstaller * @access public @@ -45,44 +47,64 @@ class BitInstaller extends BitSystem { /** * registerPackageUpgrade * - * @param array $pPackage - * @param array $pVersion - * @param array $pDatadict + * @param array $pParams + * @param array $pUpgradeHash * @access public * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure */ - function registerPackageUpgrade( $pPackage, $pVersion, $pDatadict ) { - if( !empty( $pPackage ) && $this->validateVersion( $pVersion ) && !empty( $pDatadict )) { - if( empty( $this->mPackageUpgrades[$pPackage][$pVersion] )) { - $this->mPackageUpgrades[$pPackage][$pVersion]['datadict'] = $pDatadict; - // ensure all upgrades are in ascending order that the upgrade can do its thing easily. - uksort( $this->mPackageUpgrades[$pPackage], 'upgrade_version_sort' ); - } else { - vd( "Please make sure you use a unique version number to register your new database changes." ); - } - } else { - vd( "Please make sure you use a valid version number." ); + function registerPackageUpgrade( $pParams, $pUpgradeHash ) { + if( $this->verifyPackageUpgrade( $pParams ) && !empty( $pUpgradeHash )) { + $this->mPackageUpgrades[$pParams['package']][$pParams['version']] = $pParams; + $this->mPackageUpgrades[$pParams['package']][$pParams['version']]['upgrade'] = $pUpgradeHash; + // ensure all upgrades are in ascending order + uksort( $this->mPackageUpgrades[$pParams['package']], 'upgrade_version_sort' ); } } /** - * registerDependency + * verifyPackageUpgrade * - * @param array $pPackage Package that requires the dependency - * @param array $pVersion Version of the package that requires the dependency - * @param array $pDepPackage package dependency required - * @param array $pDepVersion Version of the package that is required + * @param array $pParams + * @param array $pCheckDesc * @access public * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure */ - function registerPackageDependencies( $pPackage, $pVersion, $pDepHash ) { - if( !empty( $pPackage ) && $this->validateVersion( $pVersion ) && !empty( $pDepHash ) && is_array( $pDepHash )) { + function verifyPackageUpgrade( &$pParams, $pCheckDesc = TRUE ) { + if( empty( $pParams['package'] )) { + $this->mErrors['package'] = "Please provide a valid package name."; + } + + if( empty( $pParams['version'] ) || !$this->validateVersion( $pParams['version'] )) { + $this->mErrors['package'] = "Please provide a valid version number."; + } elseif( empty( $this->mErrors ) && !empty( $this->mPackageUpgrades[$pParams['package']][$pParams['version']] )) { + $this->mErrors['package'] = "Please make sure you use a unique version number to register your new database changes."; + } + + if( $pCheckDesc && empty( $pParams['description'] )) { + $this->mErrors['package'] = "Please add a brief description of what this upgrade is all about."; + } + + // since this should only show up when devs are working, we'll simply display the output: + if( !empty( $this->mErrors )) { + var_dump( $this->mErrors ); + } + + return( count( $this->mErrors ) == 0 ); + } + + /** + * registerPackageDependencies + * + * @param array $pParams + * @param array $pDepHash + * @access public + * @return void + */ + function registerPackageDependencies( $pParams, $pDepHash ) { + if( !empty( $pParams['package'] ) && !empty( $pParams['version'] ) && $this->validateVersion( $pParams['version'] ) && !empty( $pDepHash ) && is_array( $pDepHash )) { foreach( $pDepHash as $pkg => $version ) { if( $this->validateVersion( $version )) { - $this->mPackageDependencies[$pPackage][$pVersion]['dependencies'] = array( - 'dependency' => $pkg, - 'minversion' => $version, - ); + $this->mPackageDependencies[$pParams['package']][$pParams['version']]['dependencies'] = $pDepHash; } else { vd( "Please make sure you use a valid version number." ); } @@ -92,6 +114,11 @@ class BitInstaller extends BitSystem { function verifyDependencies() { // anyone feel like it? + // thoughts: + // - get version of installed packages and merge them with the ones that are about to be installed + // - check if all dependencies will be met at the end of the installation + // - is there a need to specify in which order the installs need to be performed? + return TRUE; } /** @@ -225,177 +252,218 @@ class BitInstaller extends BitSystem { /** * upgradePackage * - * @param array $package + * @param array $pPackage + * @access public + * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure + */ + function upgradePackage( $pPackage ) { + if( !empty( $pPackage ) && !empty( $this->mUpgrades[$pPackage] )) { + return( $this->applyUpgrade( $pPackage, $this->mUpgrades[$pPackage] )); + } + } + + /** + * upgradePackageVersion + * + * @param array $pPackage + * @param array $pVersion * @access public * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure */ - function upgradePackage( $package ) { + function upgradePackageVersions( $pPackage ) { + if( !empty( $pPackage ) && !empty( $this->mPackageUpgrades[$pPackage] )) { + // make sure everything is in the right order + uksort( $this->mPackageUpgrades[$pPackage], 'upgrade_version_sort' ); + + foreach( $this->mPackageUpgrades[$pPackage] as $version => $package ) { + $errors[$version] = $this->applyUpgrade( $pPackage, $this->mPackageUpgrades[$pPackage][$version]['upgrade'] ); + if( !empty( $errors[$version] )) { + return $errors; + } else { + // if the upgrade ended without incidence, we store the package version + // this way we store the version after every successful step to avoid duplicate upgrades + $this->storeVersion( $pPackage, $version ); + } + } + } + + return NULL; + } + + /** + * applyUpgrade + * + * @param array $pPackage + * @param array $pUpgradeHash + * @access public + * @return empty array on success, array with errors on failure + */ + function applyUpgrade( $pPackage, $pUpgradeHash ) { global $gBitDb; $ret = array(); - if( !empty( $this->mUpgrades[$package] )) { + if( !empty( $pUpgradeHash ) && is_array( $pUpgradeHash )) { // set table prefixes and handle special case of sequence prefixes $schemaQuote = strrpos( BIT_DB_PREFIX, '`' ); $sequencePrefix = ( $schemaQuote ? substr( BIT_DB_PREFIX, $schemaQuote + 1 ) : BIT_DB_PREFIX ); $tablePrefix = $this->getTablePrefix(); $dict = NewDataDictionary( $gBitDb->mDb ); - for( $i = 0; $i < count( $this->mUpgrades[$package] ); $i++ ) { + $failedcommands = array(); - if( !is_array( $this->mUpgrades[$package][$i] ) ) { - vd( "[$package][$i] is NOT array" ); - vd( $this->mUpgrades[$package][$i] ); + for( $i = 0; $i < count( $pUpgradeHash ); $i++ ) { + if( !is_array( $pUpgradeHash[$i] ) ) { + vd( "[$pPackage][$i] is NOT an array" ); + vd( $pUpgradeHash[$i] ); bt(); die; } - $type = key( $this->mUpgrades[$package][$i] ); - $step = &$this->mUpgrades[$package][$i][$type]; - $failedcommands = array(); + $type = key( $pUpgradeHash[$i] ); + $step = &$pUpgradeHash[$i][$type]; switch( $type ) { case 'DATADICT': for( $j = 0; $j < count( $step ); $j++ ) { $dd = &$step[$j]; switch( key( $dd ) ) { - case 'CREATE': - foreach( $dd as $create ) { - foreach( array_keys( $create ) as $tableName ) { - $completeTableName = $tablePrefix.$tableName; - $sql = $dict->CreateTableSQL( $completeTableName, $create[$tableName], 'REPLACE' ); - if( $sql && ( $dict->ExecuteSQLArray( $sql ) > 0 ) ) { - } else { - $errors[] = 'Failed to create '.$completeTableName; - $failedcommands[] = implode( " ", $sql ); - } - } - } - break; - case 'ALTER': - foreach( $dd as $alter ) { - foreach( array_keys( $alter ) as $tableName ) { - $completeTableName = $tablePrefix.$tableName; - foreach( $alter[$tableName] as $from => $flds ) { - if (is_string($flds)) { - $sql = $dict->ChangeTableSQL( $completeTableName, $flds ); + case 'CREATE': + foreach( $dd as $create ) { + foreach( array_keys( $create ) as $tableName ) { + $completeTableName = $tablePrefix.$tableName; + $sql = $dict->CreateTableSQL( $completeTableName, $create[$tableName], 'REPLACE' ); + if( $sql && ( $dict->ExecuteSQLArray( $sql, FALSE ) > 0 ) ) { } else { - $sql = $dict->ChangeTableSQL( $completeTableName, array($flds) ); - } - if( $sql && ($dict->ExecuteSQLArray( $sql ) > 0 ) ) { - } else { - $errors[] = 'Failed to alter '.$completeTableName.' -> '.$alter[$tableName]; + $errors[] = 'Failed to create '.$completeTableName; $failedcommands[] = implode( " ", $sql ); } } } - } - break; - case 'RENAMETABLE': - foreach( $dd as $rename ) { - foreach( array_keys( $rename ) as $tableName ) { - $completeTableName = $tablePrefix.$tableName; - if( $sql = @$dict->RenameTableSQL( $completeTableName, $tablePrefix.$rename[$tableName] ) ) { - foreach( $sql AS $query ) { - $this->mDb->query( $query ); + break; + case 'ALTER': + foreach( $dd as $alter ) { + foreach( array_keys( $alter ) as $tableName ) { + $completeTableName = $tablePrefix.$tableName; + foreach( $alter[$tableName] as $from => $flds ) { + if( is_string( $flds )) { + $sql = $dict->ChangeTableSQL( $completeTableName, $flds ); + } else { + $sql = $dict->ChangeTableSQL( $completeTableName, array( $flds )); + } + + if( $sql && $dict->ExecuteSQLArray( $sql, FALSE ) > 0 ) { + } else { + $errors[] = 'Failed to alter '.$completeTableName.' -> '.$alter[$tableName]; + $failedcommands[] = implode( " ", $sql ); + } } - } else { - $errors[] = 'Failed to rename table '.$completeTableName.'.'.$rename[$tableName][0].' to '.$rename[$tableName][1]; - $failedcommands[] = implode( " ", $sql ); } } - } - break; - case 'RENAMECOLUMN': - foreach( $dd as $rename ) { - foreach( array_keys( $rename ) as $tableName ) { - $completeTableName = $tablePrefix.$tableName; - foreach( $rename[$tableName] as $from => $flds ) { - // MySQL needs the fields string, others do not. - // see http://phplens.com/lens/adodb/docs-datadict.htm - $to = substr( $flds, 0, strpos( $flds, ' ') ); - if( $sql = @$dict->RenameColumnSQL( $completeTableName, $from, $to, $flds ) ) { + break; + case 'RENAMETABLE': + foreach( $dd as $rename ) { + foreach( array_keys( $rename ) as $tableName ) { + $completeTableName = $tablePrefix.$tableName; + if( $sql = @$dict->RenameTableSQL( $completeTableName, $tablePrefix.$rename[$tableName] ) ) { foreach( $sql AS $query ) { $this->mDb->query( $query ); } } else { - $errors[] = 'Failed to rename column '.$completeTableName.'.'.$rename[$tableName][0].' to '.$rename[$tableName][1]; + $errors[] = 'Failed to rename table '.$completeTableName.'.'.$rename[$tableName][0].' to '.$rename[$tableName][1]; $failedcommands[] = implode( " ", $sql ); } } } - } - break; - case 'CREATESEQUENCE': - foreach( $dd as $create ) { - foreach( $create as $sequence ) { - $this->mDb->CreateSequence( $sequencePrefix.$sequence ); + break; + case 'RENAMECOLUMN': + foreach( $dd as $rename ) { + foreach( array_keys( $rename ) as $tableName ) { + $completeTableName = $tablePrefix.$tableName; + foreach( $rename[$tableName] as $from => $flds ) { + // MySQL needs the fields string, others do not. + // see http://phplens.com/lens/adodb/docs-datadict.htm + $to = substr( $flds, 0, strpos( $flds, ' ') ); + if( $sql = @$dict->RenameColumnSQL( $completeTableName, $from, $to, $flds ) ) { + foreach( $sql AS $query ) { + $this->mDb->query( $query ); + } + } else { + $errors[] = 'Failed to rename column '.$completeTableName.'.'.$rename[$tableName][0].' to '.$rename[$tableName][1]; + $failedcommands[] = implode( " ", $sql ); + } + } + } } - } - break; - case 'RENAMESEQUENCE': - foreach( $dd as $rename ) { - foreach( $rename as $from => $to ) { - if( $this->mDb->tableExists( $tablePrefix.$from ) ) { - if( $id = $this->mDb->GenID( $from ) ) { - $this->mDb->DropSequence( $sequencePrefix.$from ); - $this->mDb->CreateSequence( $sequencePrefix.$to, $id ); + break; + case 'CREATESEQUENCE': + foreach( $dd as $create ) { + foreach( $create as $sequence ) { + $this->mDb->CreateSequence( $sequencePrefix.$sequence ); + } + } + break; + case 'RENAMESEQUENCE': + foreach( $dd as $rename ) { + foreach( $rename as $from => $to ) { + if( $this->mDb->tableExists( $tablePrefix.$from ) ) { + if( $id = $this->mDb->GenID( $from ) ) { + $this->mDb->DropSequence( $sequencePrefix.$from ); + $this->mDb->CreateSequence( $sequencePrefix.$to, $id ); + } else { + $errors[] = 'Failed to rename sequence '.$sequencePrefix.$from.' to '.$sequencePrefix.$to; + $failedcommands[] = implode( " ", $sql ); + } } else { - $errors[] = 'Failed to rename sequence '.$sequencePrefix.$from.' to '.$sequencePrefix.$to; - $failedcommands[] = implode( " ", $sql ); + $this->mDb->CreateSequence( $sequencePrefix.$to, $pUpgradeHash['sequences'][$to]['start'] ); } - } else { - $this->mDb->CreateSequence( $sequencePrefix.$to, $this->mPackages[$package]['sequences'][$to]['start'] ); } } - } - break; - case 'DROPCOLUMN': - foreach( $dd as $drop ) { - foreach( array_keys( $drop ) as $tableName ) { - $completeTableName = $tablePrefix.$tableName; - foreach( $drop[$tableName] as $col ) { - if( $sql = $dict->DropColumnSQL( $completeTableName, $col ) ) { - foreach( $sql AS $query ) { - $this->mDb->query( $query ); + break; + case 'DROPCOLUMN': + foreach( $dd as $drop ) { + foreach( array_keys( $drop ) as $tableName ) { + $completeTableName = $tablePrefix.$tableName; + foreach( $drop[$tableName] as $col ) { + if( $sql = $dict->DropColumnSQL( $completeTableName, $col ) ) { + foreach( $sql AS $query ) { + $this->mDb->query( $query ); + } + } else { + $errors[] = 'Failed to drop column '.$completeTableName; + $failedcommands[] = implode( " ", $sql ); } - } else { - $errors[] = 'Failed to drop column '.$completeTableName; - $failedcommands[] = implode( " ", $sql ); } } } - } - break; - case 'DROPTABLE': - foreach( $dd as $drop ) { - foreach( $drop as $tableName ) { - $completeTableName = $tablePrefix.$tableName; - $sql = $dict->DropTableSQL( $completeTableName ); - if( $sql && ($dict->ExecuteSQLArray( $sql ) > 0 ) ) { - } else { - $errors[] = 'Failed to drop table '.$completeTableName; - $failedcommands[] = implode( " ", $sql ); + break; + case 'DROPTABLE': + foreach( $dd as $drop ) { + foreach( $drop as $tableName ) { + $completeTableName = $tablePrefix.$tableName; + $sql = $dict->DropTableSQL( $completeTableName ); + if( $sql && ($dict->ExecuteSQLArray( $sql, FALSE ) > 0 ) ) { + } else { + $errors[] = 'Failed to drop table '.$completeTableName; + $failedcommands[] = implode( " ", $sql ); + } } } - } - break; - case 'CREATEINDEX': - foreach( $dd as $indices ) { - foreach( array_keys( $indices ) as $index ) { - $completeTableName = $tablePrefix.$indices[$index][0]; - if( $sql = $dict->CreateIndexSQL( $index, $completeTableName, $indices[$index][1], $indices[$index][2] ) ) { - foreach( $sql AS $query ) { - $this->mDb->query( $query ); + break; + case 'CREATEINDEX': + foreach( $dd as $indices ) { + foreach( array_keys( $indices ) as $index ) { + $completeTableName = $tablePrefix.$indices[$index][0]; + if( $sql = $dict->CreateIndexSQL( $index, $completeTableName, $indices[$index][1], $indices[$index][2] ) ) { + foreach( $sql AS $query ) { + $this->mDb->query( $query ); + } + } else { + $errors[] = 'Failed to create index '.$index; + $failedcommands[] = implode( " ", $sql ); } - } else { - $errors[] = 'Failed to create index '.$index; - $failedcommands[] = implode( " ", $sql ); } } - } - - break; + break; } - } break; case 'QUERY': @@ -437,8 +505,9 @@ class BitInstaller extends BitSystem { } // turn on features that are turned on - if( $this->isFeatureActive( 'feature_'.$package )) { - $this->storeConfig( 'package_'.$package, 'y', KERNEL_PKG_NAME ); + // legacy stuff + if( $this->isFeatureActive( 'feature_'.$pPackage )) { + $this->storeConfig( 'package_'.$pPackage, 'y', KERNEL_PKG_NAME ); } if( !empty( $failedcommands )) { @@ -460,11 +529,11 @@ class BitInstaller extends BitSystem { function identifyBlobs( $result ) { $blobs = array(); //echo "FieldCount: ".$result->FieldCount()."\n"; - for($i = 0; $i < $result->FieldCount(); $i++) { + for( $i = 0; $i < $result->FieldCount(); $i++ ) { $field = $result->FetchField($i); //echo $i."-".$field->name."-".$result->MetaType($field->type)."-".$field->max_length."\n"; // check for blobs - if(($result->MetaType($field->type)=='B') || ($result->MetaType($field->type)=='X' && $field->max_length >= 16777215)) + if(( $result->MetaType( $field->type ) == 'B' ) || ( $result->MetaType( $field->type )=='X' && $field->max_length >= 16777215 )) $blobs[] = $field->name; } return $blobs; |
