Skip to content
Snippets Groups Projects
class.ticket.php 87.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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');
    
    
    Jared Hancock's avatar
    Jared Hancock committed
    
        var $id;
    
    Jared Hancock's avatar
    Jared Hancock committed
    
        var $lastMsgId;
    
    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 '
    
                .' ,IF(sla.id IS NULL, NULL, '
                    .'DATE_ADD(ticket.created, INTERVAL sla.grace_period HOUR)) as sla_duedate '
                .' ,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->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)
    
                        if ($tag = mb_strtolower($answer->getField()->get('name')))
                            $this->_answers[$tag] = $answer;
    
    Jared Hancock's avatar
    Jared Hancock committed
        function reload() {
            return $this->load();
        }
    
    Jared Hancock's avatar
    Jared Hancock committed
        function isOpen() {
            return (strcasecmp($this->getStatus(),'Open')==0);
        }
    
        function isReopened() {
            return ($this->getReopenDate());
        }
    
        function isClosed() {
            return (strcasecmp($this->getStatus(),'Closed')==0);
        }
    
        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 ($this->getLockId());
        }
    
        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->getName();
    
            return $this->ht['helptopic'];
    
    
        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() {
    
            return $this->ht['sla_duedate'];
        }
    
        function getEstDueDate() {
    
    
            if(($duedate=$this->getDueDate()))
                return $duedate;
    
            //return sla due date (If ANY)
            return $this->getSLADueDate();
        }
    
    
        function getCloseDate() {
            return $this->ht['closed'];
    
        function getStatus() {
            return $this->ht['status'];
    
    
        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::userdate($cfg->getDateFormat(),
                                Misc::db2gmtime($this->getDueDate()))
                            :'',
    
    Peter Rotich's avatar
    Peter Rotich committed
                        'time'  =>  $this->getDueDate()?(Format::userdate('G:i', Misc::db2gmtime($this->getDueDate()))):'',
                        );
    
    Peter Rotich's avatar
    Peter Rotich committed
            return $info;
        }
    
    
    Jared Hancock's avatar
    Jared Hancock committed
        function getLockId() {
    
    Jared Hancock's avatar
    Jared Hancock committed
            if(!$this->tlock && $this->getLockId())
    
                $this->tlock= TicketLock::lookup($this->getLockId(), $this->getId());
    
    
    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 = null; //clear crap
            $this->ht['lock_id'] = 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->getLock();
        }
    
            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($this->getLastMsgId())
                return Message::lookup($this->getLastMsgId(), $this->getId());
    
            return Message::lastByTicketId($this->getId());
    
            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 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('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;
        }
    
        //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;
            return db_query(
                 'UPDATE '.TICKET_TABLE.' SET sla_id='.db_input($slaId)
                .' WHERE ticket_id='.db_input($this->getId()))
                && db_affected_rows();
        }
        /**
         * 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) {
    
    
            if(strcasecmp($this->getStatus(), $status)==0)
    
    Jared Hancock's avatar
    Jared Hancock committed
                return true; //No changes needed.
    
            switch(strtolower($status)) {
                case 'open':
                    return $this->reopen();
                    break;
                case 'closed':
                    return $this->close();
                    break;
            }
    
            return false;
        }
    
        function setState($state, $alerts=false) {
    
            switch(strtolower($state)) {
                case 'open':
                    return $this->setStatus('open');
                    break;
                case 'closed':
                    return $this->setStatus('closed');
                    break;
                case 'answered':
                    return $this->setAnsweredState(1);
                    break;
                case 'unanswered':
                    return $this->setAnsweredState(0);
                    break;
                case 'overdue':
                    return $this->markOverdue();
                    break;
    
    Peter Rotich's avatar
    Peter Rotich committed
                case 'notdue':
                    return $this->clearOverdue();
                    break;
                case 'unassined':
                    return $this->unassign();
    
    Jared Hancock's avatar
    Jared Hancock committed
            }
    
            return false;
        }
    
    
    
    
        function setAnsweredState($isanswered) {
    
            $sql='UPDATE '.TICKET_TABLE.' SET isanswered='.db_input($isanswered)
                .' WHERE ticket_id='.db_input($this->getId());
    
            return (db_query($sql) && db_affected_rows());
        }
    
        //Close the ticket
    
    Jared Hancock's avatar
    Jared Hancock committed
            global $thisstaff;
    
            $sql='UPDATE '.TICKET_TABLE.' SET closed=NOW(),isoverdue=0, duedate=NULL, updated=NOW(), status='.db_input('closed');
    
            if($thisstaff) //Give the closing  staff credit.
    
    Jared Hancock's avatar
    Jared Hancock committed
                $sql.=', staff_id='.db_input($thisstaff->getId());
    
            $sql.=' WHERE ticket_id='.db_input($this->getId());
    
    
            if(!db_query($sql) || !db_affected_rows())
                return false;
    
            $this->reload();
    
            $this->logEvent('closed');
    
            $this->deleteDrafts();
    
    Jared Hancock's avatar
    Jared Hancock committed
        }
    
        //set status to open on a closed ticket.
    
            $sql='UPDATE '.TICKET_TABLE.' SET closed=NULL, updated=NOW(), reopened=NOW() '
    
    Jared Hancock's avatar
    Jared Hancock committed
                .' ,status='.db_input('open')
                .' ,isanswered='.db_input($isanswered)
                .' WHERE ticket_id='.db_input($this->getId());
    
    
            if (!db_query($sql) || !db_affected_rows())
                return false;
    
            $this->logEvent('reopened', 'closed');
    
            $this->ht['status'] = 'open';
            $this->ht['isanswerd'] = $isanswered;
    
            return true;
    
    Jared Hancock's avatar
    Jared Hancock committed
        }
    
        function onNewTicket($message, $autorespond=true, $alertstaff=true) {
            global $cfg;
    
            //Log stuff here...
    
    Jared Hancock's avatar
    Jared Hancock committed
            if(!$autorespond && !$alertstaff) return true; //No alerts to send.
    
            /* ------ SEND OUT NEW TICKET AUTORESP && ALERTS ----------*/
    
    Jared Hancock's avatar
    Jared Hancock committed
            $this->reload(); //get the new goodies.
    
            if(!$cfg
                    || !($dept=$this->getDept())
                    || !($tpl = $dept->getTemplate())
                    || !($email=$dept->getAutoRespEmail())) {
                    return false;  //bail out...missing stuff.
            }
    
                'inreplyto'=>$message->getEmailMessageId(),
    
                'references'=>$message->getEmailReferences(),
                'thread'=>$message);
    
    Jared Hancock's avatar
    Jared Hancock committed
            //Send auto response - if enabled.
    
            if($autorespond
                    && $cfg->autoRespONNewTicket()
    
    Jared Hancock's avatar
    Jared Hancock committed
                    &&  ($msg=$tpl->getAutoRespMsgTemplate())) {
    
                $msg = $this->replaceVars($msg->asArray(),
    
                        array('message' => $message,
    
                              'recipient' => $this->getOwner(),
    
                              'signature' => ($dept && $dept->isPublic())?$dept->getSignature():'')
                        );
    
    
                $email->sendAutoReply($this->getEmail(), $msg['subj'], $msg['body'],
                    null, $options);
    
    Jared Hancock's avatar
    Jared Hancock committed
            //Send alert to out sleepy & idle staff.
    
                    && ($email=$cfg->getAlertEmail())
    
    Jared Hancock's avatar
    Jared Hancock committed
                    && ($msg=$tpl->getNewTicketAlertMsgTemplate())) {
    
                $msg = $this->replaceVars($msg->asArray(), array('message' => $message));
    
    Jared Hancock's avatar
    Jared Hancock committed
                $recipients=$sentlist=array();
    
                //Exclude the auto responding email just incase it's from staff member.
    
                if ($message->isAutoReply())
    
                    $sentlist[] = $this->getEmail();
    
    
    Jared Hancock's avatar
    Jared Hancock committed
                //Alert admin??
                if($cfg->alertAdminONNewTicket()) {
    
                    $alert = $this->replaceVars($msg, array('recipient' => 'Admin'));
                    $email->sendAlert($cfg->getAdminEmail(), $alert['subj'], $alert['body'], null, $options);
    
    Jared Hancock's avatar
    Jared Hancock committed
                    $sentlist[]=$cfg->getAdminEmail();
                }
    
    Jared Hancock's avatar
    Jared Hancock committed
                //Only alerts dept members if the ticket is NOT assigned.
                if($cfg->alertDeptMembersONNewTicket() && !$this->isAssigned()) {
    
    Peter Rotich's avatar
    Peter Rotich committed
                    if(($members=$dept->getMembers()))
    
    Jared Hancock's avatar
    Jared Hancock committed
                        $recipients=array_merge($recipients, $members);
                }
    
    Jared Hancock's avatar
    Jared Hancock committed
                if($cfg->alertDeptManagerONNewTicket() && $dept && ($manager=$dept->getManager()))
                    $recipients[]= $manager;
    
    
                foreach( $recipients as $k=>$staff) {
                    if(!is_object($staff) || !$staff->isAvailable() || in_array($staff->getEmail(), $sentlist)) continue;
    
                    $alert = $this->replaceVars($msg, array('recipient' => $staff));
                    $email->sendAlert($staff->getEmail(), $alert['subj'], $alert['body'], null, $options);
    
    Peter Rotich's avatar
    Peter Rotich committed
                    $sentlist[] = $staff->getEmail();
    
    Jared Hancock's avatar
    Jared Hancock committed
            return true;
        }
    
    
        function onOpenLimit($sendNotice=true) {
    
    
            //Log the limit notice as a warning for admin.
            $msg=sprintf('Max open tickets (%d) reached  for %s ', $cfg->getMaxOpenTickets(), $this->getEmail());
    
            $ost->logWarning('Max. Open Tickets Limit ('.$this->getEmail().')', $msg);
    
            if(!$sendNotice || !$cfg->sendOverLimitNotice())
                return true;
    
    
            //Send notice to user.
    
            if(($dept = $this->getDept())
                && ($tpl=$dept->getTemplate())
                && ($msg=$tpl->getOverlimitMsgTemplate())
                && ($email=$dept->getAutoRespEmail())) {
    
                $msg = $this->replaceVars($msg->asArray(),
    
                            array('signature' => ($dept && $dept->isPublic())?$dept->getSignature():''));
    
                $email->sendAutoReply($this->getEmail(), $msg['subj'], $msg['body']);
    
            $user = $this->getOwner();
    
            //Alert admin...this might be spammy (no option to disable)...but it is helpful..I think.
    
            $alert='Max. open tickets reached for '.$this->getEmail()."\n"
    
                  .'Open ticket: '.$user->getNumOpenTickets()."\n"
    
                  .'Max Allowed: '.$cfg->getMaxOpenTickets()."\n\nNotice sent to the user.";
    
            $ost->alertAdmin('Overlimit Notice', $alert);
    
            return true;
        }
    
    
            db_query('UPDATE '.TICKET_TABLE.' SET isanswered=1, lastresponse=NOW(), updated=NOW() WHERE ticket_id='.db_input($this->getId()));
            $this->reload();
        }
    
    
        /*
         * Notify collaborators on response or new message
         *
         */
    
    
        function  notifyCollaborators($entry, $vars = array()) {
    
            if (!$entry instanceof ThreadEntry
    
                    || !($recipients=$this->getRecipients())
    
                    || !($dept=$this->getDept())