Skip to content
Snippets Groups Projects
class.ticket.php 104 KiB
Newer Older
Jared Hancock's avatar
Jared Hancock committed
<?php
/*********************************************************************
    class.ticket.php

    The most important class! Don't play with fire please.

    Peter Rotich <peter@osticket.com>
    Copyright (c)  2006-2013 osTicket
Jared Hancock's avatar
Jared Hancock committed
    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:
**********************************************************************/
include_once(INCLUDE_DIR.'class.thread.php');
Jared Hancock's avatar
Jared Hancock committed
include_once(INCLUDE_DIR.'class.staff.php');
include_once(INCLUDE_DIR.'class.client.php');
Jared Hancock's avatar
Jared Hancock committed
include_once(INCLUDE_DIR.'class.team.php');
include_once(INCLUDE_DIR.'class.email.php');
include_once(INCLUDE_DIR.'class.dept.php');
include_once(INCLUDE_DIR.'class.topic.php');
include_once(INCLUDE_DIR.'class.lock.php');
include_once(INCLUDE_DIR.'class.file.php');
include_once(INCLUDE_DIR.'class.attachment.php');
include_once(INCLUDE_DIR.'class.banlist.php');
include_once(INCLUDE_DIR.'class.template.php');
include_once(INCLUDE_DIR.'class.variable.php');
Jared Hancock's avatar
Jared Hancock committed
include_once(INCLUDE_DIR.'class.priority.php');
Peter Rotich's avatar
Peter Rotich committed
include_once(INCLUDE_DIR.'class.sla.php');
include_once(INCLUDE_DIR.'class.canned.php');
Jared Hancock's avatar
Jared Hancock committed
require_once(INCLUDE_DIR.'class.dynamic_forms.php');
require_once(INCLUDE_DIR.'class.user.php');
require_once(INCLUDE_DIR.'class.collaborator.php');
require_once(INCLUDE_DIR.'class.faq.php');
class TicketModel extends VerySimpleModel {
    static $meta = array(
        'table' => TICKET_TABLE,
        'pk' => array('ticket_id'),
        'joins' => array(
            'user' => array(
                'constraint' => array('user_id' => 'User.id')
            ),
            'status' => array(
                'constraint' => array('status_id' => 'TicketStatus.id')
            ),
            'lock' => array(
                'reverse' => 'TicketLock.ticket',
                'list' => false,
                'null' => true,
            ),
            'dept' => array(
                'constraint' => array('dept_id' => 'Dept.id'),
            'sla' => array(
                'constraint' => array('sla_id' => 'SlaModel.id'),
                'null' => true,
            ),
Jared Hancock's avatar
Jared Hancock committed
                'constraint' => array('staff_id' => 'Staff.staff_id'),
                'null' => true,
            ),
            'team' => array(
                'constraint' => array('team_id' => 'Team.team_id'),
                'null' => true,
            ),
            'topic' => array(
                'constraint' => array('topic_id' => 'Topic.topic_id'),
                'null' => true,
            ),
            'cdata' => array(
                'reverse' => 'TicketCData.ticket',
                'list' => false,
            ),
        )
    );

    function getId() {
        return $this->ticket_id;
    }

    function getEffectiveDate() {
         return Format::datetime(max(
             strtotime($this->lastmessage),
             strtotime($this->closed),
             strtotime($this->reopened),
             strtotime($this->created)
    }

    function delete() {

        if (($ticket=Ticket::lookup($this->getId())) && @$ticket->delete())
            return true;

        return false;
    }

    static function registerCustomData(DynamicForm $form) {
        if (!isset(static::$meta['joins']['cdata+'.$form->id])) {
            $cdata_class = <<<EOF
class DynamicForm{$form->id} extends DynamicForm {
    static function getInstance() {
        static \$instance;
        if (!isset(\$instance))
            \$instance = static::lookup({$form->id});
        return \$instance;
    }
}
class TicketCdataForm{$form->id} {
    static \$meta = array(
        'view' => true,
        'pk' => array('ticket_id'),
        'joins' => array(
            'ticket' => array(
                'constraint' => array('ticket_id' => 'TicketModel.ticket_id'),
            ),
        )
    );
    static function getQuery(\$compiler) {
        return '('.DynamicForm{$form->id}::getCrossTabQuery('T', 'ticket_id').')';
    }
}
EOF;
            eval($cdata_class);
            static::$meta['joins']['cdata+'.$form->id] = array(
                'reverse' => 'TicketCdataForm'.$form->id.'.ticket',
                'null' => true,
            );
            // This may be necessary if the model has already been inspected
            if (static::$meta instanceof ModelMeta)
                static::$meta->processJoin(static::$meta['joins']['cdata+'.$form->id]);
        }
    }
}

class TicketCData extends VerySimpleModel {
    static $meta = array(
        'pk' => array('ticket_id'),
        'joins' => array(
            'ticket' => array(
                'constraint' => array('ticket_id' => 'TicketModel.ticket_id'),
            ),
            ':priority' => array(
                'constraint' => array('priority' => 'Priority.priority_id'),
                'null' => true,
            ),
        ),
    );
}
TicketCData::$meta['table'] = TABLE_PREFIX . 'ticket__cdata';

Jared Hancock's avatar
Jared Hancock committed

    var $id;
Jared Hancock's avatar
Jared Hancock committed

    var $lastMsgId;
    var $status;
Jared Hancock's avatar
Jared Hancock committed
    var $dept;  //Dept obj
    var $sla;   // SLA obj
    var $staff; //Staff obj
    var $client; //Client Obj
Jared Hancock's avatar
Jared Hancock committed
    var $team;  //Team obj
    var $topic; //Topic obj
    var $tlock; //TicketLock obj
Jared Hancock's avatar
Jared Hancock committed
        $this->id = 0;
        $this->load($id);
    }
Jared Hancock's avatar
Jared Hancock committed
    function load($id=0) {

        if(!$id && !($id=$this->getId()))
            return false;

Jared Hancock's avatar
Jared Hancock committed
        $sql='SELECT  ticket.*, lock_id, dept_name '
            .' ,count(distinct attach.attach_id) as attachments'
Jared Hancock's avatar
Jared Hancock committed
            .' FROM '.TICKET_TABLE.' ticket '
            .' LEFT JOIN '.DEPT_TABLE.' dept ON (ticket.dept_id=dept.dept_id) '
            .' LEFT JOIN '.SLA_TABLE.' sla ON (ticket.sla_id=sla.id AND sla.isactive=1) '
Peter Rotich's avatar
Peter Rotich committed
            .' LEFT JOIN '.TICKET_LOCK_TABLE.' tlock
                ON ( ticket.ticket_id=tlock.ticket_id AND tlock.expire>NOW()) '
            .' LEFT JOIN '.TICKET_ATTACHMENT_TABLE.' attach
                ON ( ticket.ticket_id=attach.ticket_id) '
Jared Hancock's avatar
Jared Hancock committed
            .' WHERE ticket.ticket_id='.db_input($id)
            .' GROUP BY ticket.ticket_id';

        //echo $sql;
        if(!($res=db_query($sql)) || !db_num_rows($res))
            return false;

Jared Hancock's avatar
Jared Hancock committed
        $this->id       = $this->ht['ticket_id'];
        $this->number   = $this->ht['number'];
        $this->_answers = array();
Jared Hancock's avatar
Jared Hancock committed
        $this->loadDynamicData();

Jared Hancock's avatar
Jared Hancock committed
        //Reset the sub classes (initiated ondemand)...good for reloads.
        $this->status= null;
Jared Hancock's avatar
Jared Hancock committed
        $this->staff = null;
        $this->client = null;
Jared Hancock's avatar
Jared Hancock committed
        $this->team  = null;
        $this->dept = null;
        $this->sla = null;
        $this->tlock = null;
        $this->stats = null;
        $this->topic = null;
        $this->collaborators = null;
Jared Hancock's avatar
Jared Hancock committed
        return true;
    }
Jared Hancock's avatar
Jared Hancock committed
    function loadDynamicData() {
        if (!$this->_answers) {
            foreach (DynamicFormEntry::forTicket($this->getId(), true) as $form) {
                foreach ($form->getAnswers() as $answer) {
                    $tag = mb_strtolower($answer->getField()->get('name'))
                        ?: 'field.' . $answer->getField()->get('id');
                        $this->_answers[$tag] = $answer;
        return $this->_answers;
Jared Hancock's avatar
Jared Hancock committed
    function reload() {
        return $this->load();
    }
    function hasState($state) {
        return  (strcasecmp($this->getState(), $state)==0);
    }

Jared Hancock's avatar
Jared Hancock committed
    function isOpen() {
        return $this->hasState('open');
Jared Hancock's avatar
Jared Hancock committed
    }

    function isReopened() {
        return ($this->getReopenDate());
    }

    function isReopenable() {
        return $this->getStatus()->isReopenable();
    }

Jared Hancock's avatar
Jared Hancock committed
    function isClosed() {
         return $this->hasState('closed');
    }

    function isArchived() {
         return $this->hasState('archived');
    }

    function isDeleted() {
         return $this->hasState('deleted');
Jared Hancock's avatar
Jared Hancock committed
    }

    function isAssigned() {
        return ($this->isOpen() && ($this->getStaffId() || $this->getTeamId()));
    }

    function isOverdue() {
Jared Hancock's avatar
Jared Hancock committed
    function isAnswered() {
       return ($this->ht['isanswered']);
    }

    function isLocked() {
        return null !== $this->getLock();
Jared Hancock's avatar
Jared Hancock committed
    }

    function checkStaffAccess($staff) {

        if(!is_object($staff) && !($staff=Staff::lookup($staff)))
            return false;

        // Staff has access to the department.
        if (!$staff->showAssignedOnly()
                && $staff->canAccessDept($this->getDeptId()))
            return true;

        // Only consider assignment if the ticket is open
        if (!$this->isOpen())
            return false;

        // Check ticket access based on direct or team assignment
        if ($staff->getId() == $this->getStaffId()
                || ($this->getTeamId()
                    && $staff->isTeamMember($this->getTeamId())
        ))
            return true;

        // No access bro!
        return false;
    function checkUserAccess($user) {
        if (!$user || !($user instanceof EndUser))
        //Ticket Owner
        if ($user->getId() == $this->getUserId())
        //Collaborator?
        // 1) If the user was authorized via this ticket.
        if ($user->getTicketId() == $this->getId()
                && !strcasecmp($user->getRole(), 'collaborator'))
            return true;

        // 2) Query the database to check for expanded access...
        if (Collaborator::lookup(array(
                        'userId' => $user->getId(),
                        'ticketId' => $this->getId())))
Jared Hancock's avatar
Jared Hancock committed
    //Getters
Jared Hancock's avatar
Jared Hancock committed
        return  $this->id;
    }

    function getOwnerId() {
        return $this->ht['user_id'];
    }

    function getOwner() {

        if (!isset($this->owner)
                && ($u=User::lookup($this->getOwnerId())))
            $this->owner = new TicketOwner(new EndUser($u), $this);

        return $this->owner;
Jared Hancock's avatar
Jared Hancock committed
    function getEmail(){
        if ($o = $this->getOwner())
            return $o->getEmail();
        return null;
    }

    function getReplyToEmail() {
        //TODO: Determine the email to use (once we enable multi-email support)
        return $this->getEmail();
    function getAuthToken() {
        # XXX: Support variable email address (for CCs)
        return md5($this->getId() . strtolower($this->getEmail()) . SECRET_SALT);
Jared Hancock's avatar
Jared Hancock committed
    function getName(){
        if ($o = $this->getOwner())
            return $o->getName();
Jared Hancock's avatar
Jared Hancock committed
    }

    function getSubject() {
        return (string) $this->_answers['subject'];
Jared Hancock's avatar
Jared Hancock committed
    }

    /* Help topic title  - NOT object -> $topic */
    function getHelpTopic() {

        if(!$this->ht['helptopic'] && ($topic=$this->getTopic()))
            $this->ht['helptopic'] = $topic->getFullName();

    function getCreateDate() {
        return $this->ht['created'];
Jared Hancock's avatar
Jared Hancock committed
    }

    function getOpenDate() {
        return $this->getCreateDate();
    }

    function getReopenDate() {

    function getUpdateDate() {
        return $this->ht['updated'];
    function getDueDate() {
        return $this->ht['duedate'];
    function getSLADueDate() {
        if ($sla = $this->getSLA()) {
            $dt = new DateTime($this->getCreateDate());

            return $dt
                ->add(new DateInterval('PT' . $sla->getGracePeriod() . 'H'))
                ->format('Y-m-d H:i:s');
        }
    }

    function updateEstDueDate() {
        $estimatedDueDate = $this->getEstDueDate();
        if ($estimatedDueDate != $this->ht['est_duedate']) {
            $sql = 'UPDATE '.TICKET_TABLE.' SET `est_duedate`='.db_input($estimatedDueDate)
                .' WHERE `ticket_id`='.db_input($this->getId());
            db_query($sql);
        }
    }

    function getEstDueDate() {

        if(($duedate=$this->getDueDate()))
            return $duedate;

        //return sla due date (If ANY)
        return $this->getSLADueDate();
    }

    function getCloseDate() {
        return $this->ht['closed'];
    function getStatusId() {
        return $this->ht['status_id'];
    }


        if (!$this->status && $this->getStatusId())
            $this->status = TicketStatus::lookup($this->getStatusId());

        return $this->status;
    }

    function getState() {

        if (!$this->getStatus())
            return '';

        return $this->getStatus()->getState();

    function getDeptId() {
       return $this->ht['dept_id'];

    function getDeptName() {

        if(!$this->ht['dept_name'] && ($dept = $this->getDept()))
            $this->ht['dept_name'] = $dept->getName();

       return $this->ht['dept_name'];
Jared Hancock's avatar
Jared Hancock committed
    }

    function getPriorityId() {
        if (($a = $this->_answers['priority'])
                && ($b = $a->getValue()))
            return $b->getId();
        return $cfg->getDefaultPriorityId();
    function getPriority() {
        if (($a = $this->_answers['priority']) && ($b = $a->getValue()))
            return $b->getDesc();
        return '';
Jared Hancock's avatar
Jared Hancock committed
    function getPhoneNumber() {
        return (string)$this->getOwner()->getPhoneNumber();
Jared Hancock's avatar
Jared Hancock committed
    }

    function getSource() {
        return $this->ht['source'];
    }
Jared Hancock's avatar
Jared Hancock committed
    function getIP() {
        return $this->ht['ip_address'];
    }

Peter Rotich's avatar
Peter Rotich committed
    function getHashtable() {
        return $this->ht;
    }

    function getUpdateInfo() {
        global $cfg;
Peter Rotich's avatar
Peter Rotich committed

        $info=array('source'    =>  $this->getSource(),
Peter Rotich's avatar
Peter Rotich committed
                    'topicId'   =>  $this->getTopicId(),
                    'slaId' =>  $this->getSLAId(),
                    'user_id' => $this->getOwnerId(),
                    'duedate'   =>  $this->getDueDate()
                        ? Format::date($this->getDueDate())
                    'time'  =>  $this->getDueDate()?(Format::date($this->getDueDate(), true, 'HH:mm')):'',
Peter Rotich's avatar
Peter Rotich committed
                    );
Peter Rotich's avatar
Peter Rotich committed
        return $info;
    }

Jared Hancock's avatar
Jared Hancock committed
        return $this->tlock;
    }
Jared Hancock's avatar
Jared Hancock committed
    function acquireLock($staffId, $lockTime) {
Jared Hancock's avatar
Jared Hancock committed
        if(!$staffId or !$lockTime) //Lockig disabled?
            return null;

        //Check if the ticket is already locked.
        if(($lock=$this->getLock()) && !$lock->isExpired()) {
            if($lock->getStaffId()!=$staffId) //someone else locked the ticket.
                return null;

            //Lock already exits...renew it
            $lock->renew($lockTime); //New clock baby.
Jared Hancock's avatar
Jared Hancock committed
            return $lock;
        }
        //No lock on the ticket or it is expired
        $this->tlock = TicketLock::acquire($this->getId(), $staffId, $lockTime); //Create a new lock..
Jared Hancock's avatar
Jared Hancock committed
        //load and return the newly created lock if any!
        return $this->tlock;
        if(!$this->dept)
            if(!($this->dept = Dept::lookup($this->getDeptId())))
                $this->dept = $cfg->getDefaultDept();
Jared Hancock's avatar
Jared Hancock committed

        return $this->dept;
    }
    function getUserId() {
        return $this->getOwnerId();
    }
    function getUser() {
        if(!isset($this->user) && $this->getOwner())
            $this->user = new EndUser($this->getOwner());
        return $this->user;

    function getStaffId() {
        return $this->ht['staff_id'];
Jared Hancock's avatar
Jared Hancock committed

        if(!$this->staff && $this->getStaffId())
            $this->staff= Staff::lookup($this->getStaffId());

        return $this->staff;
    }

    function getTeamId() {
        return $this->ht['team_id'];
Jared Hancock's avatar
Jared Hancock committed

        if(!$this->team && $this->getTeamId())
            $this->team = Team::lookup($this->getTeamId());

        return $this->team;
    }

    function getAssignee() {

        if($staff=$this->getStaff())
            return $staff->getName();

        if($team=$this->getTeam())
            return $team->getName();

        return '';
    }

Peter Rotich's avatar
Peter Rotich committed
    function getAssignees() {
        $assignees=array();
Peter Rotich's avatar
Peter Rotich committed
        if($staff=$this->getStaff())
            $assignees[] = $staff->getName();
Peter Rotich's avatar
Peter Rotich committed
        if($team=$this->getTeam())
            $assignees[] = $team->getName();
Peter Rotich's avatar
Peter Rotich committed

        return $assignees;
    }
    function getAssigned($glue='/') {
        $assignees = $this->getAssignees();
        return $assignees?implode($glue, $assignees):'';
    }

    function getTopicId() {
Jared Hancock's avatar
Jared Hancock committed

        if(!$this->topic && $this->getTopicId())
            $this->topic = Topic::lookup($this->getTopicId());
Jared Hancock's avatar
Jared Hancock committed

        return $this->topic;
    }

Jared Hancock's avatar
Jared Hancock committed
    function getSLAId() {
Jared Hancock's avatar
Jared Hancock committed
    }

    function getSLA() {

        if(!$this->sla && $this->getSLAId())
Peter Rotich's avatar
Peter Rotich committed
            $this->sla = SLA::lookup($this->getSLAId());
Jared Hancock's avatar
Jared Hancock committed

        return $this->sla;
    }

    function getLastRespondent() {

        $sql ='SELECT  resp.staff_id '
             .' FROM '.TICKET_THREAD_TABLE.' resp '
Jared Hancock's avatar
Jared Hancock committed
             .' LEFT JOIN '.STAFF_TABLE. ' USING(staff_id) '
             .' WHERE  resp.ticket_id='.db_input($this->getId()).' AND resp.staff_id>0 '
             .'   AND  resp.thread_type="R"'
Jared Hancock's avatar
Jared Hancock committed
             .' ORDER BY resp.created DESC LIMIT 1';

        if(!($res=db_query($sql)) || !db_num_rows($res))
            return null;
Jared Hancock's avatar
Jared Hancock committed
        list($id)=db_fetch_row($res);

        return Staff::lookup($id);

    }

    function getLastMessageDate() {
Jared Hancock's avatar
Jared Hancock committed
    }

    function getLastMsgDate() {
        return $this->getLastMessageDate();
    }

    function getLastResponseDate() {
Jared Hancock's avatar
Jared Hancock committed
    }

    function getLastRespDate() {
        return $this->getLastResponseDate();
    }

Jared Hancock's avatar
Jared Hancock committed
    function getLastMsgId() {
        return $this->lastMsgId;
    }

    function getLastMessage() {
        if (!isset($this->last_message)) {
            if($this->getLastMsgId())
                $this->last_message =  Message::lookup(
                    $this->getLastMsgId(), $this->getId());
            if (!$this->last_message)
                $this->last_message = Message::lastByTicketId($this->getId());
        }
        return $this->last_message;
        if(!$this->thread)
            $this->thread = Thread::lookup($this);
Jared Hancock's avatar
Jared Hancock committed
    }

    function getThreadCount() {
        return $this->getNumMessages() + $this->getNumResponses();
    }

    function getNumMessages() {
        return $this->getThread()->getNumMessages();
Jared Hancock's avatar
Jared Hancock committed
    }

    function getNumResponses() {
        return $this->getThread()->getNumResponses();
Jared Hancock's avatar
Jared Hancock committed
    }

    function getNumNotes() {
        return $this->getThread()->getNumNotes();
    function getMessages() {
        return $this->getThreadEntries('M');
    function getResponses() {
        return $this->getThreadEntries('R');
    function getNotes() {
        return $this->getThreadEntries('N');
    function getClientThread() {
        return $this->getThreadEntries(array('M', 'R'));
    function getThreadEntry($id) {
        return $this->getThread()->getEntry($id);
    function getThreadEntries($type, $order='') {
        return $this->getThread()->getEntries($type, $order);
    //Collaborators
    function getNumCollaborators() {
Peter Rotich's avatar
Peter Rotich committed
        return count($this->getCollaborators());
    function getNumActiveCollaborators() {

        if (!isset($this->ht['active_collaborators']))
            $this->ht['active_collaborators'] = count($this->getActiveCollaborators());

        return $this->ht['active_collaborators'];
    }

    function getActiveCollaborators() {
        return $this->getCollaborators(array('isactive'=>1));
    }


    function getCollaborators($criteria=array()) {

Peter Rotich's avatar
Peter Rotich committed
        if ($criteria)
            return Collaborator::forTicket($this->getId(), $criteria);

Peter Rotich's avatar
Peter Rotich committed
        if (!isset($this->collaborators))
            $this->collaborators = Collaborator::forTicket($this->getId());

        return $this->collaborators;
    }

    //UserList of recipients  (owner + collaborators)
    function getRecipients() {

        if (!isset($this->recipients)) {
            $list = new UserList();
            $list->add($this->getOwner());
            if ($collabs = $this->getActiveCollaborators()) {
                foreach ($collabs as $c)
                    $list->add($c);
            }
            $this->recipients = $list;
        }

        return $this->recipients;
    }

    function hasClientEditableFields() {
        $forms = DynamicFormEntry::forTicket($this->getId());
        foreach ($forms as $form) {
            foreach ($form->getFields() as $field) {
                if ($field->isEditableToUsers())
                    return true;
            }
        }
    }
    function getMissingRequiredFields() {
        $returnArray = array();
        $forms=DynamicFormEntry::forTicket($this->getId());
        foreach ($forms as $form) {
            foreach ($form->getFields() as $field) {
                if ($field->isRequiredForClose()) {
                    if (!($field->answer->get('value'))) {
                        array_push($returnArray, $field->get('label'));
                    }
                }
            }
        }
        return $returnArray;
    }

    function getMissingRequiredField() {
        $fields = $this->getMissingRequiredFields();
        return $fields[0];
    }

    function addCollaborator($user, $vars, &$errors) {
        if (!$user || $user->getId()==$this->getOwnerId())
Peter Rotich's avatar
Peter Rotich committed
            return null;
                'ticketId' => $this->getId(),
                'userId' => $user->getId()), $vars);
        if (!($c=Collaborator::add($vars, $errors)))
            return null;

        $this->collaborators = null;
        $this->recipients = null;
        return $c;
    }

    //XXX: Ugly for now
    function updateCollaborators($vars, &$errors) {

        //Deletes
        if($vars['del'] && ($ids=array_filter($vars['del']))) {
            $collabs = array();
            foreach ($ids as $k => $cid) {
                if (($c=Collaborator::lookup($cid))
                        && $c->getTicketId() == $this->getId()
                        && $c->remove())
Peter Rotich's avatar
Peter Rotich committed
                     $collabs[] = $c;
            $this->logNote(_S('Collaborators Removed'),
Peter Rotich's avatar
Peter Rotich committed
                    implode("<br>", $collabs), $thisstaff, false);
        }

        //statuses
        $cids = null;
        if($vars['cid'] && ($cids=array_filter($vars['cid']))) {
            $sql='UPDATE '.TICKET_COLLABORATOR_TABLE
                .' SET updated=NOW(), isactive=1 '
                .' WHERE ticket_id='.db_input($this->getId())
                .' AND id IN('.implode(',', db_input($cids)).')';
            db_query($sql);
        }

        $sql='UPDATE '.TICKET_COLLABORATOR_TABLE
            .' SET updated=NOW(), isactive=0 '
            .' WHERE ticket_id='.db_input($this->getId());
        if($cids)
            $sql.=' AND id NOT IN('.implode(',', db_input($cids)).')';

        db_query($sql);

        unset($this->ht['active_collaborators']);
        $this->collaborators = null;

        return true;
    }

Jared Hancock's avatar
Jared Hancock committed
    /* -------------------- Setters --------------------- */
    function setLastMsgId($msgid) {
        return $this->lastMsgId=$msgid;
    }
    function setLastMessage($message) {
        $this->last_message = $message;
        $this->setLastMsgId($message->getId());
    }
Jared Hancock's avatar
Jared Hancock committed

    //DeptId can NOT be 0. No orphans please!
Jared Hancock's avatar
Jared Hancock committed
        //Make sure it's a valid department//
        if(!($dept=Dept::lookup($deptId)) || $dept->getId()==$this->getDeptId())
Jared Hancock's avatar
Jared Hancock committed
            return false;

Jared Hancock's avatar
Jared Hancock committed
        $sql='UPDATE '.TICKET_TABLE.' SET updated=NOW(), dept_id='.db_input($deptId)
            .' WHERE ticket_id='.db_input($this->getId());

        return (db_query($sql) && db_affected_rows());
    }
Jared Hancock's avatar
Jared Hancock committed
    //Set staff ID...assign/unassign/release (id can be 0)
Peter Rotich's avatar
Peter Rotich committed
    function setStaffId($staffId) {

        if(!is_numeric($staffId)) return false;
        $sql='UPDATE '.TICKET_TABLE.' SET updated=NOW(), staff_id='.db_input($staffId)
            .' WHERE ticket_id='.db_input($this->getId());
Peter Rotich's avatar
Peter Rotich committed
        if (!db_query($sql)  || !db_affected_rows())
            return false;

        $this->staff = null;
        $this->ht['staff_id'] = $staffId;

Peter Rotich's avatar
Peter Rotich committed
        return true;
Jared Hancock's avatar
Jared Hancock committed
    }

    function setSLAId($slaId) {
        if ($slaId == $this->getSLAId()) return true;
        $rv = db_query(
Jared Hancock's avatar
Jared Hancock committed
             'UPDATE '.TICKET_TABLE.' SET sla_id='.db_input($slaId)
            .' WHERE ticket_id='.db_input($this->getId()))
            && db_affected_rows();
        if ($rv) {
            $this->ht['sla_id'] = $slaId;
            $this->sla = null;
        }
        return $rv;
Jared Hancock's avatar
Jared Hancock committed
    }
    /**
     * Selects the appropriate service-level-agreement plan for this ticket.
     * When tickets are transfered between departments, the SLA of the new
Jared Hancock's avatar
Jared Hancock committed
     * department should be applied to the ticket. This would be useful,
Jared Hancock's avatar
Jared Hancock committed
     * for instance, if the ticket is transferred to a different department
     * which has a shorter grace period, the ticket should be considered
     * overdue in the shorter window now that it is owned by the new
     * department.
     *
     * $trump - if received, should trump any other possible SLA source.
     *          This is used in the case of email filters, where the SLA
     *          specified in the filter should trump any other SLA to be
     *          considered.
     */
    function selectSLAId($trump=null) {
        global $cfg;
        # XXX Should the SLA be overridden if it was originally set via an
Jared Hancock's avatar
Jared Hancock committed
        #     email filter? This method doesn't consider such a case
Jared Hancock's avatar
Jared Hancock committed
            $slaId = $trump;
        } elseif ($this->getDept() && $this->getDept()->getSLAId()) {
Jared Hancock's avatar
Jared Hancock committed
            $slaId = $this->getDept()->getSLAId();
        } elseif ($this->getTopic() && $this->getTopic()->getSLAId()) {
Jared Hancock's avatar
Jared Hancock committed
            $slaId = $this->getTopic()->getSLAId();
        } else {
            $slaId = $cfg->getDefaultSLAId();
        }
Jared Hancock's avatar
Jared Hancock committed
        return ($slaId && $this->setSLAId($slaId)) ? $slaId : false;
    }

    //Set team ID...assign/unassign/release (id can be 0)
Peter Rotich's avatar
Peter Rotich committed
    function setTeamId($teamId) {
Peter Rotich's avatar
Peter Rotich committed
        if(!is_numeric($teamId)) return false;
Peter Rotich's avatar
Peter Rotich committed
        $sql='UPDATE '.TICKET_TABLE.' SET updated=NOW(), team_id='.db_input($teamId)
            .' WHERE ticket_id='.db_input($this->getId());
Peter Rotich's avatar
Peter Rotich committed
        return (db_query($sql)  && db_affected_rows());
Jared Hancock's avatar
Jared Hancock committed
    }

    //Status helper.
    function setStatus($status, $comments='', &$errors=array()) {
        global $thisstaff;
        if ($status && is_numeric($status))
            $status = TicketStatus::lookup($status);
        if (!$status || !$status instanceof TicketStatus)
            return false;

Peter Rotich's avatar
Peter Rotich committed
        // XXX: intercept deleted status and do hard delete
        if (!strcasecmp($status->getState(), 'deleted'))
            return $this->delete($comments);

        if ($this->getStatusId() == $status->getId())
            return true;

        $sql = 'UPDATE '.TICKET_TABLE.' SET updated=NOW() '.
               ' ,status_id='.db_input($status->getId());

        $ecb = null;
        switch($status->getState()) {