diff --git a/include/class.orm.php b/include/class.orm.php index 56ee74bdba907098b8f7ca07a87e44c5a5d5ef08..b769a2c4bccff2e289bc2f4ca66847ab3c4429e6 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -1340,6 +1340,10 @@ class ModelInstanceManager extends ResultSet { unset(self::$objectCache[$key]); } + static function flushCache() { + self::$objectCache = array(); + } + static function checkCache($modelClass, $fields) { $key = $modelClass::$meta->model; foreach ($modelClass::getMeta('pk') as $f) diff --git a/include/class.upgrader.php b/include/class.upgrader.php index aa45d831d3c9b25410ab937ed65cf569c49f1a08..cf75be7847adc7feb56b4218ad27c7a677208e01 100644 --- a/include/class.upgrader.php +++ b/include/class.upgrader.php @@ -73,8 +73,8 @@ class Upgrader { function setState($state) { $this->state = $state; if ($state == 'done') { - $this->createUpgradedTicket(); ModelMeta::flushModelCache(); + $this->createUpgradedTicket(); } } @@ -372,6 +372,10 @@ class StreamUpgrader extends SetupWizard { if(!($max_time = ini_get('max_execution_time'))) $max_time = 30; //Default to 30 sec batches. + // Drop any model meta cache to ensure model changes do not cause + // crashes + ModelMeta::flushModelCache(); + $task->run($max_time); if (!$task->isFinished()) { $_SESSION['ost_upgrader']['task'][$this->phash] = $task->sleep(); diff --git a/include/cli/modules/upgrade.php b/include/cli/modules/upgrade.php new file mode 100644 index 0000000000000000000000000000000000000000..297d6d56f84d36dcdc1ad23c42410a09d483b165 --- /dev/null +++ b/include/cli/modules/upgrade.php @@ -0,0 +1,96 @@ +<?php +require_once INCLUDE_DIR.'class.upgrader.php'; + +class CliUpgrader extends Module { + var $prologue = "Upgrade an osTicket help desk"; + + var $options = array( + 'summary' => array('-s', '--summary', + 'action' => 'store_true', + 'help' => 'Print an upgrade summary and exit'), + ); + + function run($args, $options) { + Bootstrap::connect(); + + // Pre-checks + global $ost; + $ost = osTicket::start(); + $upgrader = $this->getUpgrader(); + + if ($options['summary']) { + $this->doSummary($upgrader); + } + else { + $this->upgrade($upgrader); + } + } + + function getUpgrader() { + global $ost; + + if (!$ost->isUpgradePending()) { + $this->fail('No upgrade is pending for this account'); + } + + $upgrader = new Upgrader(TABLE_PREFIX, UPGRADE_DIR.'streams/'); + if (!$upgrader->isUpgradable()) { + $this->fail(__('The upgrader does NOT support upgrading from the current vesion!')); + } + elseif (!$upgrader->check_prereq()) { + $this->fail(__('Minimum requirements not met! Refer to Release Notes for more information')); + } + elseif (!strcasecmp(basename(CONFIG_FILE), 'settings.php')) { + $this->fail(__('Config file rename required to continue!')); + } + return $upgrader; + } + + function upgrade($upgrader) { + global $ost, $cfg; + $cfg = $ost->getConfig(); + + while (true) { + if ($upgrader->getTask()) { + // If there's anythin in the model cache (like a Staff + // object or something), ensure that changes to the database + // model won't cause crashes + ModelInstanceManager::flushCache(); + + // More pending tasks - doTasks returns the number of pending tasks + $this->stdout->write("... {$upgrader->getNextAction()}\n"); + $upgrader->doTask(); + } + elseif ($ost->isUpgradePending()) { + if ($upgrader->isUpgradable()) { + $this->stdout->write("... {$upgrader->getNextVersion()}\n"); + $upgrader->upgrade(); + // Reload config to pull schema_signature changes + $cfg->load(); + } + else { + $this->fail(sprintf( + __('Upgrade Failed: Invalid or wrong hash [%s]'), + $ost->getDBSignature() + )); + } + } + elseif (!$ost->isUpgradePending()) { + $this->stdout->write("Yay! All finished!\n"); + break; + } + } + } + + function doSummary($upgrader) { + foreach ($upgrader->getPatches() as $p) { + $info = $upgrader->readPatchInfo($p); + $this->stdout->write(sprintf( + "%s :: %s (%s)\n", $info['version'], $info['title'], + substr($info['signature'], 0, 8) + )); + } + } +} + +Module::register('upgrade', 'CliUpgrader');