Skip to content
Snippets Groups Projects
class.upgrader.php 7.32 KiB
Newer Older
<?php
/*********************************************************************
    class.upgrader.php

    osTicket Upgrader

    Peter Rotich <peter@osticket.com>
    Copyright (c)  2006-2012 osTicket
    http://www.osticket.com

    Released under the GNU General Public License WITHOUT ANY WARRANTY.
    See LICENSE.TXT for details.

    vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/

require_once INC_DIR.'class.setup.php';

class Upgrader extends SetupWizard {

    var $prefix;
    var $sqldir;
    var $signature;

    function Upgrader($signature, $prefix, $sqldir) {

        $this->signature = $signature;
        $this->shash = substr($signature, 0, 8);
        $this->prefix = $prefix;
        $this->sqldir = $sqldir;
        $this->errors = array();

        //Init persistent state of upgrade.
        $this->state = &$_SESSION['ost_upgrader'][$this->getShash()]['state'];

        //Init the task Manager.
        if(!isset($_SESSION['ost_upgrader'][$this->getShash()]))
            $_SESSION['ost_upgrader'][$this->getShash()]['tasks']=array();

        //Tasks to perform - saved on the session.
        $this->tasks = &$_SESSION['ost_upgrader'][$this->getShash()]['tasks'];

        $this->migrater = DatabaseMigrater($this->sqldir);
    }

    function getStops() {
        return array('7be60a84' => 'migrateAttachments2DB');
    }

    function onError($error) {
        $this->setError($error);
        $this->setState('aborted');
    }

    function isUpgradable() {
        return (!$this->isAborted() && $this->getNextPatch());
    }

    function isAborted() {
        return !strcasecmp($this->getState(), 'aborted');
    }

    function getSchemaSignature() {
        return $this->signature;
    }

    function getShash() {
        return $this->shash;
    }

    function getTablePrefix() {
        return $this->prefix;
    }

    function getSQLDir() {
        return $this->sqldir;
    }

    function getState() {
        return $this->state;
    }

    function setState($state) {
        $this->state = $state;
    }

    function getPatches() {
        return $this->migrater->getRollup($this->getStops());
    }

    function getNextPatch() {
        $p = $this->getPatches();
        return (count($p)) ? $p[0] : false;
    }

    function getNextVersion() {
        if(!$patch=$this->getNextPatch())
            return '(Latest)';

        $info = $this->readPatchInfo($patch);
        return $info['version'];
    }

    function readPatchInfo($patch) {
        $info = array();
        if (preg_match('/\*(.*)\*/', file_get_contents($patch), $matches)) {
            if (preg_match('/@([\w\d_-]+)\s+(.*)$/', $matches[0], $matches2))
                foreach ($matches2 as $match)
                    $info[$match[0]] = $match[1];
        }
        if (!isset($info['version']))
            $info['version'] = substr(basename($patch), 9, 8);
        return $info;
    }

    function getNextAction() {

        $action='Upgrade osTicket to '.$this->getVersion();
        if($this->getNumPendingTasks() && ($task=$this->getNextTask())) {
            $action = $task['desc'];
            if($task['status']) //Progress report... 
                $action.=' ('.$task['status'].')';
        } elseif($this->isUpgradable() && ($nextversion = $this->getNextVersion())) {
            $action = "Upgrade to $nextversion";
        }

        return $action;
    }

    function getNextStepInfo() {

        if(($patches=$this->getPatches()))
            return $patches[0];
        
        if(($hooks=$this->getScriptedHooks()))
            return $hooks[0]['desc'];

        return null;
    }

    function getNumPendingTasks() {

        return count($this->getPendingTasks());
    }

    function getPendingTasks() {

        $pending=array();
        if(($tasks=$this->getTasks())) {
            foreach($tasks as $k => $task) {
                if(!$task['done'])
                    $pending[$k] = $task;
            }  
        }
        
        return $pending;
    }

    function getTasks() {
       return $this->tasks;
    }

    function getNextTask() {

        if(!($tasks=$this->getPendingTasks()))
            return null;

        return current($tasks);
    }

    function removeTask($tId) {

        if(isset($this->tasks[$tId]))
            unset($this->tasks[$tId]);

        return (!$this->tasks[$tId]);
    }

    function setTaskStatus($tId, $status) {
        if(isset($this->tasks[$tId]))
            $this->tasks[$tId]['status'] = $status;
    }

    function doTasks() {

        if(!($tasks=$this->getPendingTasks()))
            return true; //Nothing to do.

        foreach($tasks as $k => $task) {
            if(call_user_func(array($this, $task['func']), $k)===0) {
                $this->tasks[$k]['done'] = true;
            } else { //Task has pending items to process.
                break;
            }
        }

        return (!$this->getPendingTasks());
    }
    
    function upgrade() {

        if($this->getPendingTasks() || !($patches=$this->getPatches()))
            return false;

        foreach ($patches as $patch)
            if (!$this->load_sql_file($patch, $this->getTablePrefix()))
                return false;

        //TODO: Log the upgrade

        //Load up post install tasks.
        $shash = substr(basename($patch), 9, 8); 
        $phash = substr(basename($patch), 0, 17); 
        
        $tasks=array();
        $tasks[] = array('func' => 'sometask',
                         'desc' => 'Some Task.... blah');
        switch($phash) { //Add  patch specific scripted tasks.
            case 'xxxx': //V1.6 ST- 1.7 *
                $tasks[] = array('func' => 'migrateAttachments2DB',
                                 'desc' => 'Migrating attachments to database, it might take a while depending on the number of files.');
                break;
        }
        
        $tasks[] = array('func' => 'cleanup',
                         'desc' => 'Post-upgrade cleanup!');
        
        
        
        //Load up tasks - NOTE: writing directly to the session - back to the future majic.
        $_SESSION['ost_upgrader'][$shash]['tasks'] = $tasks;
        $_SESSION['ost_upgrader'][$shash]['state'] = 'upgrade';

        //clear previous patch info - 
        unset($_SESSION['ost_upgrader'][$this->getSHash()]);

        return true;
    }

    /************* TASKS **********************/
    function sometask($tId) {
        
        $this->setTaskStatus($tId, 'Doing... '.time(). ' #'.$_SESSION['sometask']);

        sleep(2);
        $_SESSION['sometask']+=1;
        if($_SESSION['sometask']<4)
            return 22;

        $_SESSION['sometask']=0;

        return 0;  //Change to 1 for testing...
    }

    function cleanup($tId=0) {

        $file=$this->getSQLDir().$this->getSchemaSignature().'-cleanup.sql';
        if(!file_exists($file)) //No cleanup script.
            return 0;

        //We have a cleanup script  ::XXX: Don't abort on error? 
        if($this->load_sql_file($file, $this->getTablePrefix(), false, true))
            return 0;

        //XXX: ???
        return false;
    }
    

    function migrateAttachments2DB($tId=0) {
        echo "Process attachments here - $tId";
        $att_migrater = new AttachmentMigrater();
        $att_migrater->start_migration();
        # XXX: Loop here (with help of task manager)
        $att_migrater->do_batch();
        return 0;
    }
}
?>