1 | <?php
|
2 | /**
|
3 | * ###############################################
|
4 | *
|
5 | * SWIFT Framework
|
6 | * _______________________________________________
|
7 | *
|
8 | * @author Varun Shoor
|
9 | *
|
10 | * @package SWIFT
|
11 | * @copyright Copyright (c) 2001-2012, Kayako
|
12 | * @license http://www.kayako.com/license
|
13 | * @link http://www.kayako.com
|
14 | *
|
15 | * ###############################################
|
16 | */
|
17 |
|
18 | /**
|
19 | * The Ticket Model Class
|
20 | *
|
21 | * @author Varun Shoor
|
22 | */
|
23 | class SWIFT_Ticket extends SWIFT_Model
|
24 | {
|
25 | const TABLE_NAME = 'tickets';
|
26 | const PRIMARY_KEY = 'ticketid';
|
27 |
|
28 | const TABLE_STRUCTURE = "ticketid I PRIMARY AUTO NOTNULL,
|
29 | ticketmaskid C(20) DEFAULT '' NOTNULL,
|
30 | departmentid I DEFAULT '0' NOTNULL,
|
31 | departmenttitle C(255) DEFAULT '' NOTNULL,
|
32 | ticketstatusid I DEFAULT '0' NOTNULL,
|
33 | ticketstatustitle C(255) DEFAULT '' NOTNULL,
|
34 | priorityid I DEFAULT '0' NOTNULL,
|
35 | prioritytitle C(255) DEFAULT '' NOTNULL,
|
36 | emailqueueid I DEFAULT '0' NOTNULL,
|
37 | userid I DEFAULT '0' NOTNULL,
|
38 | staffid I DEFAULT '0' NOTNULL,
|
39 | ownerstaffid I DEFAULT '0' NOTNULL,
|
40 | ownerstaffname C(255) DEFAULT '' NOTNULL,
|
41 | assignstatus I2 DEFAULT '0' NOTNULL,
|
42 |
|
43 | fullname C(225) DEFAULT '' NOTNULL,
|
44 | email C(150) DEFAULT '' NOTNULL,
|
45 | lastreplier C(255) DEFAULT '' NOTNULL,
|
46 | replyto C(150) DEFAULT '' NOTNULL,
|
47 | subject C(255) DEFAULT '' NOTNULL,
|
48 | dateline I DEFAULT '0' NOTNULL,
|
49 | lastactivity I DEFAULT '0' NOTNULL,
|
50 | laststaffreplytime I DEFAULT '0' NOTNULL,
|
51 | lastuserreplytime I DEFAULT '0' NOTNULL,
|
52 | slaplanid I DEFAULT '0' NOTNULL,
|
53 | ticketslaplanid I DEFAULT '0' NOTNULL,
|
54 | duetime I DEFAULT '0' NOTNULL,
|
55 | totalreplies I DEFAULT '0' NOTNULL,
|
56 | ipaddress C(50) DEFAULT '0.0.0.0' NOTNULL,
|
57 | flagtype I2 DEFAULT '0' NOTNULL,
|
58 | hasnotes I2 DEFAULT '0' NOTNULL,
|
59 | hasattachments I2 DEFAULT '0' NOTNULL,
|
60 | isemailed I2 DEFAULT '0' NOTNULL,
|
61 | edited I2 DEFAULT '0' NOTNULL,
|
62 | editedbystaffid I DEFAULT '0' NOTNULL,
|
63 | editeddateline I DEFAULT '0' NOTNULL,
|
64 | creator I2 DEFAULT '0' NOTNULL,
|
65 | charset C(100) DEFAULT '' NOTNULL,
|
66 | transferencoding C(50) DEFAULT '' NOTNULL,
|
67 | timeworked I DEFAULT '0' NOTNULL,
|
68 | timebilled I DEFAULT '0' NOTNULL,
|
69 | dateicon I DEFAULT '0' NOTNULL,
|
70 | lastpostid I DEFAULT '0' NOTNULL,
|
71 | firstpostid I DEFAULT '0' NOTNULL,
|
72 | tgroupid I DEFAULT '0' NOTNULL,
|
73 | messageid C(17) DEFAULT '' NOTNULL,
|
74 | escalationruleid I DEFAULT '0' NOTNULL,
|
75 | hasdraft I2 DEFAULT '0' NOTNULL,
|
76 | hasbilling I2 DEFAULT '0' NOTNULL,
|
77 | isphonecall I2 DEFAULT '0' NOTNULL,
|
78 | isescalated I2 DEFAULT '0' NOTNULL,
|
79 | isescalatedvolatile I2 DEFAULT '0' NOTNULL,
|
80 | phoneno C(255) DEFAULT '' NOTNULL,
|
81 |
|
82 | isautoclosed I2 DEFAULT '0' NOTNULL,
|
83 | autocloseruleid I DEFAULT '0' NOTNULL,
|
84 | autoclosestatus I2 DEFAULT '0' NOTNULL,
|
85 | autoclosetimeline I DEFAULT '0' NOTNULL,
|
86 |
|
87 | escalatedtime I DEFAULT '0' NOTNULL,
|
88 | followupcount I DEFAULT '0' NOTNULL,
|
89 | hasfollowup I2 DEFAULT '0' NOTNULL,
|
90 |
|
91 | hasratings I2 DEFAULT '0' NOTNULL,
|
92 | tickethash C(50) DEFAULT '' NOTNULL,
|
93 | islinked I2 DEFAULT '0' NOTNULL,
|
94 | trasholddepartmentid I DEFAULT '0' NOT NULL,
|
95 | tickettype I2 DEFAULT '0' NOTNULL,
|
96 | tickettypeid I DEFAULT '0' NOTNULL,
|
97 | tickettypetitle C(255) DEFAULT '' NOTNULL,
|
98 | creationmode I2 DEFAULT '0' NOTNULL,
|
99 |
|
100 | isfirstcontactresolved I2 DEFAULT '0' NOTNULL,
|
101 | wasreopened I2 DEFAULT '0' NOTNULL,
|
102 | reopendateline I DEFAULT '0' NOTNULL,
|
103 | resolutiondateline I DEFAULT '0' NOTNULL,
|
104 | escalationlevelcount I DEFAULT '0' NOTNULL,
|
105 | resolutionseconds I DEFAULT '0' NOTNULL,
|
106 | resolutionlevel I DEFAULT '0' NOTNULL,
|
107 | repliestoresolution I DEFAULT '0' NOTNULL,
|
108 |
|
109 | averageresponsetime I DEFAULT '0' NOTNULL,
|
110 | averageresponsetimehits I DEFAULT '0' NOTNULL,
|
111 | firstresponsetime I DEFAULT '0' NOTNULL,
|
112 |
|
113 | resolutionduedateline I DEFAULT '0' NOTNULL,
|
114 | isresolved I2 DEFAULT '0' NOTNULL,
|
115 | iswatched I2 DEFAULT '0' NOTNULL,
|
116 |
|
117 | oldeditemailaddress C(255) DEFAULT '' NOTNULL,
|
118 |
|
119 | linkkbarticleid I DEFAULT '0' NOTNULL,
|
120 | linkticketmacroid I DEFAULT '0' NOTNULL,
|
121 | bayescategoryid I DEFAULT '0' NOTNULL";
|
122 |
|
123 | const INDEX_TICKETCOUNT = 'departmentid, ticketstatusid, ownerstaffid, lastactivity';
|
124 | const INDEX_1 = 'userid, email, replyto, departmentid, isresolved';
|
125 | const INDEX_2 = 'slaplanid, duetime, ticketstatusid';
|
126 | const INDEX_3 = 'departmentid, ticketstatusid, lastactivity';
|
127 | const INDEX_4 = 'email';
|
128 | const INDEX_5 = 'departmentid, ticketstatusid, userid';
|
129 | const INDEX_6 = 'departmentid, ticketstatusid, duetime';
|
130 | const INDEX_7 = 'dateline';
|
131 | const INDEX_8 = 'departmentid, ticketstatusid, lastuserreplytime';
|
132 | const INDEX_9 = 'duetime, resolutionduedateline, isescalatedvolatile, isresolved';
|
133 | const INDEX_10 = 'ticketmaskid, ticketid, departmentid';
|
134 | const INDEX_11 = 'departmentid, ticketstatusid, duetime, resolutionduedateline';
|
135 | const INDEX_12 = 'isresolved, departmentid';
|
136 | const INDEX_13 = 'ticketstatusid, departmentid, priorityid, tickettypeid';
|
137 | const INDEX_14 = 'isescalatedvolatile, isresolved';
|
138 | const INDEX_15 = 'ticketid, departmentid'; // Used by Staff API Protocol
|
139 | const INDEX_16 = 'ticketid, isresolved, autoclosestatus, lastactivity'; // Used by Auto Close
|
140 | const INDEX_17 = 'autoclosestatus, autocloseruleid, autoclosetimeline'; // Used by Auto Close
|
141 | const INDEX_18 = 'lastactivity'; // Unified Search
|
142 |
|
143 |
|
144 | const COLUMN_RENAME_HASBENCHMARKS = 'hasratings';
|
145 |
|
146 | protected $_dataStore = array();
|
147 |
|
148 | // Attachments
|
149 | static protected $_attachmentsContainer = array();
|
150 | static protected $_notificationAttachmentsContainer = array();
|
151 |
|
152 | // Notification Stuff
|
153 | public $Notification = false;
|
154 | public $NotificationManager = false;
|
155 | static protected $_notificationExecutionCache = array();
|
156 |
|
157 | // Workflow Queue Related Variables
|
158 | static protected $_isWorkflowQueueActive = false;
|
159 | static protected $_workflowQueue = array();
|
160 |
|
161 | // Watcher
|
162 | static protected $_watcherPendingCache = array();
|
163 | static protected $_watcherExecutedCache = array();
|
164 | protected $_watchNotificationMessage = '';
|
165 | protected $_lastPostNotificationMessage = '';
|
166 | protected $_watcherCustomName = '';
|
167 |
|
168 | protected $_noAlerts = false;
|
169 |
|
170 | /**
|
171 | * @var bool This property decides whether the SLA calculation has been queued on shutdown
|
172 | */
|
173 | protected $_slaOverdueQueued = -1;
|
174 |
|
175 | /**
|
176 | * @var bool This property is used to prevent the execution of SLA calculation.
|
177 | */
|
178 | protected $_noSLACalculation = false;
|
179 |
|
180 | /**
|
181 | * @var SWIFT_User This property is used to cache the user object
|
182 | */
|
183 | protected $_UserObject = false;
|
184 |
|
185 | /**
|
186 | * @var SWIFT_UserOrganization This property is used to cache the user organization object
|
187 | */
|
188 | protected $_UserOrganizationObject = false;
|
189 |
|
190 | /**
|
191 | * @var SWIFT_UserGroup This property is used to cache the user group object
|
192 | */
|
193 | protected $_UserGroupObject = false;
|
194 |
|
195 | /**
|
196 | * @var bool This property is used to determine the cache flag for the user object
|
197 | */
|
198 | protected $_isUserObjectCached = false;
|
199 |
|
200 | /**
|
201 | * @var bool This property is used to determine the cache flag for the user group object
|
202 | */
|
203 | protected $_isUserGroupObjectCached = false;
|
204 |
|
205 | /**
|
206 | * @var bool This property is used to determine the cache flag for the user organization object
|
207 | */
|
208 | protected $_isUserOrganizationObjectCached = false;
|
209 |
|
210 | /**
|
211 | * @var bool Is used to determine if the status was changed in this object
|
212 | */
|
213 | protected $_hasStatusChanged = false;
|
214 |
|
215 | /**
|
216 | * @var array Is used to keep old Ticket Properties.
|
217 | */
|
218 | protected $_oldTicketProperties = array();
|
219 |
|
220 | // Core Constants
|
221 | const CREATOR_STAFF = 1;
|
222 | const CREATOR_USER = 2;
|
223 | const CREATOR_CLIENT = 2;
|
224 |
|
225 | const CREATIONMODE_SUPPORTCENTER = 1;
|
226 | const CREATIONMODE_STAFFCP = 2;
|
227 | const CREATIONMODE_EMAIL = 3;
|
228 | const CREATIONMODE_API = 4;
|
229 | const CREATIONMODE_SITEBADGE = 5;
|
230 | const CREATIONMODE_MOBILE = 6;
|
231 | const CREATIONMODE_STAFFAPI = 7;
|
232 |
|
233 | const TYPE_DEFAULT = 1;
|
234 | const TYPE_PHONE = 2;
|
235 |
|
236 | const MAIL_NOTIFICATION = 1;
|
237 | const MAIL_CLIENT = 2;
|
238 | const MAIL_THIRDPARTY = 3;
|
239 |
|
240 | const AUTOCLOSESTATUS_NONE = 0;
|
241 | const AUTOCLOSESTATUS_PENDING = 1;
|
242 | const AUTOCLOSESTATUS_CLOSED = 2;
|
243 |
|
244 | /**
|
245 | * Constructor
|
246 | *
|
247 | * @author Varun Shoor
|
248 | * @param SWIFT_Data $_SWIFT_DataObject The SWIFT_Data Object
|
249 | * @return bool "true" on Success, "false" otherwise
|
250 | * @throws SWIFT_Ticket_Exception If the Record could not be loaded
|
251 | */
|
252 | public function __construct(SWIFT_Data $_SWIFT_DataObject)
|
253 | {
|
254 | parent::__construct();
|
255 |
|
256 | if (!$_SWIFT_DataObject instanceof SWIFT_Data || !$_SWIFT_DataObject->GetIsClassLoaded() || !$this->LoadData($_SWIFT_DataObject)) {
|
257 | throw new SWIFT_Ticket_Exception('Failed to load Ticket Object');
|
258 |
|
259 | $this->SetIsClassLoaded(false);
|
260 |
|
261 | return false;
|
262 | }
|
263 |
|
264 | $this->Load->Library('Ticket:TicketManager');
|
265 |
|
266 | $this->Notification = new SWIFT_TicketNotification($this);
|
267 | $this->NotificationManager = new SWIFT_NotificationManager($this);
|
268 |
|
269 | register_shutdown_function(array($this, 'ProcessNotifications'));
|
270 |
|
271 | if ($this->GetProperty('iswatched') == '1') {
|
272 | register_shutdown_function(array($this, 'ProcessWatchers'));
|
273 | }
|
274 |
|
275 | return true;
|
276 | }
|
277 |
|
278 | /**
|
279 | * Destructor
|
280 | *
|
281 | * @author Varun Shoor
|
282 | * @return bool "true" on Success, "false" otherwise
|
283 | */
|
284 | public function __destruct()
|
285 | {
|
286 | chdir(SWIFT_BASEPATH);
|
287 |
|
288 | if ($this->_slaOverdueQueued != -1) {
|
289 | $this->ProcessSLAOverdue($this->_slaOverdueQueued);
|
290 | }
|
291 |
|
292 | if ($this->GetProperty('iswatched') == '1') {
|
293 | $this->ProcessWatchers();
|
294 | }
|
295 |
|
296 | $this->ProcessUpdatePool();
|
297 |
|
298 | parent::__destruct();
|
299 |
|
300 | return true;
|
301 | }
|
302 |
|
303 | /**
|
304 | * Execute SLA If pending
|
305 | *
|
306 | * @author Varun Shoor
|
307 | * @param bool $_processResolutionDue (OPTIONAL) Whether to process the resolution due dateline
|
308 | * @param bool $_dontQueue (OPTIONAL) Dont queue the SLA execution
|
309 | * @return bool "true" on Success, "false" otherwise
|
310 | * @throws SWIFT_Exception If the Class is not Loaded
|
311 | */
|
312 | public function ExecuteSLA($_processResolutionDue = true, $_dontQueue = false) {
|
313 | if (!$this->GetIsClassLoaded()) {
|
314 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
315 |
|
316 | return false;
|
317 | }
|
318 |
|
319 | $this->ProcessUpdatePool();
|
320 |
|
321 | if ($this->_slaOverdueQueued != -1 || $_dontQueue == true) {
|
322 | $this->ProcessSLAOverdue($_processResolutionDue);
|
323 |
|
324 | if ($_dontQueue) {
|
325 | $this->ProcessUpdatePool();
|
326 | }
|
327 | } else {
|
328 | $this->QueueSLAOverdue($_processResolutionDue);
|
329 | }
|
330 |
|
331 | return true;
|
332 | }
|
333 |
|
334 | /**
|
335 | * Processes the Update Pool Data
|
336 | *
|
337 | * @author Varun Shoor
|
338 | * @return bool "true" on Success, "false" otherwise
|
339 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
340 | */
|
341 | public function ProcessUpdatePool()
|
342 | {
|
343 | if (!$this->GetIsClassLoaded()) {
|
344 | return false;
|
345 | } else if (!_is_array($this->GetUpdatePool())) {
|
346 | return false;
|
347 | }
|
348 |
|
349 | $this->Database->AutoExecute(TABLE_PREFIX . 'tickets', $this->GetUpdatePool(), 'UPDATE', "ticketid = '" . intval($this->GetTicketID()) .
|
350 | "'");
|
351 |
|
352 | $this->ClearUpdatePool();
|
353 |
|
354 | return true;
|
355 | }
|
356 |
|
357 | /**
|
358 | * Retrieves the Ticket ID
|
359 | *
|
360 | * @author Varun Shoor
|
361 | * @return mixed "ticketid" on Success, "false" otherwise
|
362 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
363 | */
|
364 | public function GetTicketID()
|
365 | {
|
366 | if (!$this->GetIsClassLoaded())
|
367 | {
|
368 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
369 |
|
370 | return false;
|
371 | }
|
372 |
|
373 | return $this->_dataStore['ticketid'];
|
374 | }
|
375 |
|
376 | /**
|
377 | * Load the Data
|
378 | *
|
379 | * @author Varun Shoor
|
380 | * @param SWIFT_Data $_SWIFT_DataObject The SWIFT_Data Object
|
381 | * @return bool "true" on Success, "false" otherwise
|
382 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
383 | */
|
384 | protected function LoadData($_SWIFT_DataObject)
|
385 | {
|
386 | $_SWIFT = SWIFT::GetInstance();
|
387 |
|
388 | // Is it a ID?
|
389 | if ($_SWIFT_DataObject instanceof SWIFT_DataID && $_SWIFT_DataObject->GetIsClassLoaded())
|
390 | {
|
391 | $_dataStore = $this->Database->QueryFetch("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid = '" .
|
392 | intval($_SWIFT_DataObject->GetDataID()) . "'");
|
393 | if (isset($_dataStore['ticketid']) && !empty($_dataStore['ticketid']))
|
394 | {
|
395 | $this->_dataStore = $_dataStore;
|
396 | $this->_dataStore['displayticketid'] = IIF($_SWIFT->Settings->Get('t_eticketid') == 'seq', $this->_dataStore['ticketid'], $this->_dataStore['ticketmaskid']);
|
397 |
|
398 | return true;
|
399 | }
|
400 |
|
401 | // Is it a Store?
|
402 | } else if ($_SWIFT_DataObject instanceof SWIFT_DataStore && $_SWIFT_DataObject->GetIsClassLoaded()) {
|
403 | $this->_dataStore = $_SWIFT_DataObject->GetDataStore();
|
404 | $this->_dataStore['displayticketid'] = IIF($_SWIFT->Settings->Get('t_eticketid') == 'seq', $this->_dataStore['ticketid'], $this->_dataStore['ticketmaskid']);
|
405 |
|
406 | if (!isset($this->_dataStore['ticketid']) || empty($this->_dataStore['ticketid']))
|
407 | {
|
408 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
409 | }
|
410 |
|
411 | return true;
|
412 | }
|
413 |
|
414 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
415 |
|
416 | return false;
|
417 | }
|
418 |
|
419 | /**
|
420 | * Returns the Data Store Array
|
421 | *
|
422 | * @author Varun Shoor
|
423 | * @return mixed "_dataStore" Array on Success, "false" otherwise
|
424 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
425 | */
|
426 | public function GetDataStore()
|
427 | {
|
428 | if (!$this->GetIsClassLoaded())
|
429 | {
|
430 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
431 |
|
432 | return false;
|
433 | }
|
434 |
|
435 | return $this->_dataStore;
|
436 | }
|
437 |
|
438 | /**
|
439 | * Retrieves a Property Value from Data Store
|
440 | *
|
441 | * @author Varun Shoor
|
442 | * @param string $_key The Key Identifier
|
443 | * @return mixed Property Data on Success, "false" otherwise
|
444 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
445 | */
|
446 | public function GetProperty($_key)
|
447 | {
|
448 | if (!$this->GetIsClassLoaded())
|
449 | {
|
450 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
451 |
|
452 | return false;
|
453 | } else if (!isset($this->_dataStore[$_key])) {
|
454 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
455 |
|
456 | return false;
|
457 | }
|
458 |
|
459 | return $this->_dataStore[$_key];
|
460 | }
|
461 |
|
462 | /**
|
463 | * Check to see if its a valid creator type
|
464 | *
|
465 | * @author Varun Shoor
|
466 | * @param constant $_creatorType The Creator Type
|
467 | * @return bool "true" on Success, "false" otherwise
|
468 | */
|
469 | static public function IsValidCreatorType($_creatorType)
|
470 | {
|
471 | if ($_creatorType == self::CREATOR_STAFF || $_creatorType == self::CREATOR_USER)
|
472 | {
|
473 | return true;
|
474 | }
|
475 |
|
476 | return false;
|
477 | }
|
478 |
|
479 | /**
|
480 | * Check to see if its a valid creation mode
|
481 | *
|
482 | * @author Varun Shoor
|
483 | * @param constant $_creationMode The Creation Mode
|
484 | * @return bool "true" on Success, "false" otherwise
|
485 | */
|
486 | static public function IsValidCreationMode($_creationMode)
|
487 | {
|
488 | if ($_creationMode == self::CREATIONMODE_SUPPORTCENTER || $_creationMode == self::CREATIONMODE_STAFFCP ||
|
489 | $_creationMode == self::CREATIONMODE_EMAIL || $_creationMode == self::CREATIONMODE_API ||
|
490 | $_creationMode == self::CREATIONMODE_SITEBADGE || $_creationMode == self::CREATIONMODE_MOBILE ||
|
491 | $_creationMode == self::CREATIONMODE_STAFFAPI)
|
492 | {
|
493 | return true;
|
494 | }
|
495 |
|
496 | return false;
|
497 | }
|
498 |
|
499 | /**
|
500 | * Check to see if its a valid ticket type
|
501 | *
|
502 | * @author Varun Shoor
|
503 | * @param constant $_ticketType The Ticket Type
|
504 | * @return bool "true" on Success, "false" otherwise
|
505 | */
|
506 | static public function IsValidTicketType($_ticketType)
|
507 | {
|
508 | if ($_ticketType == self::TYPE_DEFAULT || $_ticketType == self::TYPE_PHONE)
|
509 | {
|
510 | return true;
|
511 | }
|
512 |
|
513 | return false;
|
514 | }
|
515 |
|
516 | /**
|
517 | * Get or Create a User ID based on given info
|
518 | *
|
519 | * @author Varun Shoor
|
520 | * @param string $_fullName The User Full Name
|
521 | * @param string $_email the User Email
|
522 | * @param int $_userGroupID The User Group ID
|
523 | * @param int $_languageID (OPTIONAL) The Language ID
|
524 | * @param bool $_checkGeoIP (OPTIONAL) Check GeoIP for User
|
525 | * @return int The User ID on Success, "false" otherwise
|
526 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
527 | */
|
528 | static public function GetOrCreateUserID($_fullName, $_email, $_userGroupID, $_languageID = false, $_checkGeoIP = false) {
|
529 | $_SWIFT = SWIFT::GetInstance();
|
530 |
|
531 | // User processing.. no user specified?
|
532 | $_userIDFromEmail = SWIFT_UserEmail::RetrieveUserIDOnUserEmail($_email);
|
533 |
|
534 | $_userID = false;
|
535 | if (!empty($_userIDFromEmail)) {
|
536 | $_userID = $_userIDFromEmail;
|
537 | } else {
|
538 | $_SWIFT_UserObject = SWIFT_User::Create($_userGroupID, false, SWIFT_User::SALUTATION_NONE, $_fullName, '', '', true,
|
539 | false, array($_email), false, $_languageID, false, false, false, false, false, true, true, $_checkGeoIP);
|
540 |
|
541 | $_userID = $_SWIFT_UserObject->GetUserID();
|
542 | }
|
543 |
|
544 | return $_userID;
|
545 | }
|
546 |
|
547 | /**
|
548 | * Create a new Ticket
|
549 | *
|
550 | * @author Varun Shoor
|
551 | * @param string $_subject The Ticket Subject
|
552 | * @param string $_fullName The Full Name of Creator
|
553 | * @param string $_email The Email of Creator
|
554 | * @param string $_contents The Ticket Contents
|
555 | * @param int $_departmentID The Department ID
|
556 | * @param int $_ticketStatusID The Ticket Status ID
|
557 | * @param int $_ticketPriorityID The Ticket Priority ID
|
558 | * @param int $_ticketTypeID The Ticket Type ID
|
559 | * @param int $_userID The User ID (If creator is user)
|
560 | * @param int $_staffID The Staff ID (If creator is staff)
|
561 | * @param constant $_ticketType The Ticket Type (Default/Phone)
|
562 | * @param constant $_creatorType The Creator Type
|
563 | * @param constant $_creationMode The Creation Mode
|
564 | * @param string $_phoneNumber (OPTIONAL) The Phone Number of User
|
565 | * @param int $_emailQueueID (OPTIONAL) The Email Queue ID
|
566 | * @param bool $_dispatchAutoResponder (OPTIONAL) Whether to dispatch the autoresponder msg
|
567 | * @param string $_emailTo (OPTIONAL) Only to be used when creating tickets from staff cp and using send mail option. Signifies the destination email address.
|
568 | * @param bool $_isPrivate (OPTIONAL) Whether private ticket post
|
569 | * @return mixed "_SWIFT_TicketObject" (OBJECT) on Success, "false" otherwise
|
570 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided or If the Object could not be created
|
571 | */
|
572 | static public function Create($_subject, $_fullName, $_email, $_contents, $_departmentID, $_ticketStatusID, $_ticketPriorityID, $_ticketTypeID,
|
573 | $_userID, $_staffID, $_ticketType, $_creatorType, $_creationMode, $_phoneNumber = '', $_emailQueueID = 0, $_dispatchAutoResponder = true,
|
574 | $_emailTo = '', $_isHTML = false, $_date = DATENOW, $_isPrivate = false)
|
575 | {
|
576 | $_SWIFT = SWIFT::GetInstance();
|
577 |
|
578 | $_departmentID = intval($_departmentID);
|
579 | $_ticketStatusID = intval($_ticketStatusID);
|
580 | $_ticketPriorityID = intval($_ticketPriorityID);
|
581 | $_userID = intval($_userID);
|
582 | $_ticketTypeID = intval($_ticketTypeID);
|
583 |
|
584 | $_ticketTypeCache = $_SWIFT->Cache->Get('tickettypecache');
|
585 | if(empty($_ticketTypeID)) {
|
586 | // Set default ticket type ID
|
587 | foreach ($_ticketTypeCache as $_ticketTypeID => $_ticketTypeContainer) {
|
588 | break;
|
589 | }
|
590 |
|
591 | }
|
592 |
|
593 | if ($_subject == '' || empty($_fullName) || empty($_email) || $_contents == '' || empty($_departmentID) || empty($_ticketStatusID) || !self::IsValidCreatorType($_creatorType)
|
594 | || !self::IsValidCreationMode($_creationMode) || !self::IsValidTicketType($_ticketType))
|
595 | {
|
596 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
597 |
|
598 | return false;
|
599 | }
|
600 |
|
601 |
|
602 | // Sanity check.. IMPORTANT
|
603 | $_departmentCache = $_SWIFT->Cache->Get('departmentcache');
|
604 | $_ticketStatusCache = $_SWIFT->Cache->Get('statuscache');
|
605 | $_ticketPriorityCache = $_SWIFT->Cache->Get('prioritycache');
|
606 |
|
607 | if (!isset($_departmentCache[$_departmentID]) || !isset($_ticketStatusCache[$_ticketStatusID]) ||
|
608 | !isset($_ticketPriorityCache[$_ticketPriorityID]) || !isset($_ticketTypeCache[$_ticketTypeID])) {
|
609 | throw new SWIFT_Ticket_Exception('Invalid Core Data: Department, Status, Priority, Type');
|
610 | } else if ($_departmentCache[$_departmentID]['departmentapp'] != APP_TICKETS) {
|
611 | throw new SWIFT_Ticket_Exception('Invalid Department App');
|
612 | }
|
613 |
|
614 | $_ticketMaskID = GenerateUniqueMask();
|
615 |
|
616 | $_isPhoneCall = false;
|
617 | if ($_ticketType == self::TYPE_PHONE)
|
618 | {
|
619 | $_isPhoneCall = true;
|
620 | }
|
621 |
|
622 | $_replyToEmail = $_email;
|
623 | if (!empty($_emailTo))
|
624 | {
|
625 | $_replyToEmail = $_emailTo;
|
626 | }
|
627 |
|
628 | $_isEmailed = false;
|
629 | if ($_creationMode == self::CREATIONMODE_EMAIL)
|
630 | {
|
631 | $_isEmailed = true;
|
632 | }
|
633 |
|
634 | $_ipAddress = '';
|
635 | if ($_SWIFT->Interface->GetInterface() != SWIFT_Interface::INTERFACE_CRON && $_SWIFT->Interface->GetInterface() != SWIFT_Interface::INTERFACE_CONSOLE)
|
636 | {
|
637 | $_ipAddress = SWIFT::Get('IP');
|
638 | }
|
639 |
|
640 | $_SWIFT_BayesianObject = new SWIFT_Bayesian();
|
641 | $_finalBayesCategoryID = 0;
|
642 | $_probabilityContainer = $_SWIFT_BayesianObject->Get($_subject . ' ' . $_contents);
|
643 | if (_is_array($_probabilityContainer))
|
644 | {
|
645 | $_finalBayesBenchmark = 0;
|
646 | foreach ($_probabilityContainer[0] as $_bayesCategoryID => $_probability)
|
647 | {
|
648 | if ($_probability['combined'] >= 0.500 && $_probability['combined'] > $_finalBayesBenchmark)
|
649 | {
|
650 | $_finalBayesCategoryID = $_bayesCategoryID;
|
651 | $_finalBayesBenchmark = $_probability['combined'];
|
652 | }
|
653 | }
|
654 | }
|
655 |
|
656 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('ticketmaskid' => $_ticketMaskID, 'departmentid' => intval($_departmentID),
|
657 | 'ticketstatusid' => intval($_ticketStatusID), 'priorityid' => intval($_ticketPriorityID), 'emailqueueid' => intval($_emailQueueID),
|
658 | 'userid' => intval($_userID), 'staffid' => intval($_staffID), 'fullname' => $_fullName, 'email' => mb_strtolower($_email), 'lastreplier' => $_fullName,
|
659 | 'replyto' => $_replyToEmail, 'subject' => $_subject, 'dateline' => $_date, 'lastactivity' => DATENOW, 'ipaddress' => $_ipAddress,
|
660 | 'isemailed' => intval($_isEmailed), 'isphonecall' => intval($_isPhoneCall), 'creator' => intval($_creatorType),
|
661 | 'tickettype' => intval($_ticketType), 'phoneno' => $_phoneNumber, 'tickettypeid' => intval($_ticketTypeID), 'tickethash' => substr(BuildHash(), 0, 12),
|
662 | 'creationmode' => intval($_creationMode), 'bayescategoryid' => intval($_finalBayesCategoryID)), 'INSERT');
|
663 | $_ticketID = $_SWIFT->Database->Insert_ID();
|
664 |
|
665 | if (!$_ticketID)
|
666 | {
|
667 | throw new SWIFT_Ticket_Exception(SWIFT_CREATEFAILED);
|
668 |
|
669 | return false;
|
670 | }
|
671 |
|
672 | $_SWIFT_TicketObject = new SWIFT_Ticket(new SWIFT_DataID($_ticketID));
|
673 | if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded())
|
674 | {
|
675 | throw new SWIFT_Ticket_Exception(SWIFT_CREATEFAILED);
|
676 |
|
677 | return false;
|
678 | }
|
679 |
|
680 | $_departmentTitle = $_departmentCache[$_departmentID]['title'];
|
681 | $_statusTitle = $_ticketStatusCache[$_ticketStatusID]['title'];
|
682 | $_typeTitle = $_ticketTypeCache[$_ticketTypeID]['title'];
|
683 | $_priorityTitle = $_ticketPriorityCache[$_ticketPriorityID]['title'];
|
684 |
|
685 | $_SWIFT_TicketObject->UpdatePool('departmenttitle', $_departmentTitle);
|
686 | $_SWIFT_TicketObject->UpdatePool('ticketstatustitle', $_statusTitle);
|
687 | $_SWIFT_TicketObject->UpdatePool('tickettypetitle', $_typeTitle);
|
688 | $_SWIFT_TicketObject->UpdatePool('prioritytitle', $_priorityTitle);
|
689 |
|
690 | // Create the ticket post..
|
691 | $_creatorID = $_staffID;
|
692 | if ($_creatorType == self::CREATOR_CLIENT) {
|
693 | $_creatorID = $_userID;
|
694 | }
|
695 |
|
696 | // Get Email Queue Name
|
697 | $_emailQueueCache = $_SWIFT->Cache->Get('queuecache');
|
698 | $_emailQueueAddress = '';
|
699 | if (isset($_emailQueueCache['list'][$_emailQueueID])) {
|
700 | $_emailQueueAddress = $_emailQueueCache['list'][$_emailQueueID]['email'];
|
701 | }
|
702 |
|
703 | // Create Audit Log
|
704 |
|
705 | /*
|
706 | * BUG FIX - Varun Shoor
|
707 | *
|
708 | * SWIFT-1657 Audit Log does not show email queue address via which ticket is created
|
709 | *
|
710 | * Comments: None
|
711 | */
|
712 | if (!empty($_emailQueueAddress)) {
|
713 | SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_NEWTICKET, sprintf($_SWIFT->Language->Get('al_newticket_queue'), $_fullName, $_email, $_subject, $_emailQueueAddress),
|
714 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
715 | } else {
|
716 | SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_NEWTICKET, sprintf($_SWIFT->Language->Get('al_newticket'), $_fullName, $_email, $_subject),
|
717 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
718 | }
|
719 |
|
720 | $_ticketPostID = SWIFT_TicketPost::Create($_SWIFT_TicketObject, $_fullName, $_email, $_contents, $_creatorType, $_creatorID, $_creationMode,
|
721 | $_subject, $_emailTo, $_isHTML, false, false, $_date, $_isPrivate);
|
722 |
|
723 | $_SWIFT_TicketObject->UpdatePool('firstpostid', $_ticketPostID);
|
724 | $_SWIFT_TicketObject->UpdatePool('lastpostid', $_ticketPostID);
|
725 | $_SWIFT_TicketObject->UpdatePool('totalreplies', '0');
|
726 |
|
727 |
|
728 | /*
|
729 | * BUG FIX - Varun Shoor
|
730 | *
|
731 | * SWIFT-965 When a new ticket is created with status "closed", 'Clear due time' setting does not work
|
732 | *
|
733 | * Comments: None
|
734 | */
|
735 |
|
736 | // SLA & Status Properties
|
737 | $_ticketStatusContainer = $_ticketStatusCache[$_ticketStatusID];
|
738 | if ($_ticketStatusContainer['resetduetime'] == '1') {
|
739 | $_SWIFT_TicketObject->UpdatePool('duetime', '0');
|
740 | $_SWIFT_TicketObject->_noSLACalculation = true;
|
741 | }
|
742 |
|
743 | if ($_ticketStatusContainer['markasresolved'] == '1')
|
744 | {
|
745 | $_SWIFT_TicketObject->UpdatePool('isresolved', '1');
|
746 | $_SWIFT_TicketObject->UpdatePool('resolutiondateline', DATENOW);
|
747 | $_SWIFT_TicketObject->UpdatePool('repliestoresolution', $_SWIFT_TicketObject->GetProperty('totalreplies'));
|
748 |
|
749 | // How much time did it take to resolve this ticket?
|
750 | $_SWIFT_TicketObject->UpdatePool('resolutionseconds', DATENOW-$_SWIFT_TicketObject->GetProperty('dateline'));
|
751 | }
|
752 |
|
753 | // If the status is set to resolved then we reset the resolution due time
|
754 | $_processResolutionDue = false;
|
755 | if ($_ticketStatusContainer['markasresolved'] == '1') {
|
756 | $_SWIFT_TicketObject->UpdatePool('resolutionduedateline', '0');
|
757 | $_SWIFT_TicketObject->UpdatePool('duetime', '0');
|
758 |
|
759 | $_SWIFT_TicketObject->_noSLACalculation = true;
|
760 |
|
761 | // Otherwise if its not, and resolutionduedateline is 0 then we force it to recalculate the resolution due time
|
762 | } else if ($_ticketStatusContainer['markasresolved'] == '0' && $_SWIFT_TicketObject->GetProperty('resolutionduedateline') == '0') {
|
763 | $_processResolutionDue = true;
|
764 | }
|
765 |
|
766 | $_SWIFT_TicketObject->ProcessSLAOverdue($_processResolutionDue);
|
767 |
|
768 | // Notification Event
|
769 | $_SWIFT_TicketObject->NotificationManager->SetEvent('newticket');
|
770 |
|
771 | // Load and Process Workflow Rules
|
772 | self::AddToWorkflowQueue($_SWIFT_TicketObject);
|
773 |
|
774 | // Recount the cache
|
775 | SWIFT_TicketManager::Recount(false);
|
776 |
|
777 | if ($_dispatchAutoResponder == true)
|
778 | {
|
779 | $_SWIFT_TicketObject->DispatchAutoresponder();
|
780 | }
|
781 |
|
782 | return $_SWIFT_TicketObject;
|
783 | }
|
784 |
|
785 | /**
|
786 | * Update the Ticket Record
|
787 | *
|
788 | * @author Varun Shoor
|
789 | * @param string $_subject The Ticket Subject
|
790 | * @param string $_fullName The Ticket Fullname
|
791 | * @param string $_email The Ticket Email
|
792 | * @return bool "true" on Success, "false" otherwise
|
793 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
794 | */
|
795 | public function Update($_subject, $_fullName, $_email)
|
796 | {
|
797 | $_SWIFT = SWIFT::GetInstance();
|
798 |
|
799 | if (!$this->GetIsClassLoaded())
|
800 | {
|
801 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
802 |
|
803 | return false;
|
804 | }
|
805 |
|
806 | // Create Audit Log
|
807 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
|
808 | sprintf($_SWIFT->Language->Get('al_updateproperties'), StripName($this->GetProperty('subject'), 60), StripName($_subject, 60), StripName($this->GetProperty('fullname'), 30),
|
809 | StripName($_fullName, 30), StripName($this->GetProperty('email'), 40), StripName($_email, 40)), SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
810 |
|
811 | $this->UpdatePool('subject', $_subject);
|
812 | $this->UpdatePool('fullname', $_fullName);
|
813 |
|
814 | $_ticketEmailAddress = $this->GetProperty('email');
|
815 | if ($this->GetProperty('replyto') != '')
|
816 | {
|
817 | $_ticketEmailAddress = $this->GetProperty('replyto');
|
818 | }
|
819 |
|
820 | $this->UpdatePool('oldeditemailaddress', $_ticketEmailAddress);
|
821 | $this->UpdatePool('email', $_email);
|
822 | $this->UpdatePool('replyto', $_email);
|
823 |
|
824 | // Load and Process Workflow Rules
|
825 | self::AddToWorkflowQueue($this);
|
826 |
|
827 | return true;
|
828 | }
|
829 |
|
830 | /**
|
831 | * Delete the Ticket record
|
832 | *
|
833 | * @author Varun Shoor
|
834 | * @return bool "true" on Success, "false" otherwise
|
835 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
836 | */
|
837 | public function Delete()
|
838 | {
|
839 | if (!$this->GetIsClassLoaded())
|
840 | {
|
841 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
842 |
|
843 | return false;
|
844 | }
|
845 |
|
846 | self::DeleteList(array($this->GetTicketID()));
|
847 |
|
848 | $this->SetIsClassLoaded(false);
|
849 |
|
850 | return true;
|
851 | }
|
852 |
|
853 | /**
|
854 | * Delete a list of Tickets
|
855 | *
|
856 | * @author Varun Shoor
|
857 | * @param array $_ticketIDList The Ticket ID List
|
858 | * @return bool "true" on Success, "false" otherwise
|
859 | */
|
860 | static public function DeleteList($_ticketIDList)
|
861 | {
|
862 | $_SWIFT = SWIFT::GetInstance();
|
863 |
|
864 | if (!_is_array($_ticketIDList))
|
865 | {
|
866 | return false;
|
867 | }
|
868 |
|
869 | $_finalTicketIDList = $_departmentIDList = array();
|
870 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
871 | while ($_SWIFT->Database->NextRecord())
|
872 | {
|
873 | $_finalTicketIDList[] = intval($_SWIFT->Database->Record['ticketid']);
|
874 |
|
875 | $_departmentIDList[] = intval($_SWIFT->Database->Record['departmentid']);
|
876 |
|
877 | $_SWIFT_TicketObject = new SWIFT_Ticket(new SWIFT_DataSTore($_SWIFT->Database->Record));
|
878 |
|
879 | // Create Audit Log
|
880 | SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_DELETETICKET,
|
881 | sprintf($_SWIFT->Language->Get('al_deleteticket'), $_SWIFT_TicketObject->GetTicketDisplayID(), $_SWIFT->Database->Record['subject'],
|
882 | $_SWIFT->Database->Record['fullname'], $_SWIFT->Database->Record['email']),
|
883 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
884 | }
|
885 |
|
886 | if (!count($_finalTicketIDList))
|
887 | {
|
888 | return false;
|
889 | }
|
890 |
|
891 | $_SWIFT->Database->Query("DELETE FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_finalTicketIDList) . ")");
|
892 |
|
893 | // Clear Ticket Posts
|
894 | SWIFT_TicketPost::DeleteOnTicket($_finalTicketIDList);
|
895 |
|
896 | // Clear Attachments
|
897 | SWIFT_Attachment::DeleteOnTicket($_finalTicketIDList);
|
898 |
|
899 | // Clear Notes
|
900 | SWIFT_TicketNote::DeleteOnTicket($_finalTicketIDList);
|
901 |
|
902 | // Clear Ticket Drafts
|
903 | SWIFT_TicketDraft::DeleteOnTicket($_finalTicketIDList);
|
904 |
|
905 | // Release the Locks
|
906 | SWIFT_TicketLock::DeleteOnTicket($_finalTicketIDList);
|
907 | SWIFT_TicketPostLock::DeleteOnTicket($_finalTicketIDList);
|
908 |
|
909 | // Clear the Recipients
|
910 | SWIFT_TicketRecipient::DeleteOnTicket($_finalTicketIDList);
|
911 |
|
912 | // Clear the Audit Logs
|
913 | SWIFT_TicketAuditLog::DeleteOnTicket($_finalTicketIDList);
|
914 |
|
915 | // Clear the Time Track entries
|
916 | SWIFT_TicketTimeTrack::DeleteOnTicket($_finalTicketIDList);
|
917 |
|
918 | // Clear the Message IDs
|
919 | SWIFT_TicketMessageID::DeleteOnTicket($_finalTicketIDList);
|
920 |
|
921 | // Clear the Linked Table IDs
|
922 | SWIFT_TicketLinkedTable::DeleteOnTicket($_finalTicketIDList);
|
923 |
|
924 | // Clear the ticket watchers
|
925 | SWIFT_TicketWatcher::DeleteOnTicket($_finalTicketIDList);
|
926 |
|
927 | // Clear the chains
|
928 | SWIFT_TicketLinkChain::DeleteOnTicket($_finalTicketIDList);
|
929 |
|
930 | // Delete the merge logs
|
931 | SWIFT_TicketMergeLog::DeleteOnTicket($_finalTicketIDList);
|
932 |
|
933 | // Delete the Ticket Follow-Up's
|
934 | SWIFT_TicketFollowUp::DeleteOnTicket($_finalTicketIDList);
|
935 |
|
936 | // Delete the Ticket Escalation Paths
|
937 | SWIFT_EscalationPath::DeleteOnTicket($_finalTicketIDList);
|
938 |
|
939 | // Delete the Ticket Recurrence
|
940 | SWIFT_TicketRecurrence::DeleteOnTicket($_finalTicketIDList);
|
941 |
|
942 | // Delete the tags
|
943 | SWIFT_TagLink::DeleteOnLinkList(SWIFT_TagLink::TYPE_TICKET, $_finalTicketIDList);
|
944 |
|
945 | // Rebuild count cache
|
946 | SWIFT_TicketManager::RebuildCache();
|
947 |
|
948 | return true;
|
949 | }
|
950 |
|
951 | /**
|
952 | * Un-Delete a list of Tickets
|
953 | *
|
954 | * @author Varun Shoor
|
955 | * @param array $_ticketIDList The Ticket ID List
|
956 | * @return bool "true" on Success, "false" otherwise
|
957 | */
|
958 | static public function UnDeleteList($_ticketIDList)
|
959 | {
|
960 | $_SWIFT = SWIFT::GetInstance();
|
961 |
|
962 | if (!_is_array($_ticketIDList))
|
963 | {
|
964 | return false;
|
965 | }
|
966 |
|
967 | $_finalTicketIDList = $_departmentIDList = $_ticketContainer = array();
|
968 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
969 | while ($_SWIFT->Database->NextRecord())
|
970 | {
|
971 | $_ticketContainer[$_SWIFT->Database->Record['ticketid']] = $_SWIFT->Database->Record;
|
972 |
|
973 | $_finalTicketIDList[] = intval($_SWIFT->Database->Record['ticketid']);
|
974 |
|
975 | $_departmentIDList[] = intval($_SWIFT->Database->Record['departmentid']);
|
976 |
|
977 | $_SWIFT_TicketObject = new SWIFT_Ticket(new SWIFT_DataSTore($_SWIFT->Database->Record));
|
978 |
|
979 | // Create Audit Log
|
980 | SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_DELETETICKET,
|
981 | sprintf($_SWIFT->Language->Get('al_untrashticket'), $_SWIFT_TicketObject->GetTicketDisplayID(), $_SWIFT->Database->Record['subject'],
|
982 | $_SWIFT->Database->Record['fullname'], $_SWIFT->Database->Record['email']),
|
983 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
984 | }
|
985 |
|
986 | if (!count($_finalTicketIDList))
|
987 | {
|
988 | return false;
|
989 | }
|
990 |
|
991 | foreach ($_finalTicketIDList as $_ticketID)
|
992 | {
|
993 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('departmentid' => intval($_ticketContainer[$_ticketID]['trasholddepartmentid'])), 'UPDATE', "ticketid = '" . intval($_ticketID) . "'");
|
994 | }
|
995 |
|
996 | // Rebuild count cache
|
997 | SWIFT_TicketManager::RebuildCache();
|
998 |
|
999 | return true;
|
1000 | }
|
1001 |
|
1002 | /**
|
1003 | * Merge a list of tickets together
|
1004 | *
|
1005 | * @author Varun Shoor
|
1006 | * @param array $_ticketIDList The Ticket ID List
|
1007 | * @param int $_parentTicketID (OPTIONAL) The Parent Ticket ID
|
1008 | * @return bool "true" on Success, "false" otherwise
|
1009 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
1010 | */
|
1011 | static public function Merge($_ticketIDList, $_parentTicketID = false, $_staffID = false) {
|
1012 | $_SWIFT = SWIFT::GetInstance();
|
1013 |
|
1014 | if (!_is_array($_ticketIDList) || (count($_ticketIDList) < 2 && empty($_parentTicketID))) {
|
1015 | return false;
|
1016 | }
|
1017 |
|
1018 | $_departmentIDList = $_ticketMaskIDList = $_mergeTicketIDList = $_mergeEmailList = array();
|
1019 |
|
1020 | if (!$_parentTicketID) {
|
1021 | $_parentTicketID = $_ticketIDList[0];
|
1022 | }
|
1023 |
|
1024 | // Load the parent ticket
|
1025 | $_SWIFT_ParentTicketObject = new SWIFT_Ticket(new SWIFT_DataID($_parentTicketID));
|
1026 | if (!$_SWIFT_ParentTicketObject instanceof SWIFT_Ticket || !$_SWIFT_ParentTicketObject->GetIsClassLoaded()) {
|
1027 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
1028 | }
|
1029 |
|
1030 | $_departmentIDList[] = $_SWIFT_ParentTicketObject->GetProperty('departmentid');
|
1031 |
|
1032 | // Load the other objects
|
1033 | $_ticketObjectContainer = array();
|
1034 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
1035 | while ($_SWIFT->Database->NextRecord()) {
|
1036 | if ($_SWIFT->Database->Record['ticketid'] == $_parentTicketID) {
|
1037 | continue;
|
1038 | }
|
1039 |
|
1040 | $_ticketObjectContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
1041 |
|
1042 | // Create Audit Log
|
1043 | $_SWIFT_TicketObject_Merge = $_ticketObjectContainer[$_SWIFT->Database->Record['ticketid']];
|
1044 | SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject_Merge, null, SWIFT_TicketAuditLog::ACTION_MERGETICKET,
|
1045 | sprintf($_SWIFT->Language->Get('al_merge'), $_SWIFT_TicketObject_Merge->GetTicketDisplayID(), $_SWIFT->Database->Record['subject'],
|
1046 | $_SWIFT->Database->Record['fullname'], $_SWIFT->Database->Record['email']),
|
1047 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
1048 |
|
1049 | if (!in_array($_SWIFT->Database->Record['departmentid'], $_departmentIDList)) {
|
1050 | $_departmentIDList[] = $_SWIFT->Database->Record['departmentid'];
|
1051 | }
|
1052 |
|
1053 | $_ticketMaskIDList[] = $_SWIFT->Database->Record['ticketmaskid'];
|
1054 |
|
1055 | $_mergeTicketIDList[] = $_SWIFT->Database->Record['ticketid'];
|
1056 |
|
1057 | if (!in_array($_SWIFT->Database->Record['email'], $_mergeEmailList) &&
|
1058 | $_SWIFT->Database->Record['email'] != $_SWIFT_ParentTicketObject->GetProperty('email')) {
|
1059 | $_mergeEmailList[] = $_SWIFT->Database->Record['email'];
|
1060 | }
|
1061 | }
|
1062 |
|
1063 | /**
|
1064 | * @todo Raise Alert Here
|
1065 | */
|
1066 |
|
1067 | // By now we have the parent ticket and the child tickets, we need to start the merge process now.
|
1068 |
|
1069 | // Update Notes. !! IMPORTANT: This needs to be called before ticket posts are updated. !!
|
1070 | SWIFT_TicketNoteManager::ReplaceTicket($_mergeTicketIDList, $_SWIFT_ParentTicketObject);
|
1071 |
|
1072 | // Update Ticket Posts
|
1073 | SWIFT_TicketPost::ReplaceTicket($_mergeTicketIDList, $_SWIFT_ParentTicketObject);
|
1074 |
|
1075 | // Update Attachments
|
1076 | SWIFT_Attachment::ReplaceTicket($_mergeTicketIDList, $_SWIFT_ParentTicketObject);
|
1077 |
|
1078 | // Update the Recipients
|
1079 | SWIFT_TicketRecipient::ReplaceTicket($_mergeTicketIDList, $_SWIFT_ParentTicketObject);
|
1080 |
|
1081 | // Update the Audit Logs
|
1082 | SWIFT_TicketAuditLog::ReplaceTicket($_mergeTicketIDList, $_SWIFT_ParentTicketObject);
|
1083 |
|
1084 | // Update the Time Track entries
|
1085 | SWIFT_TicketTimeTrack::ReplaceTicket($_mergeTicketIDList, $_SWIFT_ParentTicketObject);
|
1086 |
|
1087 | // Update the Ticket Follow-Up's
|
1088 | SWIFT_TicketFollowUp::ReplaceTicket($_mergeTicketIDList, $_SWIFT_ParentTicketObject);
|
1089 |
|
1090 | // Add all the recipients if needed
|
1091 | if ($_SWIFT->Settings->Get('t_mergrecip') == 1 && count($_mergeEmailList))
|
1092 | {
|
1093 | SWIFT_TicketRecipient::Create($_SWIFT_ParentTicketObject, SWIFT_TicketRecipient::TYPE_CC, $_mergeEmailList);
|
1094 | }
|
1095 |
|
1096 | // Recaclulate all properties
|
1097 | $_SWIFT_ParentTicketObject->RebuildProperties();
|
1098 |
|
1099 | /**
|
1100 | * @todo Add Audit Log Entry
|
1101 | */
|
1102 |
|
1103 | // First add the Merge Log List.. this is used to route replies to the right ticket.
|
1104 | foreach ($_ticketObjectContainer as $_ticketID => $_SWIFT_TicketObject) {
|
1105 | SWIFT_TicketMergeLog::Create($_SWIFT_ParentTicketObject, $_SWIFT_TicketObject->GetTicketID(),
|
1106 | $_SWIFT_TicketObject->GetProperty('ticketmaskid'), $_staffID);
|
1107 | }
|
1108 |
|
1109 | // Delete JUST the ticket entries
|
1110 | $_SWIFT->Database->Query("DELETE FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_mergeTicketIDList) . ")");
|
1111 |
|
1112 | // Clear Ticket Drafts
|
1113 | SWIFT_TicketDraft::DeleteOnTicket($_mergeTicketIDList);
|
1114 |
|
1115 | // Release the Locks
|
1116 | SWIFT_TicketLock::DeleteOnTicket($_mergeTicketIDList);
|
1117 | SWIFT_TicketPostLock::DeleteOnTicket($_mergeTicketIDList);
|
1118 |
|
1119 | // Clear the Message IDs
|
1120 | SWIFT_TicketMessageID::DeleteOnTicket($_mergeTicketIDList);
|
1121 |
|
1122 | // Clear the Linked Table IDs
|
1123 | SWIFT_TicketLinkedTable::DeleteOnTicket($_mergeTicketIDList);
|
1124 |
|
1125 | // Clear the ticket watchers
|
1126 | SWIFT_TicketWatcher::DeleteOnTicket($_mergeTicketIDList);
|
1127 |
|
1128 | // Clear the chains
|
1129 | SWIFT_TicketLinkChain::DeleteOnTicket($_mergeTicketIDList);
|
1130 |
|
1131 | // Delete the Ticket Escalation Paths
|
1132 | SWIFT_EscalationPath::DeleteOnTicket($_mergeTicketIDList);
|
1133 |
|
1134 | // Delete the Ticket Recurrence
|
1135 | SWIFT_TicketRecurrence::DeleteOnTicket($_mergeTicketIDList);
|
1136 |
|
1137 | // Delete the tags
|
1138 | SWIFT_TagLink::DeleteOnLinkList(SWIFT_TagLink::TYPE_TICKET, $_mergeTicketIDList);
|
1139 |
|
1140 | // Time for a recount
|
1141 | SWIFT_TicketManager::RebuildCache();
|
1142 |
|
1143 | return true;
|
1144 | }
|
1145 |
|
1146 | /**
|
1147 | * Move the Ticket record to trash
|
1148 | *
|
1149 | * @author Varun Shoor
|
1150 | * @return bool "true" on Success, "false" otherwise
|
1151 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1152 | */
|
1153 | public function Trash()
|
1154 | {
|
1155 | if (!$this->GetIsClassLoaded())
|
1156 | {
|
1157 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1158 |
|
1159 | return false;
|
1160 | }
|
1161 |
|
1162 | self::TrashList(array($this->GetTicketID()));
|
1163 |
|
1164 | return true;
|
1165 | }
|
1166 |
|
1167 | /**
|
1168 | * Trash a list of Tickets
|
1169 | *
|
1170 | * @author Varun Shoor
|
1171 | * @param array $_ticketIDList The Ticket ID List
|
1172 | * @return bool "true" on Success, "false" otherwise
|
1173 | */
|
1174 | static public function TrashList($_ticketIDList)
|
1175 | {
|
1176 | $_SWIFT = SWIFT::GetInstance();
|
1177 |
|
1178 | if (!_is_array($_ticketIDList))
|
1179 | {
|
1180 | return false;
|
1181 | }
|
1182 |
|
1183 | $_finalTicketIDList = $_departmentIDList = array();
|
1184 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
1185 | while ($_SWIFT->Database->NextRecord())
|
1186 | {
|
1187 | $_SWIFT_TicketObject = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
1188 | $_SWIFT_TicketObject->UpdateTrashDepartment();
|
1189 |
|
1190 | $_finalTicketIDList[] = intval($_SWIFT->Database->Record['ticketid']);
|
1191 |
|
1192 | $_departmentIDList[] = intval($_SWIFT->Database->Record['departmentid']);
|
1193 |
|
1194 | // Create Audit Log
|
1195 | SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_TRASHTICKET,
|
1196 | sprintf($_SWIFT->Language->Get('al_trashticket'), $_SWIFT_TicketObject->GetTicketDisplayID(), $_SWIFT->Database->Record['subject'],
|
1197 | $_SWIFT->Database->Record['fullname'], $_SWIFT->Database->Record['email']),
|
1198 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
1199 | }
|
1200 |
|
1201 | if (!count($_finalTicketIDList))
|
1202 | {
|
1203 | return false;
|
1204 | }
|
1205 |
|
1206 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('departmentid' => '0'), 'UPDATE', "ticketid IN (" .
|
1207 | BuildIN($_finalTicketIDList) . ")");
|
1208 |
|
1209 | // Rebuild count cache
|
1210 | SWIFT_TicketManager::RebuildCache();
|
1211 |
|
1212 | return true;
|
1213 | }
|
1214 |
|
1215 | /**
|
1216 | * Update the trash department
|
1217 | *
|
1218 | * @author Varun Shoor
|
1219 | * @return bool "true" on Success, "false" otherwise
|
1220 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1221 | */
|
1222 | public function UpdateTrashDepartment() {
|
1223 | if (!$this->GetIsClassLoaded()) {
|
1224 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1225 |
|
1226 | return false;
|
1227 | }
|
1228 |
|
1229 | /*
|
1230 | * BUG FIX - Varun Shoor
|
1231 | *
|
1232 | * SWIFT-1781 Help desk is not removing the SLA while moving the tickets in Trash folder
|
1233 | *
|
1234 | */
|
1235 | $this->ClearOverdue();
|
1236 | $this->ClearResolutiondue();
|
1237 | $this->UpdatePool('slaplanid', '0');
|
1238 | $this->UpdatePool('trasholddepartmentid', $this->GetProperty('departmentid'));
|
1239 | $this->ProcessUpdatePool();
|
1240 |
|
1241 | return true;
|
1242 | }
|
1243 |
|
1244 | /**
|
1245 | * Ban the creator of this ticket
|
1246 | *
|
1247 | * @author Varun Shoor
|
1248 | * @return bool "true" on Success, "false" otherwise
|
1249 | * @param int $_staffID (OPTIONAL) The Staff ID initiating the Ban
|
1250 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1251 | */
|
1252 | public function Ban($_staffID = 0)
|
1253 | {
|
1254 | if (!$this->GetIsClassLoaded())
|
1255 | {
|
1256 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1257 |
|
1258 | return false;
|
1259 | }
|
1260 |
|
1261 | self::BanList(array($this->GetTicketID()), $_staffID);
|
1262 |
|
1263 | return true;
|
1264 | }
|
1265 |
|
1266 | /**
|
1267 | * Ban a list of ticket ids
|
1268 | *
|
1269 | * @author Varun Shoor
|
1270 | * @param array $_ticketIDList The Ticket ID List to ban
|
1271 | * @param int $_staffID (OPTIONAL) The Staff ID initiating the Ban
|
1272 | * @return bool "true" on Success, "false" otherwise
|
1273 | */
|
1274 | static public function BanList($_ticketIDList, $_staffID = 0)
|
1275 | {
|
1276 | $_SWIFT = SWIFT::GetInstance();
|
1277 |
|
1278 | if (!_is_array($_ticketIDList))
|
1279 | {
|
1280 | return false;
|
1281 | }
|
1282 |
|
1283 | $_staffCache = $_SWIFT->Cache->Get('staffcache');
|
1284 | $_emailQueueCache = $_SWIFT->Cache->Get('queuecache');
|
1285 | $_rejectEmailList = array();
|
1286 |
|
1287 | foreach ($_staffCache as $_key => $_val)
|
1288 | {
|
1289 | $_rejectEmailList[] = mb_strtolower($_val['email']);
|
1290 | }
|
1291 |
|
1292 | if (_is_array($_emailQueueCache) && isset($_emailQueueCache['list']) && _is_array($_emailQueueCache['list']))
|
1293 | {
|
1294 | foreach ($_emailQueueCache['list'] as $_key => $_val)
|
1295 | {
|
1296 | $_rejectEmailList[] = mb_strtolower($_val['email']);
|
1297 | }
|
1298 | }
|
1299 |
|
1300 | $_finalEmailBanList = array();
|
1301 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
1302 | while ($_SWIFT->Database->NextRecord())
|
1303 | {
|
1304 | $_SWIFT_TicketObject = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
1305 |
|
1306 | // Create Audit Log
|
1307 | SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_BAN,
|
1308 | sprintf($_SWIFT->Language->Get('al_ban'), $_SWIFT_TicketObject->GetTicketDisplayID(), $_SWIFT->Database->Record['email']),
|
1309 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
1310 |
|
1311 | if (!in_array(mb_strtolower($_SWIFT->Database->Record['email']), $_finalEmailBanList) &&
|
1312 | !in_array(mb_strtolower($_SWIFT->Database->Record['email']), $_rejectEmailList))
|
1313 | {
|
1314 | $_finalEmailBanList[] = mb_strtolower($_SWIFT->Database->Record['email']);
|
1315 | }
|
1316 | }
|
1317 |
|
1318 | if (!count($_finalEmailBanList))
|
1319 | {
|
1320 | return false;
|
1321 | }
|
1322 |
|
1323 | SWIFT_Loader::LoadModel('Ban:ParserBan', APP_PARSER);
|
1324 |
|
1325 | if (class_exists('SWIFT_ParserBan', false))
|
1326 | {
|
1327 | foreach ($_finalEmailBanList as $_key => $_val)
|
1328 | {
|
1329 | SWIFT_ParserBan::Create($_val, $_staffID);
|
1330 | }
|
1331 | }
|
1332 |
|
1333 | return true;
|
1334 | }
|
1335 |
|
1336 | /**
|
1337 | * Recaculates the 'hasattachment' property of the given tickets
|
1338 | *
|
1339 | * @author Varun Shoor
|
1340 | * @param array $_ticketIDList The Ticket ID List
|
1341 | * @return bool "true" on Success, "false" otherwise
|
1342 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
1343 | */
|
1344 | static public function RecalculateHasAttachmentProperty($_ticketIDList) {
|
1345 | $_SWIFT = SWIFT::GetInstance();
|
1346 |
|
1347 | if (!_is_array($_ticketIDList)) {
|
1348 | return false;
|
1349 | }
|
1350 |
|
1351 | $_finalTicketIDList = array();
|
1352 | $_SWIFT->Database->Query("SELECT ticketid FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
1353 | while ($_SWIFT->Database->NextRecord()) {
|
1354 | $_finalTicketIDList[] = $_SWIFT->Database->Record['ticketid'];
|
1355 | }
|
1356 |
|
1357 | if (!count($_finalTicketIDList)) {
|
1358 | return false;
|
1359 | }
|
1360 |
|
1361 | // Now we calculate attachments
|
1362 | $_attachmentCountContainer = array();
|
1363 | $_SWIFT->Database->Query("SELECT COUNT(*) AS totalitems, ticketid FROM " . TABLE_PREFIX . "attachments GROUP BY ticketid HAVING ticketid IN (" . BuildIN($_finalTicketIDList) . ")");
|
1364 | while ($_SWIFT->Database->NextRecord()) {
|
1365 | $_attachmentCountContainer[$_SWIFT->Database->Record['ticketid']] = intval($_SWIFT->Database->Record['totalitems']);
|
1366 | }
|
1367 |
|
1368 | $_attachmentTicketIDList = array();
|
1369 | foreach ($_attachmentCountContainer as $_key => $_val) {
|
1370 | if ($_val > 0) {
|
1371 | $_attachmentTicketIDList[] = $_key;
|
1372 | }
|
1373 | }
|
1374 |
|
1375 | $_nonAttachmentTicketIDList = array();
|
1376 | foreach ($_finalTicketIDList as $_ticketID) {
|
1377 | if (!in_array($_ticketID, $_attachmentTicketIDList)) {
|
1378 | $_nonAttachmentTicketIDList[] = $_ticketID;
|
1379 | }
|
1380 | }
|
1381 |
|
1382 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('hasattachments' => '1'), 'UPDATE', "ticketid IN (" . BuildIN($_attachmentTicketIDList) . ")");
|
1383 |
|
1384 | if (count($_nonAttachmentTicketIDList)) {
|
1385 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('hasattachments' => '0'), 'UPDATE', "ticketid IN (" . BuildIN($_nonAttachmentTicketIDList) . ")");
|
1386 | }
|
1387 |
|
1388 | return true;
|
1389 | }
|
1390 |
|
1391 | /**
|
1392 | * Retrieve the User Group ID based on User ID
|
1393 | *
|
1394 | * @author Varun Shoor
|
1395 | * @return bool "true" on Success, "false" otherwise
|
1396 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1397 | */
|
1398 | public function GetUserGroupID() {
|
1399 | if (!$this->GetIsClassLoaded()) {
|
1400 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1401 |
|
1402 | return false;
|
1403 | }
|
1404 |
|
1405 | $_userID = intval($this->GetProperty('userid'));
|
1406 | if (empty($_userID)) {
|
1407 | return false;
|
1408 | }
|
1409 |
|
1410 | try {
|
1411 | $_SWIFT_UserObject = $this->GetUserObject();
|
1412 |
|
1413 | if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded()) {
|
1414 | return $_SWIFT_UserObject->GetProperty('usergroupid');
|
1415 | }
|
1416 |
|
1417 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
1418 | return false;
|
1419 | }
|
1420 |
|
1421 | return false;
|
1422 | }
|
1423 |
|
1424 | /**
|
1425 | * Retrieve the SLA properties. This array is used to process the SLA rules and the value should match the criteria specified for SWIFT_SLA
|
1426 | *
|
1427 | * @author Varun Shoor
|
1428 | * @return mixed "_slaProperties" (ARRAY) on Success, "false" otherwise
|
1429 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1430 | */
|
1431 | public function GetSLAProperties() {
|
1432 | if (!$this->GetIsClassLoaded()) {
|
1433 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1434 |
|
1435 | return false;
|
1436 | }
|
1437 |
|
1438 | $_slaProperties = array();
|
1439 | $_slaProperties[SWIFT_SLA::SLA_TICKETSTATUS] = $this->GetProperty('ticketstatusid');
|
1440 | $_slaProperties[SWIFT_SLA::SLA_TICKETPRIORITY] = $this->GetProperty('priorityid');
|
1441 | $_slaProperties[SWIFT_SLA::SLA_TICKETDEPARTMENT] = $this->GetProperty('departmentid');
|
1442 | $_slaProperties[SWIFT_SLA::SLA_TICKETOWNER] = $this->GetProperty('ownerstaffid');
|
1443 | $_slaProperties[SWIFT_SLA::SLA_TICKETEMAILQUEUE] = $this->GetProperty('emailqueueid');
|
1444 | $_slaProperties[SWIFT_SLA::SLA_TICKETFLAGTYPE] = $this->GetProperty('flagtype');
|
1445 | $_slaProperties[SWIFT_SLA::SLA_TICKETCREATOR] = $this->GetProperty('creator');
|
1446 | $_slaProperties[SWIFT_SLA::SLA_TICKETUSERGROUP] = $this->GetUserGroupID();
|
1447 |
|
1448 | $_slaProperties[SWIFT_SLA::SLA_TICKETFULLNAME] = $this->GetProperty('fullname');
|
1449 | $_slaProperties[SWIFT_SLA::SLA_TICKETEMAIL] = $this->GetProperty('email');
|
1450 | $_slaProperties[SWIFT_SLA::SLA_TICKETLASTREPLIER] = $this->GetProperty('lastreplier');
|
1451 | $_slaProperties[SWIFT_SLA::SLA_TICKETSUBJECT] = $this->GetProperty('subject');
|
1452 | $_slaProperties[SWIFT_SLA::SLA_TICKETCHARSET] = $this->GetProperty('charset');
|
1453 |
|
1454 | $_slaProperties[SWIFT_SLA::SLA_TICKETTEMPLATEGROUP] = $this->GetProperty('tgroupid');
|
1455 | $_slaProperties[SWIFT_SLA::SLA_TICKETISRESOLVED] = $this->GetProperty('isresolved');
|
1456 | $_slaProperties[SWIFT_SLA::SLA_TICKETTYPE] = $this->GetProperty('tickettypeid');
|
1457 | $_slaProperties[SWIFT_SLA::SLA_TICKETWASREOPENED] = $this->GetProperty('wasreopened');
|
1458 | $_slaProperties[SWIFT_SLA::SLA_TICKETTOTALREPLIES] = $this->GetProperty('totalreplies');
|
1459 | $_slaProperties[SWIFT_SLA::SLA_TICKETBAYESCATEGORY] = $this->GetProperty('bayescategoryid');
|
1460 |
|
1461 | return $_slaProperties;
|
1462 | }
|
1463 |
|
1464 | /**
|
1465 | * process the SLA Overdue time
|
1466 | *
|
1467 | * @author Varun Shoor
|
1468 | * @param bool $_processResolutionDue (OPTIONAL) Whether to process the resolution due dateline
|
1469 | * @return bool "true" on Success, "false" otherwise
|
1470 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1471 | */
|
1472 | public function ProcessSLAOverdue($_processResolutionDue = false) {
|
1473 | $_SWIFT = SWIFT::GetInstance();
|
1474 | chdir(SWIFT_BASEPATH);
|
1475 | if (!$this->GetIsClassLoaded()) {
|
1476 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1477 |
|
1478 | return false;
|
1479 | }
|
1480 |
|
1481 | if ($this->_noSLACalculation == true) {
|
1482 | return false;
|
1483 | }
|
1484 |
|
1485 | $this->Load->Library('SLA:SLAManager');
|
1486 |
|
1487 | $_slaManagerResult = $this->SLAManager->GetDueTime($this);
|
1488 | if (count($_slaManagerResult) != 2) {
|
1489 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
1490 | }
|
1491 |
|
1492 | $_SWIFT_SLAPlanObject = $_slaManagerResult[0];
|
1493 | $_overDueSeconds = $_slaManagerResult[1];
|
1494 |
|
1495 | if ($_SWIFT_SLAPlanObject instanceof SWIFT_SLA && $_SWIFT_SLAPlanObject->GetIsClassLoaded()) {
|
1496 | // Notification Rule
|
1497 | $this->NotificationManager->Changed(SWIFT_NotificationRule::CRITERIA_SLAPLAN, $this->GetProperty('slaplanid'), $_SWIFT_SLAPlanObject->GetSLAPlanID());
|
1498 |
|
1499 | /*
|
1500 | * BUG FIX - Varun Shoor
|
1501 | *
|
1502 | * SWIFT-970 Resolution time is not updated according to SLA plan, while changing the ticket department using Mass Action
|
1503 | *
|
1504 | * Comments: We now force resolution due time recalculation if SLA plan changes
|
1505 | */
|
1506 | if ($this->GetProperty('slaplanid') != $_SWIFT_SLAPlanObject->GetSLAPlanID()) {
|
1507 | $_processResolutionDue = true;
|
1508 | }
|
1509 |
|
1510 | $this->UpdatePool('slaplanid', $_SWIFT_SLAPlanObject->GetSLAPlanID());
|
1511 | $this->UpdatePool('isescalatedvolatile', '0');
|
1512 |
|
1513 |
|
1514 | /**
|
1515 | * BUG FIX - Parminder Singh
|
1516 | *
|
1517 | * SWIFT-795: Issue with SLA plan retention
|
1518 | *
|
1519 | * Comments: If no SLA found then clear the exising one.
|
1520 | */
|
1521 | } else {
|
1522 | // $this->UpdatePool('slaplanid', '0');
|
1523 | }
|
1524 |
|
1525 | /**
|
1526 | * BUG FIX - Parminder Singh
|
1527 | *
|
1528 | * SWIFT-1583: "Clear the Due Time" setting under Ticket Statuses settings, does not work properly
|
1529 | *
|
1530 | * Comments: If the setting 'Clear the Due Time' is disabled and overdue seconds ($_overDueSeconds) are coming blank then no need for SLA/ overdue hours.
|
1531 | */
|
1532 | $_ticketStatusCache = $this->Cache->Get('statuscache');
|
1533 | if (isset($_ticketStatusCache[$this->GetProperty('ticketstatusid')])) {
|
1534 | $_ticketStatusContainer = $_ticketStatusCache[$this->GetProperty('ticketstatusid')];
|
1535 | if ($_ticketStatusContainer['resetduetime'] == '0' && empty($_overDueSeconds) && $this->GetProperty('duetime') != '0') {
|
1536 | $this->_noSLACalculation = true;
|
1537 |
|
1538 | return true;
|
1539 | }
|
1540 | }
|
1541 |
|
1542 | // Create Audit Log
|
1543 | $_renderedDate = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_overDueSeconds);
|
1544 | if (empty($_overDueSeconds)) {
|
1545 | $_renderedDate = $this->Language->Get('duetimecleared');
|
1546 | }
|
1547 |
|
1548 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
|
1549 | sprintf($_SWIFT->Language->Get('al_due'), $_renderedDate),
|
1550 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('duetime'), '', $_overDueSeconds, '');
|
1551 |
|
1552 | $this->UpdatePool('duetime', intval($_overDueSeconds));
|
1553 |
|
1554 | if ($_processResolutionDue == true) {
|
1555 | if (!$_SWIFT_SLAPlanObject instanceof SWIFT_SLA || !$_SWIFT_SLAPlanObject->GetIsClassLoaded())
|
1556 | {
|
1557 | $_SWIFT_SLAPlanObject = null;
|
1558 | }
|
1559 |
|
1560 | $_slaManagerResult_ResolutionDue = $this->SLAManager->GetResolutionTime($this, $_SWIFT_SLAPlanObject);
|
1561 | $_resolutionOverDueSeconds = $_slaManagerResult_ResolutionDue[1];
|
1562 |
|
1563 | // Create Audit Log
|
1564 | $_resolutionRenderedDate = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_resolutionOverDueSeconds);
|
1565 | if (empty($_resolutionOverDueSeconds)) {
|
1566 | $_resolutionRenderedDate = $this->Language->Get('duetimecleared');
|
1567 | }
|
1568 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
|
1569 | sprintf($_SWIFT->Language->Get('al_resolutiondue'), $_resolutionRenderedDate),
|
1570 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('resolutionduedateline'), '', $_resolutionOverDueSeconds, '');
|
1571 |
|
1572 | $this->UpdatePool('resolutionduedateline', intval($_resolutionOverDueSeconds));
|
1573 | }
|
1574 |
|
1575 | $this->_noSLACalculation = true;
|
1576 |
|
1577 | return true;
|
1578 | }
|
1579 |
|
1580 | /**
|
1581 | * Queue the SLA Overdue calculation on shutdown
|
1582 | *
|
1583 | * @author Varun Shoor
|
1584 | * @param bool $_processResolutionDue (OPTIONAL) Whether to process the resolution due dateline
|
1585 | * @return bool "true" on Success, "false" otherwise
|
1586 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1587 | */
|
1588 | public function QueueSLAOverdue($_processResolutionDue = false) {
|
1589 | if (!$this->GetIsClassLoaded()) {
|
1590 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1591 |
|
1592 | return false;
|
1593 | }
|
1594 |
|
1595 | if ($this->_slaOverdueQueued != -1) {
|
1596 | return true;
|
1597 | }
|
1598 |
|
1599 | $this->_slaOverdueQueued = $_processResolutionDue;
|
1600 |
|
1601 | register_shutdown_function(array($this, 'ProcessSLAOverdue'), $this->_slaOverdueQueued);
|
1602 |
|
1603 | return true;
|
1604 | }
|
1605 |
|
1606 | /**
|
1607 | * Set a fixed SLA Plan for this Ticket
|
1608 | *
|
1609 | * @author Varun Shoor
|
1610 | * @param SWIFT_SLA $_SWIFT_SLAObject The SWIFT_SLA Object Pointer
|
1611 | * @return bool "true" on Success, "false" otherwise
|
1612 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
1613 | */
|
1614 | public function SetSLA(SWIFT_SLA $_SWIFT_SLAObject) {
|
1615 | $_SWIFT = SWIFT::GetInstance();
|
1616 |
|
1617 | if (!$this->GetIsClassLoaded()) {
|
1618 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1619 |
|
1620 | return false;
|
1621 | } else if (!$_SWIFT_SLAObject instanceof SWIFT_SLA || !$_SWIFT_SLAObject->GetIsClassLoaded()) {
|
1622 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
1623 | }
|
1624 |
|
1625 | // If the current sla plan and the one provided matches then bail out
|
1626 | if ($this->GetProperty('ticketslaplanid') == $_SWIFT_SLAObject->GetSLAPlanID()) {
|
1627 | return true;
|
1628 | }
|
1629 |
|
1630 | $_slaPlanCache = $this->Cache->Get('slaplancache');
|
1631 |
|
1632 | // Create Audit Log
|
1633 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATESLA,
|
1634 | sprintf($_SWIFT->Language->Get('al_sla'), $_SWIFT_SLAObject->GetProperty('title')),
|
1635 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('ticketslaplanid'), '', $_SWIFT_SLAObject->GetSLAPlanID(), '');
|
1636 |
|
1637 | // Notification Rule
|
1638 | $this->NotificationManager->Changed(SWIFT_NotificationRule::CRITERIA_SLAPLAN, $this->GetProperty('ticketslaplanid'), $_SWIFT_SLAObject->GetSLAPlanID());
|
1639 |
|
1640 | // Notification Update
|
1641 | $_oldTicketSLAPlanID = $this->GetProperty('ticketslaplanid');
|
1642 | $_oldSLATitle = $_newSLATitle = '';
|
1643 | if ($_oldTicketSLAPlanID != '0') {
|
1644 | if (isset($_slaPlanCache[$_oldTicketSLAPlanID])) {
|
1645 | $_oldSLATitle = $_slaPlanCache[$_oldTicketSLAPlanID]['title'];
|
1646 | } else {
|
1647 | $_oldSLATitle = $this->Language->Get('na');
|
1648 | }
|
1649 | }
|
1650 |
|
1651 | $_newSLATitle = $_SWIFT_SLAObject->GetProperty('title');
|
1652 |
|
1653 | $this->Notification->Update($this->Language->Get('notification_sla'), $_oldSLATitle, $_newSLATitle);
|
1654 |
|
1655 | $this->UpdatePool('ticketslaplanid', intval($_SWIFT_SLAObject->GetSLAPlanID()));
|
1656 | $this->UpdatePool('slaplanid', intval($_SWIFT_SLAObject->GetSLAPlanID()));
|
1657 | $this->UpdatePool('isescalatedvolatile', '0');
|
1658 |
|
1659 | // We set these to 0 and expect the sla processing engine to set the correct values
|
1660 | // $this->UpdatePool('duetime', '0');
|
1661 | // $this->UpdatePool('resolutionduedateline', '0');
|
1662 |
|
1663 | $this->_noSLACalculation = false;
|
1664 | $this->ProcessSLAOverdue(true);
|
1665 | // $this->QueueSLAOverdue(true);
|
1666 |
|
1667 | // Load and Process Workflow Rules
|
1668 | self::AddToWorkflowQueue($this);
|
1669 |
|
1670 | return true;
|
1671 | }
|
1672 |
|
1673 | /**
|
1674 | * Clear the fixed Ticket SLA Plan
|
1675 | *
|
1676 | * @author Varun Shoor
|
1677 | * @return bool "true" on Success, "false" otherwise
|
1678 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1679 | */
|
1680 | public function ClearSLA() {
|
1681 | $_SWIFT = SWIFT::GetInstance();
|
1682 |
|
1683 | if (!$this->GetIsClassLoaded()) {
|
1684 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1685 |
|
1686 | return false;
|
1687 | }
|
1688 |
|
1689 | if ($this->GetProperty('ticketslaplanid') == '0') {
|
1690 | return true;
|
1691 | }
|
1692 |
|
1693 | $_slaPlanCache = $this->Cache->Get('slaplancache');
|
1694 |
|
1695 | // Create Audit Log
|
1696 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATESLA,
|
1697 | $_SWIFT->Language->Get('al_slaclear'),
|
1698 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('ticketslaplanid'), '', 0, '');
|
1699 |
|
1700 | // Notification Update
|
1701 | $_oldTicketSLAPlanID = $this->GetProperty('ticketslaplanid');
|
1702 | $_oldSLATitle = $_newSLATitle = '';
|
1703 | if ($_oldTicketSLAPlanID != '0') {
|
1704 | if (isset($_slaPlanCache[$_oldTicketSLAPlanID])) {
|
1705 | $_oldSLATitle = $_slaPlanCache[$_oldTicketSLAPlanID]['title'];
|
1706 | } else {
|
1707 | $_oldSLATitle = $this->Language->Get('na');
|
1708 | }
|
1709 | }
|
1710 |
|
1711 | $_newSLATitle = $this->Language->Get('notificationcleared');
|
1712 |
|
1713 | $this->Notification->Update($this->Language->Get('notification_sla'), $_oldSLATitle, $_newSLATitle);
|
1714 |
|
1715 | $this->UpdatePool('ticketslaplanid', 0);
|
1716 |
|
1717 | $this->QueueSLAOverdue();
|
1718 |
|
1719 | // Load and Process Workflow Rules
|
1720 | self::AddToWorkflowQueue($this);
|
1721 |
|
1722 | return true;
|
1723 | }
|
1724 |
|
1725 | /**
|
1726 | * Escalate this Ticket
|
1727 | *
|
1728 | * @author Varun Shoor
|
1729 | * @param SWIFT_EscalationRule $_SWIFT_EscalationRuleObject
|
1730 | * @return bool "true" on Success, "false" otherwise
|
1731 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
1732 | */
|
1733 | public function Escalate(SWIFT_EscalationRule $_SWIFT_EscalationRuleObject) {
|
1734 | $_SWIFT = SWIFT::GetInstance();
|
1735 |
|
1736 | if (!$this->GetIsClassLoaded()) {
|
1737 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1738 |
|
1739 | return false;
|
1740 | } else if (!$_SWIFT_EscalationRuleObject instanceof SWIFT_EscalationRule || !$_SWIFT_EscalationRuleObject->GetIsClassLoaded()) {
|
1741 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
1742 | }
|
1743 |
|
1744 | $_staffCache = $this->Cache->Get('staffcache');
|
1745 |
|
1746 | // We execute this before all arguments so that if a custom SLA plan is set, it can override this value.
|
1747 | $this->UpdatePool('isescalatedvolatile', '1');
|
1748 |
|
1749 | SWIFT_EscalationPath::Create($this, $this->GetProperty('slaplanid'), $_SWIFT_EscalationRuleObject->GetEscalationRuleID(),
|
1750 | $this->GetProperty('ownerstaffid'), $this->GetProperty('departmentid'), $this->GetProperty('ticketstatusid'),
|
1751 | $this->GetProperty('priorityid'), $this->GetProperty('tickettypeid'), $this->GetProperty('flagtype'));
|
1752 |
|
1753 | if ($_SWIFT_EscalationRuleObject->GetProperty('staffid') != '-1' && $_SWIFT_EscalationRuleObject->GetProperty('staffid') != '0' && isset($_staffCache[$_SWIFT_EscalationRuleObject->GetProperty('staffid')]))
|
1754 | {
|
1755 | $this->SetOwner($_SWIFT_EscalationRuleObject->GetProperty('staffid'));
|
1756 | }
|
1757 |
|
1758 | if ($_SWIFT_EscalationRuleObject->GetProperty('departmentid') != '0' && $_SWIFT_EscalationRuleObject->GetProperty('departmentid') != '-1')
|
1759 | {
|
1760 | $this->SetDepartment($_SWIFT_EscalationRuleObject->GetProperty('departmentid'));
|
1761 | }
|
1762 |
|
1763 | if ($_SWIFT_EscalationRuleObject->GetProperty('ticketstatusid') != '0' && $_SWIFT_EscalationRuleObject->GetProperty('ticketstatusid') != '-1')
|
1764 | {
|
1765 | $this->SetStatus($_SWIFT_EscalationRuleObject->GetProperty('ticketstatusid'));
|
1766 | }
|
1767 |
|
1768 | if ($_SWIFT_EscalationRuleObject->GetProperty('priorityid') != '0' && $_SWIFT_EscalationRuleObject->GetProperty('priorityid') != '-1')
|
1769 | {
|
1770 | $this->SetPriority($_SWIFT_EscalationRuleObject->GetProperty('priorityid'));
|
1771 | }
|
1772 |
|
1773 | if ($_SWIFT_EscalationRuleObject->GetProperty('tickettypeid') != '0' && $_SWIFT_EscalationRuleObject->GetProperty('tickettypeid') != '-1')
|
1774 | {
|
1775 | $this->SetType($_SWIFT_EscalationRuleObject->GetProperty('tickettypeid'));
|
1776 | }
|
1777 |
|
1778 | if ($_SWIFT_EscalationRuleObject->GetProperty('flagtype') != '0' && $_SWIFT_EscalationRuleObject->GetProperty('flagtype') != '-1')
|
1779 | {
|
1780 | $this->SetFlag($_SWIFT_EscalationRuleObject->GetProperty('flagtype'));
|
1781 | }
|
1782 |
|
1783 | if ($_SWIFT_EscalationRuleObject->GetProperty('newslaplanid') != '0' && $_SWIFT_EscalationRuleObject->GetProperty('newslaplanid') != '-1')
|
1784 | {
|
1785 | $this->SetSLA(new SWIFT_SLA(new SWIFT_DataID($_SWIFT_EscalationRuleObject->GetProperty('newslaplanid'))));
|
1786 | }
|
1787 |
|
1788 | if ($_SWIFT_EscalationRuleObject->GetProperty('addtags') != '')
|
1789 | {
|
1790 | $_tagContainer = json_decode($_SWIFT_EscalationRuleObject->GetProperty('addtags'));
|
1791 | if (is_array($_tagContainer)) {
|
1792 | SWIFT_Tag::AddTags(SWIFT_TagLink::TYPE_TICKET, $this->GetTicketID(),
|
1793 | $_tagContainer, false);
|
1794 | }
|
1795 | }
|
1796 |
|
1797 | if ($_SWIFT_EscalationRuleObject->GetProperty('removetags') != '')
|
1798 | {
|
1799 | $_tagContainer = json_decode($_SWIFT_EscalationRuleObject->GetProperty('removetags'));
|
1800 | if (is_array($_tagContainer)) {
|
1801 | SWIFT_Tag::RemoveTags(SWIFT_TagLink::TYPE_TICKET, array($this->GetTicketID()),
|
1802 | $_tagContainer, false);
|
1803 | }
|
1804 |
|
1805 | }
|
1806 |
|
1807 | $this->UpdatePool('escalationruleid', $_SWIFT_EscalationRuleObject->GetEscalationRuleID());
|
1808 | $this->UpdatePool('isescalated', '1');
|
1809 | $this->UpdatePool('escalatedtime', DATENOW);
|
1810 | $this->UpdatePool('escalationlevelcount', ($this->GetProperty('escalationlevelcount')+1));
|
1811 |
|
1812 | // Load and Process Workflow Rules
|
1813 | self::AddToWorkflowQueue($this);
|
1814 |
|
1815 | return true;
|
1816 | }
|
1817 |
|
1818 | /**
|
1819 | * Mark the ticket as watched
|
1820 | *
|
1821 | * @author Varun Shoor
|
1822 | * @return bool "true" on Success, "false" otherwise
|
1823 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1824 | */
|
1825 | public function MarkAsWatched() {
|
1826 | $_SWIFT = SWIFT::GetInstance();
|
1827 |
|
1828 | if (!$this->GetIsClassLoaded()) {
|
1829 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1830 |
|
1831 | return false;
|
1832 | }
|
1833 |
|
1834 | $this->UpdatePool('iswatched', '1');
|
1835 |
|
1836 | return true;
|
1837 | }
|
1838 |
|
1839 | /**
|
1840 | * Mark the ticket as overdue
|
1841 | *
|
1842 | * @author Varun Shoor
|
1843 | * @return bool "true" on Success, "false" otherwise
|
1844 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1845 | */
|
1846 | public function MarkAsDue() {
|
1847 | $_SWIFT = SWIFT::GetInstance();
|
1848 |
|
1849 | if (!$this->GetIsClassLoaded()) {
|
1850 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1851 |
|
1852 | return false;
|
1853 | }
|
1854 |
|
1855 | // Create Audit Log
|
1856 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
|
1857 | $_SWIFT->Language->Get('al_duestaffoverdue'),
|
1858 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('duetime'), '', DATENOW, '');
|
1859 |
|
1860 | // Notification Update
|
1861 | $_newDueDate = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, DATENOW);
|
1862 | $this->Notification->Update($this->Language->Get('notification_due'), '', $_newDueDate);
|
1863 |
|
1864 |
|
1865 | $this->UpdatePool('duetime', DATENOW);
|
1866 |
|
1867 | // Prevent SLA Calculation
|
1868 | $this->_noSLACalculation = true;
|
1869 |
|
1870 | // Load and Process Workflow Rules
|
1871 | self::AddToWorkflowQueue($this);
|
1872 |
|
1873 | return true;
|
1874 | }
|
1875 |
|
1876 | /**
|
1877 | * Clear the overdue time
|
1878 | *
|
1879 | * @author Varun Shoor
|
1880 | * @return bool "true" on Success, "false" otherwise
|
1881 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1882 | */
|
1883 | public function ClearOverdue() {
|
1884 | $_SWIFT = SWIFT::GetInstance();
|
1885 |
|
1886 | if (!$this->GetIsClassLoaded()) {
|
1887 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1888 |
|
1889 | return false;
|
1890 | }
|
1891 |
|
1892 | if ($this->GetProperty('duetime') == '0') {
|
1893 | return true;
|
1894 | }
|
1895 | // Create Audit Log
|
1896 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
|
1897 | $_SWIFT->Language->Get('al_duestaffclear'),
|
1898 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('duetime'), '', 0, '');
|
1899 |
|
1900 | // Notification Update
|
1901 | $_oldDueDate = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $this->GetProperty('duetime'));
|
1902 | $_newDueDate = $this->Language->Get('notificationcleared');
|
1903 |
|
1904 | $this->Notification->Update($this->Language->Get('notification_due'), $_oldDueDate, $_newDueDate);
|
1905 |
|
1906 | $this->UpdatePool('duetime', '0');
|
1907 |
|
1908 | // Prevent calculation of SLA due time on this ticket
|
1909 | $this->_noSLACalculation = true;
|
1910 |
|
1911 | // Load and Process Workflow Rules
|
1912 | self::AddToWorkflowQueue($this);
|
1913 |
|
1914 | return true;
|
1915 | }
|
1916 |
|
1917 | /**
|
1918 | * Set the Template Group
|
1919 | *
|
1920 | * @author Varun Shoor
|
1921 | * @param int $_templateGroupID The Template Group ID
|
1922 | * @return bool "true" on Success, "false" otherwise
|
1923 | * @throws SWIFT_Exception If the Class is not Loaded
|
1924 | */
|
1925 | public function SetTemplateGroup($_templateGroupID)
|
1926 | {
|
1927 | if (!$this->GetIsClassLoaded())
|
1928 | {
|
1929 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
1930 |
|
1931 | return false;
|
1932 | }
|
1933 |
|
1934 | $this->UpdatePool('tgroupid', intval($_templateGroupID));
|
1935 |
|
1936 | return true;
|
1937 | }
|
1938 |
|
1939 | /**
|
1940 | * Clear the resolution time
|
1941 | *
|
1942 | * @author Varun Shoor
|
1943 | * @return bool "true" on Success, "false" otherwise
|
1944 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
1945 | */
|
1946 | public function ClearResolutionDue() {
|
1947 | $_SWIFT = SWIFT::GetInstance();
|
1948 |
|
1949 | if (!$this->GetIsClassLoaded()) {
|
1950 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1951 |
|
1952 | return false;
|
1953 | }
|
1954 |
|
1955 | if ($this->GetProperty('resolutionduedateline') == '0') {
|
1956 | return true;
|
1957 | }
|
1958 |
|
1959 | // Create Audit Log
|
1960 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
|
1961 | $_SWIFT->Language->Get('al_resduestaffclear'),
|
1962 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('resolutionduedateline'), '', 0, '');
|
1963 |
|
1964 | // Notification Update
|
1965 | $_oldDueDate = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $this->GetProperty('resolutionduedateline'));
|
1966 | $_newDueDate = $this->Language->Get('notificationcleared');
|
1967 |
|
1968 | $this->Notification->Update($this->Language->Get('notification_resolutiondue'), $_oldDueDate, $_newDueDate);
|
1969 |
|
1970 | $this->UpdatePool('resolutionduedateline', '0');
|
1971 |
|
1972 | // Prevent calculation of SLA due time on this ticket
|
1973 | $this->_noSLACalculation = true;
|
1974 |
|
1975 | // Load and Process Workflow Rules
|
1976 | self::AddToWorkflowQueue($this);
|
1977 |
|
1978 | return true;
|
1979 | }
|
1980 |
|
1981 | /**
|
1982 | * Set a flag on this ticket
|
1983 | *
|
1984 | * @author Varun Shoor
|
1985 | * @param constant $_flagType The Flag Type
|
1986 | * @return bool "true" on Success, "false" otherwise
|
1987 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
1988 | */
|
1989 | public function SetFlag($_flagType) {
|
1990 | $_SWIFT = SWIFT::GetInstance();
|
1991 |
|
1992 | if (!$this->GetIsClassLoaded()) {
|
1993 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
1994 |
|
1995 | return false;
|
1996 | }
|
1997 |
|
1998 | $this->Load->Library('Flag:TicketFlag');
|
1999 | $_flagContainer = $this->TicketFlag->GetFlagContainer();
|
2000 |
|
2001 | if ($_flagType == '0') {
|
2002 | // Notification Update
|
2003 | $_oldFlagTitle = '';
|
2004 | if (isset($_flagContainer[$this->GetProperty('flagtype')])) {
|
2005 | $_oldFlagTitle = $_flagContainer[$this->GetProperty('flagtype')][0];
|
2006 | }
|
2007 | $_newFlagTitle = $this->Language->Get('notificationcleared');
|
2008 |
|
2009 | $this->Notification->Update($this->Language->Get('notification_flag'), $_oldFlagTitle, $_newFlagTitle);
|
2010 |
|
2011 | $this->UpdatePool('flagtype', '0');
|
2012 |
|
2013 | $this->QueueSLAOverdue();
|
2014 |
|
2015 | return true;
|
2016 | }
|
2017 |
|
2018 | if (!SWIFT_TicketFlag::IsValidFlagType($_flagType)) {
|
2019 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2020 | }
|
2021 |
|
2022 | // If this ticket already has a flag set which matches the one specified.. then move on
|
2023 | if ($this->GetProperty('flagtype') == $_flagType) {
|
2024 | return true;
|
2025 | }
|
2026 |
|
2027 | // Create Audit Log
|
2028 | $_flagTitle = $_flagContainer[$_flagType][0];
|
2029 |
|
2030 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATEFLAG,
|
2031 | sprintf($_SWIFT->Language->Get('al_flag'), $_flagTitle),
|
2032 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('flagtype'), '', $_flagType, '');
|
2033 |
|
2034 | // Notification Rule
|
2035 | $this->NotificationManager->Changed(SWIFT_NotificationRule::CRITERIA_FLAGTYPE, $this->GetProperty('flagtype'), $_flagType);
|
2036 |
|
2037 | // Notification Update
|
2038 | $_oldFlagTitle = '';
|
2039 | if (isset($_flagContainer[$this->GetProperty('flagtype')])) {
|
2040 | $_oldFlagTitle = $_flagContainer[$this->GetProperty('flagtype')][0];
|
2041 | }
|
2042 | $_newFlagTitle = $_flagTitle;
|
2043 |
|
2044 | $this->Notification->Update($this->Language->Get('notification_flag'), $_oldFlagTitle, $_newFlagTitle);
|
2045 |
|
2046 | $this->UpdatePool('flagtype', intval($_flagType));
|
2047 |
|
2048 | $this->QueueSLAOverdue();
|
2049 |
|
2050 | // Load and Process Workflow Rules
|
2051 | self::AddToWorkflowQueue($this);
|
2052 |
|
2053 | return true;
|
2054 | }
|
2055 |
|
2056 | /**
|
2057 | * Clear a flag on a ticket
|
2058 | *
|
2059 | * @author Varun Shoor
|
2060 | * @return bool "true" on Success, "false" otherwise
|
2061 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
2062 | */
|
2063 | public function ClearFlag() {
|
2064 | $_SWIFT = SWIFT::GetInstance();
|
2065 |
|
2066 | if (!$this->GetIsClassLoaded()) {
|
2067 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2068 |
|
2069 | return false;
|
2070 | }
|
2071 |
|
2072 | // If there is no flag set, then ignore.
|
2073 | if ($this->GetProperty('flagtype') == '0') {
|
2074 | return true;
|
2075 | }
|
2076 |
|
2077 | $_SWIFT_TicketFlagObject = new SWIFT_TicketFlag();
|
2078 | $_flagContainer = $_SWIFT_TicketFlagObject->GetFlagContainer();
|
2079 |
|
2080 | // Create Audit Log
|
2081 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATEFLAG,
|
2082 | $_SWIFT->Language->Get('al_flagclear'),
|
2083 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('flagtype'), '', 0, '');
|
2084 |
|
2085 | // Notification Update
|
2086 | $_oldFlagTitle = '';
|
2087 | if (isset($_flagContainer[$this->GetProperty('flagtype')])) {
|
2088 | $_oldFlagTitle = $_flagContainer[$this->GetProperty('flagtype')][0];
|
2089 | }
|
2090 | $_newFlagTitle = $this->Language->Get('notificationcleared');
|
2091 |
|
2092 | $this->Notification->Update($this->Language->Get('notification_flag'), $_oldFlagTitle, $_newFlagTitle);
|
2093 |
|
2094 | $this->UpdatePool('flagtype', 0);
|
2095 |
|
2096 | $this->QueueSLAOverdue();
|
2097 |
|
2098 | // Load and Process Workflow Rules
|
2099 | self::AddToWorkflowQueue($this);
|
2100 |
|
2101 | return true;
|
2102 | }
|
2103 |
|
2104 | /**
|
2105 | * Change the department for the ticket
|
2106 | *
|
2107 | * @author Varun Shoor
|
2108 | * @param int $_departmentID The department id
|
2109 | * @return bool "true" on Success, "false" otherwise
|
2110 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or if Invalid Data is Provided
|
2111 | */
|
2112 | public function SetDepartment($_departmentID) {
|
2113 | $_SWIFT = SWIFT::GetInstance();
|
2114 |
|
2115 | if (!$this->GetIsClassLoaded()) {
|
2116 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2117 |
|
2118 | return false;
|
2119 | } else if (empty($_departmentID)) {
|
2120 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2121 | }
|
2122 |
|
2123 | $_departmentCache = $this->Cache->Get('departmentcache');
|
2124 | if (!isset($_departmentCache[$_departmentID])) {
|
2125 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2126 | }
|
2127 |
|
2128 | // If the ticket is already in this department then bail out
|
2129 | if ($this->GetProperty('departmentid') == $_departmentID) {
|
2130 | return true;
|
2131 | }
|
2132 |
|
2133 | // Add old and new department to recount queue
|
2134 | // SWIFT_TicketManager::Recount($this->GetProperty('departmentid'));
|
2135 | // SWIFT_TicketManager::Recount($_departmentID);
|
2136 | SWIFT_TicketManager::Recount(false);
|
2137 |
|
2138 | // Create Audit Log
|
2139 | $_oldDepartmentTitle = $_newDepartmentTitle = '';
|
2140 | if (isset($_departmentCache[$this->GetProperty('departmentid')])) {
|
2141 | $_oldDepartmentTitle = $_departmentCache[$this->GetProperty('departmentid')]['title'];
|
2142 | }
|
2143 |
|
2144 | if ($this->GetProperty('departmentid') == '0') {
|
2145 | $_oldDepartmentTitle = $this->Language->Get('trash');
|
2146 | }
|
2147 |
|
2148 | $_newDepartmentTitle = $_departmentCache[$_departmentID]['title'];
|
2149 |
|
2150 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATEDEPARTMENT,
|
2151 | sprintf($_SWIFT->Language->Get('al_department'), $_oldDepartmentTitle, $_newDepartmentTitle),
|
2152 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('departmentid'), '', $_departmentID, '');
|
2153 |
|
2154 | // Notification Rule
|
2155 | $this->NotificationManager->Changed(SWIFT_NotificationRule::CRITERIA_DEPARTMENT, $this->GetProperty('departmentid'), $_departmentID);
|
2156 |
|
2157 | // Notification Update
|
2158 | $_oldNotificationDepartmentTitle = $_newNotificationDepartmentTitle = '';
|
2159 | if ($_oldDepartmentTitle == '') {
|
2160 | $_oldNotificationDepartmentTitle = $this->Language->Get('na');
|
2161 | } else {
|
2162 | $_oldNotificationDepartmentTitle = $_oldDepartmentTitle;
|
2163 | }
|
2164 |
|
2165 | $_newNotificationDepartmentTitle = $_newDepartmentTitle;
|
2166 |
|
2167 | $_oldUserNotificationDepartmentTitle = $_oldNotificationDepartmentTitle;
|
2168 | $_newUserNotificationDepartmentTitle = $_newNotificationDepartmentTitle;
|
2169 |
|
2170 | if (isset($_departmentCache[$this->GetProperty('departmentid')]) && $_departmentCache[$this->GetProperty('departmentid')]['departmenttype'] == SWIFT_PRIVATE) {
|
2171 | $_oldUserNotificationDepartmentTitle = $this->Language->Get('private');
|
2172 | }
|
2173 |
|
2174 | if (isset($_departmentCache[$_departmentID]) && $_departmentCache[$_departmentID]['departmenttype'] == SWIFT_PRIVATE) {
|
2175 | $_newUserNotificationDepartmentTitle = $this->Language->Get('private');
|
2176 | }
|
2177 |
|
2178 | $this->Notification->Update($this->Language->Get('notification_department'), $_oldNotificationDepartmentTitle, $_newNotificationDepartmentTitle, $_oldUserNotificationDepartmentTitle, $_newUserNotificationDepartmentTitle);
|
2179 |
|
2180 | $this->UpdatePool('departmentid', intval($_departmentID));
|
2181 | $this->UpdatePool('departmenttitle', $_newDepartmentTitle);
|
2182 |
|
2183 | $this->QueueSLAOverdue();
|
2184 |
|
2185 | // Load and Process Workflow Rules
|
2186 | self::AddToWorkflowQueue($this);
|
2187 |
|
2188 | return true;
|
2189 | }
|
2190 |
|
2191 | /**
|
2192 | * Set the Ticket Type
|
2193 | *
|
2194 | * @author Varun Shoor
|
2195 | * @param int $_ticketTypeID The Ticket Type ID
|
2196 | * @return bool "true" on Success, "false" otherwise
|
2197 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
2198 | */
|
2199 | public function SetType($_ticketTypeID) {
|
2200 | $_SWIFT = SWIFT::GetInstance();
|
2201 |
|
2202 | if (!$this->GetIsClassLoaded()) {
|
2203 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2204 |
|
2205 | return false;
|
2206 | } else if (empty($_ticketTypeID)) {
|
2207 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2208 | }
|
2209 |
|
2210 | // Verify value of ticket type
|
2211 | $_ticketTypeCache = $this->Cache->Get('tickettypecache');
|
2212 | if (!isset($_ticketTypeCache[$_ticketTypeID])) {
|
2213 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2214 | }
|
2215 |
|
2216 | $_ticketTypeContainer = $_ticketTypeCache[$_ticketTypeID];
|
2217 |
|
2218 | // If current ticket type is same as the new type then bail out
|
2219 | if ($this->GetProperty('tickettypeid') == $_ticketTypeID) {
|
2220 | return true;
|
2221 | }
|
2222 |
|
2223 | // Verify the department id link of ticket type
|
2224 |
|
2225 | /*
|
2226 | * BUG FIX - Varun Shoor
|
2227 | *
|
2228 | * SWIFT-1298 Issue with ticket types and ticket statuses, if they are linked with Parent department
|
2229 | *
|
2230 | * Comments: None
|
2231 | */
|
2232 | $_departmentCache = $this->Cache->Get('departmentcache');
|
2233 | $_parentDepartmentID = false;
|
2234 | if (isset($_departmentCache[$this->GetProperty('departmentid')])) {
|
2235 | $_parentDepartmentID = $_departmentCache[$this->GetProperty('departmentid')]['parentdepartmentid'];
|
2236 | }
|
2237 |
|
2238 | if ($_ticketTypeContainer['departmentid'] != '0' && $_ticketTypeContainer['departmentid'] != $this->GetProperty('departmentid') && $_ticketTypeContainer['departmentid'] != $_parentDepartmentID) {
|
2239 | throw new SWIFT_Ticket_Exception('Ticket Type (' . intval($_ticketTypeID) . ') & Department ID (' . intval($this->GetProperty('departmentid')) . ') Mismatch');
|
2240 | }
|
2241 |
|
2242 | // Create Audit Log
|
2243 | $_oldTypeTitle = $_newTypeTitle = '';
|
2244 | if (isset($_ticketTypeCache[$this->GetProperty('tickettypeid')])) {
|
2245 | $_oldTypeTitle = $_ticketTypeCache[$this->GetProperty('tickettypeid')]['title'];
|
2246 | }
|
2247 |
|
2248 | $_newTypeTitle = $_ticketTypeCache[$_ticketTypeID]['title'];
|
2249 |
|
2250 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETYPE,
|
2251 | sprintf($_SWIFT->Language->Get('al_type'), $_oldTypeTitle, $_newTypeTitle),
|
2252 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('tickettypeid'), '', $_ticketTypeID, '');
|
2253 |
|
2254 | // Notification Rule
|
2255 | $this->NotificationManager->Changed(SWIFT_NotificationRule::CRITERIA_TICKETTYPE, $this->GetProperty('tickettypeid'), $_ticketTypeID);
|
2256 |
|
2257 | // Notification Update
|
2258 | $_oldNotificationTypeTitle = $_newNotificationTypeTitle = '';
|
2259 | if ($_oldTypeTitle == '') {
|
2260 | $_oldNotificationTypeTitle = $this->Language->Get('na');
|
2261 | } else {
|
2262 | $_oldNotificationTypeTitle = $_oldTypeTitle;
|
2263 | }
|
2264 |
|
2265 | $_newNotificationTypeTitle = $_newTypeTitle;
|
2266 |
|
2267 | $_oldUserNotificationTypeTitle = $_oldNotificationTypeTitle;
|
2268 | $_newUserNotificationTypeTitle = $_newNotificationTypeTitle;
|
2269 |
|
2270 | if ($_ticketTypeCache[$this->GetProperty('tickettypeid')]['type'] == SWIFT_PRIVATE) {
|
2271 | $_oldUserNotificationTypeTitle = $this->Language->Get('private');
|
2272 | }
|
2273 |
|
2274 | if ($_ticketTypeCache[$_ticketTypeID]['type'] == SWIFT_PRIVATE) {
|
2275 | $_newUserNotificationTypeTitle = $this->Language->Get('private');
|
2276 | }
|
2277 |
|
2278 | $this->Notification->Update($this->Language->Get('notification_type'), $_oldNotificationTypeTitle, $_newNotificationTypeTitle, $_oldUserNotificationTypeTitle, $_newUserNotificationTypeTitle);
|
2279 |
|
2280 |
|
2281 | $this->UpdatePool('tickettypeid', intval($_ticketTypeID));
|
2282 | $this->UpdatePool('tickettypetitle', $_newTypeTitle);
|
2283 |
|
2284 | // SWIFT_TicketManager::Recount($this->GetProperty('departmentid'));
|
2285 | SWIFT_TicketManager::Recount(false);
|
2286 |
|
2287 | $this->QueueSLAOverdue();
|
2288 |
|
2289 | // Load and Process Workflow Rules
|
2290 | self::AddToWorkflowQueue($this);
|
2291 |
|
2292 | return true;
|
2293 | }
|
2294 |
|
2295 | /**
|
2296 | * Set the Has Status Changed Property
|
2297 | *
|
2298 | * @author Varun Shoor
|
2299 | * @param bool $_hasStatusChanged
|
2300 | * @return bool "true" on Success, "false" otherwise
|
2301 | * @throws SWIFT_Exception If the Class is not Loaded
|
2302 | */
|
2303 | protected function SetHasStatusChanged($_hasStatusChanged)
|
2304 | {
|
2305 | if (!$this->GetIsClassLoaded()) {
|
2306 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
2307 |
|
2308 | return false;
|
2309 | }
|
2310 |
|
2311 | $this->_hasStatusChanged = $_hasStatusChanged;
|
2312 |
|
2313 | return true;
|
2314 | }
|
2315 |
|
2316 | /**
|
2317 | * Retrieve the Has Status Changed Property
|
2318 | *
|
2319 | * @author Varun Shoor
|
2320 | * @return bool "true" on Success, "false" otherwise
|
2321 | * @throws SWIFT_Exception If the Class is not Loaded
|
2322 | */
|
2323 | public function GetHasStatusChanged()
|
2324 | {
|
2325 | if (!$this->GetIsClassLoaded()) {
|
2326 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
2327 |
|
2328 | return false;
|
2329 | }
|
2330 |
|
2331 | return $this->_hasStatusChanged;
|
2332 | }
|
2333 |
|
2334 | /**
|
2335 | * Set the Ticket Status
|
2336 | *
|
2337 | * @author Varun Shoor
|
2338 | * @param int $_ticketStatusID The Ticket Status ID
|
2339 | * @param bool $_isViaAutoClose (OPTIONAL) If the status change is via auto close
|
2340 | * @param bool $_suppressSurveyEmail (OPTIONAL) Whether to suppress survey email
|
2341 | * @return bool "true" on Success, "false" otherwise
|
2342 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
2343 | */
|
2344 | public function SetStatus($_ticketStatusID, $_isViaAutoClose = false, $_suppressSurveyEmail = false) {
|
2345 | $_SWIFT = SWIFT::GetInstance();
|
2346 |
|
2347 | if (!$this->GetIsClassLoaded()) {
|
2348 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2349 |
|
2350 | } else if (empty($_ticketStatusID)) {
|
2351 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2352 | }
|
2353 |
|
2354 | $_ticketStatusCache = $this->Cache->Get('statuscache');
|
2355 | if (!isset($_ticketStatusCache[$_ticketStatusID])) {
|
2356 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2357 | }
|
2358 |
|
2359 | $_ticketStatusContainer = $_ticketStatusCache[$_ticketStatusID];
|
2360 |
|
2361 | $this->SetHasStatusChanged(true);
|
2362 |
|
2363 | // If the current ticket status id matches then bail out
|
2364 | if ($this->GetProperty('ticketstatusid') == $_ticketStatusID) {
|
2365 | return true;
|
2366 | }
|
2367 |
|
2368 | // Verify the department id link of ticket status
|
2369 |
|
2370 | /*
|
2371 | * BUG FIX - Varun Shoor
|
2372 | *
|
2373 | * SWIFT-1298 Issue with ticket types and ticket statuses, if they are linked with Parent department
|
2374 | *
|
2375 | * Comments: None
|
2376 | */
|
2377 | $_departmentCache = $this->Cache->Get('departmentcache');
|
2378 | $_parentDepartmentID = false;
|
2379 | if (isset($_departmentCache[$this->GetProperty('departmentid')])) {
|
2380 | $_parentDepartmentID = $_departmentCache[$this->GetProperty('departmentid')]['parentdepartmentid'];
|
2381 | }
|
2382 |
|
2383 | if ($_ticketStatusContainer['departmentid'] != '0' && $_ticketStatusContainer['departmentid'] != $this->GetProperty('departmentid') && $_ticketStatusContainer['departmentid'] != $_parentDepartmentID) {
|
2384 | throw new SWIFT_Ticket_Exception('Ticket Status (' . intval($_ticketStatusID) . ') & Department ID (' . intval($this->GetProperty('departmentid')) . ') Mismatch');
|
2385 | }
|
2386 |
|
2387 | // Create Audit Log
|
2388 | $_oldStatusTitle = $_newStatusTitle = '';
|
2389 | if (isset($_ticketStatusCache[$this->GetProperty('ticketstatusid')])) {
|
2390 | $_oldStatusTitle = $_ticketStatusCache[$this->GetProperty('ticketstatusid')]['title'];
|
2391 | }
|
2392 |
|
2393 | $_newStatusTitle = $_ticketStatusCache[$_ticketStatusID]['title'];
|
2394 |
|
2395 | $_statusLanguageKey = 'al_status';
|
2396 | if ($_isViaAutoClose) {
|
2397 | $_statusLanguageKey = 'al_statusautoclose';
|
2398 | }
|
2399 |
|
2400 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATESTATUS,
|
2401 | sprintf($_SWIFT->Language->Get($_statusLanguageKey), $_oldStatusTitle, $_newStatusTitle),
|
2402 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('ticketstatusid'), '', $_ticketStatusID, '');
|
2403 |
|
2404 | // Notification Rule
|
2405 | $this->NotificationManager->Changed(SWIFT_NotificationRule::CRITERIA_TICKETSTATUS, $this->GetProperty('ticketstatusid'), $_ticketStatusID);
|
2406 |
|
2407 | // Notification Update
|
2408 | $_oldNotificationStatusTitle = $_newNotificationStatusTitle = '';
|
2409 | if ($_oldStatusTitle == '') {
|
2410 | $_oldNotificationStatusTitle = $this->Language->Get('na');
|
2411 | } else {
|
2412 | $_oldNotificationStatusTitle = $_oldStatusTitle;
|
2413 | }
|
2414 |
|
2415 | $_newNotificationStatusTitle = $_newStatusTitle;
|
2416 |
|
2417 | $_oldUserNotificationStatusTitle = $_oldNotificationStatusTitle;
|
2418 | $_newUserNotificationStatusTitle = $_newNotificationStatusTitle;
|
2419 |
|
2420 | if ($_ticketStatusCache[$this->GetProperty('ticketstatusid')]['statustype'] == SWIFT_PRIVATE) {
|
2421 | $_oldUserNotificationStatusTitle = $this->Language->Get('private');
|
2422 | }
|
2423 |
|
2424 | if ($_ticketStatusCache[$_ticketStatusID]['statustype'] == SWIFT_PRIVATE) {
|
2425 | $_newUserNotificationStatusTitle = $this->Language->Get('private');
|
2426 | }
|
2427 |
|
2428 | $this->Notification->Update($this->Language->Get('notification_status'), $_oldNotificationStatusTitle, $_newNotificationStatusTitle, $_oldUserNotificationStatusTitle, $_newUserNotificationStatusTitle);
|
2429 |
|
2430 | $this->UpdatePool('ticketstatusid', intval($_ticketStatusID));
|
2431 | $this->UpdatePool('ticketstatustitle', $_newStatusTitle);
|
2432 |
|
2433 | // SWIFT_TicketManager::Recount($this->GetProperty('departmentid'));
|
2434 | SWIFT_TicketManager::Recount(false);
|
2435 |
|
2436 | // Was reopened?
|
2437 | if ($_ticketStatusContainer['markasresolved'] == '0' && $this->GetProperty('isresolved') == '1') {
|
2438 | $this->UpdatePool('wasreopened', '1');
|
2439 | $this->UpdatePool('reopendateline', DATENOW);
|
2440 | }
|
2441 |
|
2442 | if ($_ticketStatusContainer['resetduetime'] == '1') {
|
2443 | $this->ClearOverdue();
|
2444 | }
|
2445 |
|
2446 | if ($_ticketStatusContainer['markasresolved'] == '1')
|
2447 | {
|
2448 | $this->UpdatePool('isresolved', '1');
|
2449 | $this->UpdatePool('resolutiondateline', DATENOW);
|
2450 | $this->UpdatePool('repliestoresolution', $this->GetProperty('totalreplies'));
|
2451 |
|
2452 | // How much time did it take to resolve this ticket?
|
2453 | $this->UpdatePool('resolutionseconds', DATENOW-$this->GetProperty('dateline'));
|
2454 | } else {
|
2455 | $this->UpdatePool('isresolved', '0');
|
2456 |
|
2457 | // Are we changing to an unresolved status and ticket is marked as auto closed or pending closure?
|
2458 | if ($this->GetProperty('autoclosestatus') != self::AUTOCLOSESTATUS_NONE) {
|
2459 | $this->UpdatePool('autoclosestatus', self::AUTOCLOSESTATUS_NONE);
|
2460 | $this->UpdatePool('isautoclosed', '0');
|
2461 | $this->UpdatePool('autoclosetimeline', '0');
|
2462 | }
|
2463 | }
|
2464 |
|
2465 | // If the status is set to resolved then we reset the resolution due time
|
2466 | $_processResolutionDue = false;
|
2467 | if ($_ticketStatusContainer['markasresolved'] == '1') {
|
2468 | $this->UpdatePool('resolutionduedateline', '0');
|
2469 | $this->UpdatePool('duetime', '0');
|
2470 | $this->UpdatePool('slaplanid', '0');
|
2471 |
|
2472 | $this->_noSLACalculation = true;
|
2473 |
|
2474 | // Otherwise if its not, and resolutionduedateline is 0 then we force it to recalculate the resolution due time
|
2475 | } else if ($_ticketStatusContainer['markasresolved'] == '0' && $this->GetProperty('resolutionduedateline') == '0') {
|
2476 | $_processResolutionDue = true;
|
2477 | }
|
2478 |
|
2479 | // Do we have to trigger a survey?
|
2480 | if ($_ticketStatusContainer['triggersurvey'] == '1' && !$_suppressSurveyEmail)
|
2481 | {
|
2482 | $this->Load->Library('Ticket:TicketEmailDispatch', array($this));
|
2483 | $this->TicketEmailDispatch->DispatchSurvey();
|
2484 | }
|
2485 |
|
2486 | $this->QueueSLAOverdue($_processResolutionDue);
|
2487 |
|
2488 | // Is First Contact Resolved?
|
2489 | if ($this->GetProperty('totalreplies') == '0' && $_ticketStatusContainer['markasresolved'] == '1' && $this->GetProperty('isfirstcontactresolved') == '0') {
|
2490 | $this->UpdatePool('isfirstcontactresolved', '1');
|
2491 | }
|
2492 |
|
2493 | // Load and Process Workflow Rules
|
2494 | self::AddToWorkflowQueue($this);
|
2495 |
|
2496 | return true;
|
2497 | }
|
2498 |
|
2499 | /**
|
2500 | * Set the Ticket Priority
|
2501 | *
|
2502 | * @author Varun Shoor
|
2503 | * @param int $_ticketPriorityID The Ticket Priority ID
|
2504 | * @return bool "true" on Success, "false" otherwise
|
2505 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
2506 | */
|
2507 | public function SetPriority($_ticketPriorityID) {
|
2508 | $_SWIFT = SWIFT::GetInstance();
|
2509 |
|
2510 | if (!$this->GetIsClassLoaded()) {
|
2511 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2512 |
|
2513 | return false;
|
2514 | } else if (empty($_ticketPriorityID)) {
|
2515 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2516 | }
|
2517 |
|
2518 | $_ticketPriorityCache = $this->Cache->Get('prioritycache');
|
2519 | if (!isset($_ticketPriorityCache[$_ticketPriorityID])) {
|
2520 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2521 | }
|
2522 |
|
2523 | $_ticketPriorityContainer = $_ticketPriorityCache[$_ticketPriorityID];
|
2524 |
|
2525 | // If the current ticket priority id matches then bail out
|
2526 | if ($this->GetProperty('priorityid') == $_ticketPriorityID) {
|
2527 | return true;
|
2528 | }
|
2529 |
|
2530 | // Create Audit Log
|
2531 | $_oldPriorityTitle = $_newPriorityTitle = '';
|
2532 | if (isset($_ticketPriorityCache[$this->GetProperty('priorityid')])) {
|
2533 | $_oldPriorityTitle = $_ticketPriorityCache[$this->GetProperty('priorityid')]['title'];
|
2534 | }
|
2535 |
|
2536 | $_newPriorityTitle = $_ticketPriorityCache[$_ticketPriorityID]['title'];
|
2537 |
|
2538 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATEPRIORITY,
|
2539 | sprintf($_SWIFT->Language->Get('al_priority'), $_oldPriorityTitle, $_newPriorityTitle),
|
2540 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('priorityid'), '', $_ticketPriorityID, '');
|
2541 |
|
2542 | // Notification Rule
|
2543 | $this->NotificationManager->Changed(SWIFT_NotificationRule::CRITERIA_TICKETPRIORITY, $this->GetProperty('priorityid'), $_ticketPriorityID);
|
2544 |
|
2545 | // Notification Update
|
2546 | $_oldNotificationPriorityTitle = $_newNotificationPriorityTitle = '';
|
2547 | if ($_oldPriorityTitle == '') {
|
2548 | $_oldNotificationPriorityTitle = $this->Language->Get('na');
|
2549 | } else {
|
2550 | $_oldNotificationPriorityTitle = $_oldPriorityTitle;
|
2551 | }
|
2552 |
|
2553 | $_newNotificationPriorityTitle = $_newPriorityTitle;
|
2554 |
|
2555 | $_oldUserNotificationPriorityTitle = $_oldNotificationPriorityTitle;
|
2556 | $_newUserNotificationPriorityTitle = $_newNotificationPriorityTitle;
|
2557 |
|
2558 | if ($_ticketPriorityCache[$this->GetProperty('priorityid')]['type'] == SWIFT_PRIVATE) {
|
2559 | $_oldUserNotificationPriorityTitle = $this->Language->Get('private');
|
2560 | }
|
2561 |
|
2562 | if ($_ticketPriorityCache[$_ticketPriorityID]['type'] == SWIFT_PRIVATE) {
|
2563 | $_newUserNotificationPriorityTitle = $this->Language->Get('private');
|
2564 | }
|
2565 |
|
2566 | $this->Notification->Update($this->Language->Get('notification_priority'), $_oldNotificationPriorityTitle, $_newNotificationPriorityTitle, $_oldUserNotificationPriorityTitle, $_newUserNotificationPriorityTitle);
|
2567 |
|
2568 | $this->UpdatePool('priorityid', intval($_ticketPriorityID));
|
2569 | $this->UpdatePool('prioritytitle', $_newPriorityTitle);
|
2570 |
|
2571 | // SWIFT_TicketManager::Recount($this->GetProperty('departmentid'));
|
2572 | SWIFT_TicketManager::Recount(false);
|
2573 |
|
2574 | $this->QueueSLAOverdue();
|
2575 |
|
2576 | // Load and Process Workflow Rules
|
2577 | self::AddToWorkflowQueue($this);
|
2578 |
|
2579 | return true;
|
2580 | }
|
2581 |
|
2582 | /**
|
2583 | * Set the Ticket Owner
|
2584 | *
|
2585 | * @author Varun Shoor
|
2586 | * @param int $_staffID The Owner Staff ID
|
2587 | * @return bool "true" on Success, "false" otherwise
|
2588 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
2589 | */
|
2590 | public function SetOwner($_staffID) {
|
2591 | $_SWIFT = SWIFT::GetInstance();
|
2592 |
|
2593 | if (!$this->GetIsClassLoaded()) {
|
2594 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2595 |
|
2596 | return false;
|
2597 | }
|
2598 |
|
2599 | $_staffCache = $this->Cache->Get('staffcache');
|
2600 | if ($_staffID != 0 && !isset($_staffCache[$_staffID])) {
|
2601 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2602 | }
|
2603 |
|
2604 | // If the current owner matches the one provided then bail out
|
2605 | if ($this->GetProperty('ownerstaffid') == $_staffID) {
|
2606 | return true;
|
2607 | }
|
2608 |
|
2609 | // Create Audit Log
|
2610 | $_oldOwnerTitle = $_newOwnerTitle = '';
|
2611 | if (isset($_staffCache[$this->GetProperty('ownerstaffid')])) {
|
2612 | $_oldOwnerTitle = $_staffCache[$this->GetProperty('ownerstaffid')]['fullname'];
|
2613 | }
|
2614 |
|
2615 | if ($this->GetProperty('ownerstaffid') == '0') {
|
2616 | $_oldOwnerTitle = $this->Language->Get('unassigned');
|
2617 | }
|
2618 |
|
2619 | if ($_staffID == '0') {
|
2620 | $_newOwnerTitle = $this->Language->Get('unassigned');
|
2621 | } else {
|
2622 | $_newOwnerTitle = $_staffCache[$_staffID]['fullname'];
|
2623 | }
|
2624 |
|
2625 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATEOWNER,
|
2626 | sprintf($_SWIFT->Language->Get('al_owner'), $_oldOwnerTitle, $_newOwnerTitle),
|
2627 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('ownerstaffid'), '', $_staffID, '');
|
2628 |
|
2629 | // Notification Event
|
2630 | $this->NotificationManager->SetEvent('ticketassigned');
|
2631 |
|
2632 | // Notification Rule
|
2633 | $this->NotificationManager->Changed(SWIFT_NotificationRule::CRITERIA_OWNER, $this->GetProperty('ownerstaffid'), $_staffID);
|
2634 |
|
2635 | // Notification Update
|
2636 | $_oldNotificationOwnerTitle = $_newNotificationOwnerTitle = '';
|
2637 | if ($_oldOwnerTitle == '') {
|
2638 | $_oldNotificationOwnerTitle = $this->Language->Get('na');
|
2639 | } else {
|
2640 | $_oldNotificationOwnerTitle = $_oldOwnerTitle;
|
2641 | }
|
2642 |
|
2643 | $_newNotificationOwnerTitle = $_newOwnerTitle;
|
2644 |
|
2645 | $this->Notification->Update($this->Language->Get('notification_staff'), $_oldNotificationOwnerTitle, $_newNotificationOwnerTitle);
|
2646 |
|
2647 |
|
2648 | $this->UpdatePool('ownerstaffid', intval($_staffID));
|
2649 |
|
2650 | $_staffName = '';
|
2651 | if (isset($_staffCache[$_staffID])) {
|
2652 | $_staffName = $_staffCache[$_staffID]['fullname'];
|
2653 | }
|
2654 |
|
2655 | $this->UpdatePool('ownerstaffname', $_staffName);
|
2656 |
|
2657 | // How many owners did it take to resolve this ticket?
|
2658 | $this->UpdatePool('resolutionlevel', intval($this->GetProperty('resolutionlevel'))+1);
|
2659 |
|
2660 | // SWIFT_TicketManager::Recount($this->GetProperty('departmentid'));
|
2661 | SWIFT_TicketManager::Recount(false);
|
2662 |
|
2663 | $this->QueueSLAOverdue();
|
2664 |
|
2665 | // Load the last notification message for ticket assigned alert
|
2666 | $this->LoadLastPostNotificationMessage();
|
2667 |
|
2668 | // Load and Process Workflow Rules
|
2669 | self::AddToWorkflowQueue($this);
|
2670 |
|
2671 | return true;
|
2672 | }
|
2673 |
|
2674 | /**
|
2675 | * Set the Due Time
|
2676 | *
|
2677 | * @author Varun Shoor
|
2678 | * @param string $_dueDateline The Due Dateline
|
2679 | * @return bool "true" on Success, "false" otherwise
|
2680 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
2681 | */
|
2682 | public function SetDue($_dueDateline) {
|
2683 | $_SWIFT = SWIFT::GetInstance();
|
2684 |
|
2685 | if (!$this->GetIsClassLoaded()) {
|
2686 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2687 |
|
2688 | return false;
|
2689 | } else if (empty($_dueDateline)) {
|
2690 | return false;
|
2691 | }
|
2692 |
|
2693 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
|
2694 | sprintf($_SWIFT->Language->Get('al_due'), SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_dueDateline)),
|
2695 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('duetime'), '', $_dueDateline, '');
|
2696 |
|
2697 | // Notification Update
|
2698 | $_oldNotificationDueTitle = $_newNotificationDueTitle = '';
|
2699 | if ($this->GetProperty('duetime') == '0') {
|
2700 | $_oldNotificationDueTitle = $this->Language->Get('na');
|
2701 | } else {
|
2702 | $_oldNotificationDueTitle = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $this->GetProperty('duetime'));
|
2703 | }
|
2704 |
|
2705 | $_newNotificationDueTitle = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_dueDateline);
|
2706 |
|
2707 | $this->Notification->Update($this->Language->Get('notification_due'), $_oldNotificationDueTitle, $_newNotificationDueTitle);
|
2708 |
|
2709 | // Prevent calculation of SLA due time on this ticket
|
2710 | $this->_noSLACalculation = true;
|
2711 |
|
2712 | $this->UpdatePool('duetime', intval($_dueDateline));
|
2713 |
|
2714 | return true;
|
2715 | }
|
2716 |
|
2717 | /**
|
2718 | * Set the Resolution Due Time
|
2719 | *
|
2720 | * @author Varun Shoor
|
2721 | * @param string $_dueDateline The Due Dateline
|
2722 | * @return bool "true" on Success, "false" otherwise
|
2723 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
2724 | */
|
2725 | public function SetResolutionDue($_dueDateline) {
|
2726 | $_SWIFT = SWIFT::GetInstance();
|
2727 |
|
2728 | if (!$this->GetIsClassLoaded()) {
|
2729 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2730 |
|
2731 | return false;
|
2732 | } else if (empty($_dueDateline)) {
|
2733 | return false;
|
2734 | }
|
2735 |
|
2736 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
|
2737 | sprintf($_SWIFT->Language->Get('al_resolutiondue'), SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_dueDateline)),
|
2738 | SWIFT_TicketAuditLog::VALUE_NONE, $this->GetProperty('duetime'), '', $_dueDateline, '');
|
2739 |
|
2740 | // Notification Update
|
2741 | $_oldNotificationDueTitle = $_newNotificationDueTitle = '';
|
2742 | if ($this->GetProperty('resolutionduedateline') == '0') {
|
2743 | $_oldNotificationDueTitle = $this->Language->Get('na');
|
2744 | } else {
|
2745 | $_oldNotificationDueTitle = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $this->GetProperty('resolutionduedateline'));
|
2746 | }
|
2747 |
|
2748 | $_newNotificationDueTitle = SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_dueDateline);
|
2749 |
|
2750 | $this->Notification->Update($this->Language->Get('notification_resolutiondue'), $_oldNotificationDueTitle, $_newNotificationDueTitle);
|
2751 |
|
2752 | // Prevent calculation of SLA due time on this ticket
|
2753 | $this->_noSLACalculation = true;
|
2754 |
|
2755 | $this->UpdatePool('resolutionduedateline', intval($_dueDateline));
|
2756 |
|
2757 | return true;
|
2758 | }
|
2759 |
|
2760 | /**
|
2761 | * Retrieve the linked tickets in the active chain
|
2762 | *
|
2763 | * @author Varun Shoor
|
2764 | * @return array The Linked Ticket Container
|
2765 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
2766 | */
|
2767 | public function GetLinks() {
|
2768 | if (!$this->GetIsClassLoaded()) {
|
2769 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2770 |
|
2771 | return false;
|
2772 | }
|
2773 |
|
2774 | if ($this->GetProperty('islinked') == '0') {
|
2775 | return array();
|
2776 | }
|
2777 |
|
2778 | // First get all the chain hashes where this ticket is part of
|
2779 | $_chainHashList = array();
|
2780 | $this->Database->Query("SELECT chainhash FROM " . TABLE_PREFIX . "ticketlinkchains WHERE ticketid = '" . intval($this->GetTicketID()) .
|
2781 | "'");
|
2782 | while ($this->Database->NextRecord()) {
|
2783 | $_chainHashList[] = $this->Database->Record['chainhash'];
|
2784 | }
|
2785 |
|
2786 | if (!count($_chainHashList)) {
|
2787 | return array();
|
2788 | }
|
2789 |
|
2790 | // Now get all the tickets that are part of the chain hashes
|
2791 | $_ticketLinkContainer = array();
|
2792 | $this->Database->Query("SELECT tickets.*, ticketlinkchains.ticketlinktypeid FROM " . TABLE_PREFIX . "ticketlinkchains AS ticketlinkchains
|
2793 | LEFT JOIN " . TABLE_PREFIX . "tickets AS tickets ON (ticketlinkchains.ticketid = tickets.ticketid) WHERE
|
2794 | chainhash IN (" . BuildIN($_chainHashList) . ")");
|
2795 | while ($this->Database->NextRecord()) {
|
2796 | if ($this->Database->Record['ticketid'] == $this->GetTicketID()) {
|
2797 | continue;
|
2798 | }
|
2799 |
|
2800 | $_ticketLinkContainer[$this->Database->Record['ticketlinktypeid']][$this->Database->Record['ticketid']] =
|
2801 | new SWIFT_Ticket(new SWIFT_DataStore($this->Database->Record));
|
2802 | }
|
2803 |
|
2804 | return $_ticketLinkContainer;
|
2805 | }
|
2806 |
|
2807 | /**
|
2808 | * Mark ticket as linked
|
2809 | *
|
2810 | * @author Varun Shoor
|
2811 | * @return bool "true" on Success, "false" otherwise
|
2812 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
2813 | */
|
2814 | public function MarkAsLinked() {
|
2815 | if (!$this->GetIsClassLoaded()) {
|
2816 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2817 |
|
2818 | return false;
|
2819 | }
|
2820 |
|
2821 | $this->UpdatePool('islinked', '1');
|
2822 |
|
2823 | return true;
|
2824 | }
|
2825 |
|
2826 | /**
|
2827 | * Mark ticket as unlinked
|
2828 | *
|
2829 | * @author Varun Shoor
|
2830 | * @return bool "true" on Success, "false" otherwise
|
2831 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
2832 | */
|
2833 | public function MarkAsUnlinked() {
|
2834 | if (!$this->GetIsClassLoaded()) {
|
2835 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2836 |
|
2837 | return false;
|
2838 | }
|
2839 |
|
2840 | $this->UpdatePool('islinked', '0');
|
2841 |
|
2842 | return true;
|
2843 | }
|
2844 |
|
2845 | /**
|
2846 | * Lock a Ticket
|
2847 | *
|
2848 | * @author Varun Shoor
|
2849 | * @param SWIFT_Staff $_SWIFT_StaffObject The SWIFT_Staff Object Pointer
|
2850 | * @return bool "true" on Success, "false" otherwise
|
2851 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
2852 | */
|
2853 | public function Lock(SWIFT_Staff $_SWIFT_StaffObject) {
|
2854 | if (!$this->GetIsClassLoaded()) {
|
2855 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2856 |
|
2857 | return false;
|
2858 | } else if (!$_SWIFT_StaffObject instanceof SWIFT_Staff || !$_SWIFT_StaffObject->GetIsClassLoaded()) {
|
2859 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
2860 | }
|
2861 |
|
2862 | SWIFT_TicketLock::Create($this, $_SWIFT_StaffObject);
|
2863 |
|
2864 | return true;
|
2865 | }
|
2866 |
|
2867 | /**
|
2868 | * Unlock the ticket completely
|
2869 | *
|
2870 | * @author Varun Shoor
|
2871 | * @return bool "true" on Success, "false" otherwise
|
2872 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
2873 | */
|
2874 | public function Unlock() {
|
2875 | if (!$this->GetIsClassLoaded()) {
|
2876 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2877 |
|
2878 | return false;
|
2879 | }
|
2880 |
|
2881 | SWIFT_TicketLock::DeleteOnTicket(array($this->GetTicketID()));
|
2882 |
|
2883 | return true;
|
2884 | }
|
2885 |
|
2886 | /**
|
2887 | * Rebuild the Ticket Properties (hasnotes, hasattachments etc.)
|
2888 | *
|
2889 | * @author Varun Shoor
|
2890 | * @return bool "true" on Success, "false" otherwise
|
2891 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
2892 | */
|
2893 | public function RebuildProperties() {
|
2894 | if (!$this->GetIsClassLoaded()) {
|
2895 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
2896 |
|
2897 | return false;
|
2898 | }
|
2899 |
|
2900 | $_ticketStatusCache = $this->Cache->Get('statuscache');
|
2901 |
|
2902 | /**
|
2903 | * BUG FIX - Parminder Singh
|
2904 | *
|
2905 | * SWIFT-1894: 'Trash' count does not clear the ticket count in case a department is deleted
|
2906 | *
|
2907 | */
|
2908 |
|
2909 | $_departmentCache = $this->Cache->Get('departmentcache');
|
2910 |
|
2911 | if ($this->GetProperty('trasholddepartmentid') != '0' && !isset($_departmentCache[$this->GetProperty('trasholddepartmentid')])) {
|
2912 | $this->UpdatePool('trasholddepartmentid', '0');
|
2913 | }
|
2914 |
|
2915 | // First Post, Last Post & Total Replies
|
2916 | $_ticketPostIDContainer = $this->Database->QueryFetch("SELECT MIN(ticketpostid) AS firstpostid, MAX(ticketpostid) AS lastpostid,
|
2917 | COUNT(*) AS totalreplies FROM " . TABLE_PREFIX . "ticketposts WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
2918 | if (isset($_ticketPostIDContainer['firstpostid']) && !empty($_ticketPostIDContainer['firstpostid']))
|
2919 | {
|
2920 | $this->UpdatePool('firstpostid', intval($_ticketPostIDContainer['firstpostid']));
|
2921 | }
|
2922 |
|
2923 | if (isset($_ticketPostIDContainer['lastpostid']) && !empty($_ticketPostIDContainer['lastpostid']))
|
2924 | {
|
2925 | $this->UpdatePool('lastpostid', intval($_ticketPostIDContainer['lastpostid']));
|
2926 |
|
2927 | $_lastTicketPostContainer = $this->Database->QueryFetch("SELECT fullname, dateline FROM " . TABLE_PREFIX . "ticketposts WHERE
|
2928 | ticketpostid = '" . intval($_ticketPostIDContainer['lastpostid']) . "'");
|
2929 |
|
2930 | if (isset($_lastTicketPostContainer['fullname']) && !empty($_lastTicketPostContainer['fullname']))
|
2931 | {
|
2932 | $this->UpdatePool('lastreplier', $_lastTicketPostContainer['fullname']);
|
2933 | }
|
2934 |
|
2935 | if (isset($_lastTicketPostContainer['dateline']) && $_lastTicketPostContainer['dateline'] > $this->GetProperty('lastactivity'))
|
2936 | {
|
2937 | $this->UpdatePool('lastactivity', intval($_lastTicketPostContainer['dateline']));
|
2938 | }
|
2939 | }
|
2940 |
|
2941 | if (isset($_ticketPostIDContainer['totalreplies']))
|
2942 | {
|
2943 | // We deduct by 1 to ignore the original ticket post as a reply
|
2944 | if ($_ticketPostIDContainer['totalreplies'] > 0)
|
2945 | {
|
2946 | $_ticketPostIDContainer['totalreplies']--;
|
2947 | }
|
2948 |
|
2949 | $this->UpdatePool('totalreplies', intval($_ticketPostIDContainer['totalreplies']));
|
2950 | }
|
2951 |
|
2952 | // Has Notes?
|
2953 | $_hasNotesContainer = $this->Database->QueryFetch("SELECT COUNT(*) AS totalnotes FROM " . TABLE_PREFIX . "ticketnotes WHERE
|
2954 | linktypeid = '" . intval($this->GetTicketID()) . "' AND linktype = '" . SWIFT_TicketNoteManager::LINKTYPE_TICKET . "'");
|
2955 |
|
2956 | $this->UpdatePool('hasnotes', IIF($_hasNotesContainer['totalnotes'] > 0, '1', '0'));
|
2957 |
|
2958 | // Has Attachments?
|
2959 | $_hasAttachmentsContainer = $this->Database->QueryFetch("SELECT COUNT(*) AS totalattachments FROM " . TABLE_PREFIX . "attachments WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
2960 |
|
2961 | $this->UpdatePool('hasattachments', IIF($_hasAttachmentsContainer['totalattachments'] > 0, '1', '0'));
|
2962 |
|
2963 | /**
|
2964 | * BUG FIX - Saloni Dhall
|
2965 | *
|
2966 | * SWIFT-2576: 'hasattachments' field is not getting saved if ticket is having attachments
|
2967 | *
|
2968 | */
|
2969 | $_storeTicketIDList = $this->GetTicketPostIDList();
|
2970 | if (is_array($_storeTicketIDList) && !empty($_storeTicketIDList)) {
|
2971 | foreach ($_storeTicketIDList as $_ticketPostID)
|
2972 | {
|
2973 | $_hasAttachmentsContainer = $this->Database->QueryFetch("SELECT COUNT(*) as attachmentcount FROM " . TABLE_PREFIX . "attachments WHERE linktypeid = '" . $_ticketPostID . "'");
|
2974 | $_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
|
2975 | $_SWIFT_TicketPostObject->UpdatePool('hasattachments', IIF($_hasAttachmentsContainer['attachmentcount'] > 0, '1', '0'));
|
2976 | }
|
2977 | }
|
2978 |
|
2979 | // Has Draft?
|
2980 | $_hasDraftContainer = $this->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "ticketdrafts WHERE
|
2981 | ticketid = '" . intval($this->GetTicketID()) . "'");
|
2982 |
|
2983 | $this->UpdatePool('hasdraft', IIF($_hasDraftContainer['totalitems'] > 0, '1', '0'));
|
2984 |
|
2985 | // Has Billing Entries?
|
2986 | $_hasBillingContainer = $this->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "tickettimetracks WHERE
|
2987 | ticketid = '" . intval($this->GetTicketID()) . "'");
|
2988 |
|
2989 | $this->UpdatePool('hasbilling', IIF($_hasBillingContainer['totalitems'] > 0, '1', '0'));
|
2990 |
|
2991 | // Has Follow-Up's?
|
2992 | $_hasFollowUpContainer = $this->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "ticketfollowups WHERE
|
2993 | ticketid = '" . intval($this->GetTicketID()) . "'");
|
2994 |
|
2995 | $this->UpdatePool('hasfollowup', IIF($_hasFollowUpContainer['totalitems'] > 0, '1', '0'));
|
2996 | $this->UpdatePool('followupcount', intval($_hasFollowUpContainer['totalitems']));
|
2997 |
|
2998 | // Update time worked + time billed
|
2999 | $_ticketTimeWorked = $_ticketTimeBillable = 0;
|
3000 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickettimetracks WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
3001 | while ($this->Database->NextRecord())
|
3002 | {
|
3003 | $_ticketTimeWorked += intval($this->Database->Record['timespent']);
|
3004 | $_ticketTimeBillable += intval($this->Database->Record['timebillable']);
|
3005 | }
|
3006 |
|
3007 | $this->UpdateTimeTrack($_ticketTimeWorked, $_ticketTimeBillable);
|
3008 |
|
3009 | // Is Resolved
|
3010 | if (isset($_ticketStatusCache[$this->GetProperty('ticketstatusid')])) {
|
3011 | if ($_ticketStatusCache[$this->GetProperty('ticketstatusid')]['markasresolved'] == '1')
|
3012 | {
|
3013 | $this->UpdatePool('isresolved', '1');
|
3014 | $this->UpdatePool('repliestoresolution', $this->GetProperty('totalreplies'));
|
3015 | } else {
|
3016 | $this->UpdatePool('isresolved', '0');
|
3017 | }
|
3018 | }
|
3019 |
|
3020 | // Rebuild the titles & names
|
3021 | $this->RebuildTitles();
|
3022 |
|
3023 | // Calculate the additional properties
|
3024 | $this->CalculateProperties();
|
3025 |
|
3026 | // Load and Process Workflow Rules
|
3027 | self::AddToWorkflowQueue($this);
|
3028 |
|
3029 | return true;
|
3030 | }
|
3031 |
|
3032 | /**
|
3033 | * Rebuilds the titles associated with the ticket
|
3034 | *
|
3035 | * @author Varun Shoor
|
3036 | * @return bool "true" on Success, "false" otherwise
|
3037 | * @throws SWIFT_Exception If the Class is not Loaded
|
3038 | */
|
3039 | protected function RebuildTitles()
|
3040 | {
|
3041 | if (!$this->GetIsClassLoaded()) {
|
3042 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
3043 |
|
3044 | return false;
|
3045 | }
|
3046 |
|
3047 | $_departmentCache = $this->Cache->Get('departmentcache');
|
3048 | $_staffCache = $this->Cache->Get('staffcache');
|
3049 | $_ticketStatusCache = $this->Cache->Get('statuscache');
|
3050 | $_ticketPriorityCache = $this->Cache->Get('prioritycache');
|
3051 | $_ticketTypeCache = $this->Cache->Get('tickettypecache');
|
3052 | $_slaPlanCache = $this->Cache->Get('slaplancache');
|
3053 | $_escalationRuleCache = $this->Cache->Get('escalationrulecache');
|
3054 |
|
3055 | // Build local properties
|
3056 | if (isset($_departmentCache[$this->GetProperty('departmentid')])) {
|
3057 | $this->UpdatePool('departmenttitle', $_departmentCache[$this->GetProperty('departmentid')]['title']);
|
3058 | }
|
3059 |
|
3060 | if (isset($_staffCache[$this->GetProperty('ownerstaffid')])) {
|
3061 | $this->UpdatePool('ownerstaffname', $_staffCache[$this->GetProperty('ownerstaffid')]['fullname']);
|
3062 | }
|
3063 |
|
3064 | if (isset($_ticketStatusCache[$this->GetProperty('ticketstatusid')])) {
|
3065 | $this->UpdatePool('ticketstatustitle', $_ticketStatusCache[$this->GetProperty('ticketstatusid')]['title']);
|
3066 | }
|
3067 |
|
3068 | if (isset($_ticketPriorityCache[$this->GetProperty('priorityid')])) {
|
3069 | $this->UpdatePool('prioritytitle', $_ticketPriorityCache[$this->GetProperty('priorityid')]['title']);
|
3070 | }
|
3071 |
|
3072 | if (isset($_ticketTypeCache[$this->GetProperty('tickettypeid')])) {
|
3073 | $this->UpdatePool('tickettypetitle', $_ticketTypeCache[$this->GetProperty('tickettypeid')]['title']);
|
3074 | }
|
3075 |
|
3076 | // Ticket Drafts
|
3077 | $_ticketDraftUpdateContainer = array();
|
3078 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "ticketdrafts WHERE ticketid = '" . $this->GetTicketID() . "'");
|
3079 | while ($this->Database->NextRecord()) {
|
3080 | $_ticketDraftUpdateContainer[$this->Database->Record['ticketdraftid']] = $this->Database->Record;
|
3081 |
|
3082 | if (isset($_staffCache[$this->Database->Record['staffid']])) {
|
3083 | $_ticketDraftUpdateContainer[$this->Database->Record['staffname']] = $_staffCache[$this->Database->Record['staffid']]['fullname'];
|
3084 | }
|
3085 |
|
3086 | if (isset($_staffCache[$this->Database->Record['editedbystaffid']])) {
|
3087 | $_ticketDraftUpdateContainer[$this->Database->Record['editedstaffname']] = $_staffCache[$this->Database->Record['editedbystaffid']]['fullname'];
|
3088 | }
|
3089 | }
|
3090 |
|
3091 | foreach ($_ticketDraftUpdateContainer as $_ticketDraftID => $_ticketDraft) {
|
3092 | SWIFT_TicketDraft::UpdateStaffName($_ticketDraftID, $_ticketDraft['staffname'], $_ticketDraft['editedstaffname']);
|
3093 | }
|
3094 | unset($_ticketDraftUpdateContainer);
|
3095 |
|
3096 | // Ticket Audit Logs
|
3097 | $_ticketAuditLogUpdateContainer = array();
|
3098 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "ticketauditlogs WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
3099 | while ($this->Database->NextRecord()) {
|
3100 | $_ticketAuditLogUpdateContainer[$this->Database->Record['ticketauditlogid']] = $this->Database->Record;
|
3101 |
|
3102 | if (isset($_departmentCache[$this->Database->Record['departmentid']])) {
|
3103 | $_ticketAuditLogUpdateContainer[$this->Database->Record['ticketauditlogid']]['departmenttitle'] = $_departmentCache[$this->Database->Record['departmentid']]['title'];
|
3104 | }
|
3105 |
|
3106 | if ($this->Database->Record['creatortype'] == SWIFT_TicketAuditLog::CREATOR_STAFF && isset($_staffCache[$this->Database->Record['creatorid']])) {
|
3107 | $_ticketAuditLogUpdateContainer[$this->Database->Record['ticketauditlogid']]['creatorfullname'] = $_staffCache[$this->Database->Record['creatorid']]['fullname'];
|
3108 | }
|
3109 | }
|
3110 |
|
3111 | foreach ($_ticketAuditLogUpdateContainer as $_ticketAuditLogID => $_ticketAuditLog) {
|
3112 | SWIFT_TicketAuditLog::UpdateProperties($_ticketAuditLogID, $_ticketAuditLog['departmenttitle'], $_ticketAuditLog['creatorfullname']);
|
3113 | }
|
3114 | unset($_ticketAuditLogUpdateContainer);
|
3115 |
|
3116 | // Ticket Notes
|
3117 | $_ticketNoteUpdateContainer = array();
|
3118 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "ticketnotes
|
3119 | WHERE linktype = '" . SWIFT_TicketNote::LINKTYPE_TICKET . "' AND linktypeid = '" . intval($this->GetTicketID()) . "'");
|
3120 | while ($this->Database->NextRecord()) {
|
3121 | $_ticketNoteUpdateContainer[$this->Database->Record['ticketnoteid']] = $this->Database->Record;
|
3122 |
|
3123 | if (isset($_staffCache[$this->Database->Record['staffid']])) {
|
3124 | $_ticketNoteUpdateContainer[$this->Database->Record['ticketnoteid']]['staffname'] = $_staffCache[$this->Database->Record['staffid']]['fullname'];
|
3125 | }
|
3126 |
|
3127 | if (isset($_staffCache[$this->Database->Record['editedstaffid']])) {
|
3128 | $_ticketNoteUpdateContainer[$this->Database->Record['ticketnoteid']]['editedstaffname'] = $_staffCache[$this->Database->Record['editedstaffid']]['fullname'];
|
3129 | }
|
3130 | }
|
3131 |
|
3132 | foreach ($_ticketNoteUpdateContainer as $_ticketNoteID => $_ticketNote) {
|
3133 | SWIFT_TicketNoteManager::UpdateProperties($_ticketNoteID, $_ticketNote['staffname'], $_ticketNote['editedstaffname']);
|
3134 | }
|
3135 |
|
3136 | unset($_ticketNoteUpdateContainer);
|
3137 |
|
3138 | // Ticket Time Tracks
|
3139 | $_ticketTimeTrackUpdateContainer = array();
|
3140 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickettimetracks WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
3141 | while ($this->Database->NextRecord()) {
|
3142 | $_ticketTimeTrackUpdateContainer[$this->Database->Record['tickettimetrackid']] = $this->Database->Record;
|
3143 |
|
3144 | if (isset($_staffCache[$this->Database->Record['creatorstaffid']])) {
|
3145 | $_ticketTimeTrackUpdateContainer[$this->Database->Record['tickettimetrackid']]['creatorstaffname'] = $_staffCache[$this->Database->Record['creatorstaffid']]['fullname'];
|
3146 | }
|
3147 |
|
3148 | if (isset($_staffCache[$this->Database->Record['editedstaffid']])) {
|
3149 | $_ticketTimeTrackUpdateContainer[$this->Database->Record['tickettimetrackid']]['editedstaffname'] = $_staffCache[$this->Database->Record['editedstaffid']]['fullname'];
|
3150 | }
|
3151 |
|
3152 | if (isset($_staffCache[$this->Database->Record['workerstaffid']])) {
|
3153 | $_ticketTimeTrackUpdateContainer[$this->Database->Record['tickettimetrackid']]['workerstaffname'] = $_staffCache[$this->Database->Record['workerstaffid']]['fullname'];
|
3154 | }
|
3155 | }
|
3156 |
|
3157 | foreach ($_ticketTimeTrackUpdateContainer as $_ticketTimeTrackID => $_ticketTimeTrack) {
|
3158 | SWIFT_TicketTimeTrack::UpdateProperties($_ticketTimeTrackID, $_ticketTimeTrack['creatorstaffname'], $_ticketTimeTrack['editedstaffname'], $_ticketTimeTrack['workerstaffname']);
|
3159 | }
|
3160 | unset($_ticketTimeTrackUpdateContainer);
|
3161 |
|
3162 | // Escalation Paths
|
3163 | $_escalationPathUpdateContainer = array();
|
3164 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "escalationpaths WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
3165 | while ($this->Database->NextRecord()) {
|
3166 | $_escalationPathUpdateContainer[$this->Database->Record['escalationpathid']] = $this->Database->Record;
|
3167 |
|
3168 | if (isset($_slaPlanCache[$this->Database->Record['slaplanid']])) {
|
3169 | $_escalationPathUpdateContainer[$this->Database->Record['escalationpathid']]['slaplantitle'] = $_slaPlanCache[$this->Database->Record['slaplanid']]['title'];
|
3170 | }
|
3171 |
|
3172 | if (isset($_escalationRuleCache[$this->Database->Record['escalationruleid']])) {
|
3173 | $_escalationPathUpdateContainer[$this->Database->Record['escalationpathid']]['escalationruletitle'] = $_escalationRuleCache[$this->Database->Record['escalationruleid']]['title'];
|
3174 | }
|
3175 |
|
3176 | if (isset($_staffCache[$this->Database->Record['ownerstaffid']])) {
|
3177 | $_escalationPathUpdateContainer[$this->Database->Record['escalationpathid']]['ownerstaffname'] = $_staffCache[$this->Database->Record['ownerstaffid']]['fullname'];
|
3178 | }
|
3179 |
|
3180 | if (isset($_departmentCache[$this->Database->Record['departmentid']])) {
|
3181 | $_escalationPathUpdateContainer[$this->Database->Record['escalationpathid']]['departmenttitle'] = $_departmentCache[$this->Database->Record['departmentid']]['title'];
|
3182 | }
|
3183 |
|
3184 | if (isset($_ticketStatusCache[$this->Database->Record['ticketstatusid']])) {
|
3185 | $_escalationPathUpdateContainer[$this->Database->Record['escalationpathid']]['ticketstatustitle'] = $_ticketStatusCache[$this->Database->Record['ticketstatusid']]['title'];
|
3186 | }
|
3187 |
|
3188 | if (isset($_ticketPriorityCache[$this->Database->Record['priorityid']])) {
|
3189 | $_escalationPathUpdateContainer[$this->Database->Record['escalationpathid']]['prioritytitle'] = $_ticketPriorityCache[$this->Database->Record['priorityid']]['title'];
|
3190 | }
|
3191 |
|
3192 | if (isset($_ticketTypeCache[$this->Database->Record['tickettypeid']])) {
|
3193 | $_escalationPathUpdateContainer[$this->Database->Record['escalationpathid']]['tickettypetitle'] = $_ticketTypeCache[$this->Database->Record['tickettypeid']]['title'];
|
3194 | }
|
3195 | }
|
3196 |
|
3197 | foreach ($_escalationPathUpdateContainer as $_escalationPathID => $_escalationPath) {
|
3198 | SWIFT_EscalationPath::UpdateProperties($_escalationPathID, $_escalationPath['slaplantitle'], $_escalationPath['escalationruletitle'], $_escalationPath['ownerstaffname'],
|
3199 | $_escalationPath['departmenttitle'], $_escalationPath['ticketstatustitle'], $_escalationPath['prioritytitle'], $_escalationPath['tickettypetitle']);
|
3200 | }
|
3201 | unset($_escalationPathUpdateContainer);
|
3202 |
|
3203 | return true;
|
3204 | }
|
3205 |
|
3206 | /**
|
3207 | * Calculate the Ticket Properties like is firstcontactresolved etc.
|
3208 | *
|
3209 | * @author Varun Shoor
|
3210 | * @return bool "true" on Success, "false" otherwise
|
3211 | * @throws SWIFT_Exception If the Class is not Loaded
|
3212 | */
|
3213 | public function CalculateProperties() {
|
3214 | if (!$this->GetIsClassLoaded()) {
|
3215 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
3216 |
|
3217 | return false;
|
3218 | }
|
3219 |
|
3220 | $_SWIFT_TicketPostObject_Last = false;
|
3221 | try {
|
3222 | $_SWIFT_TicketPostObject_Last = new SWIFT_TicketPost(new SWIFT_DataID($this->GetProperty('lastpostid')));
|
3223 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
3224 | }
|
3225 |
|
3226 | // Is First Contact Resolved?
|
3227 | if ($this->GetProperty('totalreplies') == '1' && $_SWIFT_TicketPostObject_Last instanceof SWIFT_TicketPost && $_SWIFT_TicketPostObject_Last->GetIsClassLoaded() && $_SWIFT_TicketPostObject_Last->GetProperty('creator') == SWIFT_TicketPost::CREATOR_STAFF
|
3228 | && $this->GetProperty('isresolved') == '1' && $this->GetProperty('isfirstcontactresolved') == '0') {
|
3229 | $this->UpdatePool('isfirstcontactresolved', '1');
|
3230 | }
|
3231 |
|
3232 | $_lastActivity = $this->GetProperty('lastactivity');
|
3233 | $_lastPostActivity = $_lastActivity;
|
3234 | if ($_SWIFT_TicketPostObject_Last instanceof SWIFT_TicketPost && $_SWIFT_TicketPostObject_Last->GetIsClassLoaded()) {
|
3235 | $_lastPostActivity = $_SWIFT_TicketPostObject_Last->GetProperty('dateline');
|
3236 | }
|
3237 |
|
3238 | $_finalLastActivity = $_lastActivity;
|
3239 | if ($_lastPostActivity > $_finalLastActivity) {
|
3240 | $_finalLastActivity = $_lastPostActivity;
|
3241 | }
|
3242 |
|
3243 | if ($this->GetProperty('isresolved') == '1') {
|
3244 | $this->UpdatePool('resolutiondateline', $_finalLastActivity);
|
3245 |
|
3246 | // How much time did it take to resolve this ticket?
|
3247 | $this->UpdatePool('resolutionseconds', $_finalLastActivity-$this->GetProperty('dateline'));
|
3248 | } else {
|
3249 | $this->UpdatePool('resolutiondateline', '0');
|
3250 | $this->UpdatePool('resolutionseconds', '0');
|
3251 | }
|
3252 |
|
3253 | // Is watched?
|
3254 | $_ticketWatcherCountContainer = $this->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "ticketwatchers WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
3255 | if (isset($_ticketWatcherCountContainer['totalitems']) && $_ticketWatcherCountContainer['totalitems'] > 0) {
|
3256 | $this->UpdatePool('iswatched', '1');
|
3257 | } else {
|
3258 | $this->UpdatePool('iswatched', '0');
|
3259 | }
|
3260 |
|
3261 | // Calculate the average response time
|
3262 | $this->UpdatePool('averageresponsetime', '0');
|
3263 | $this->UpdatePool('averageresponsetimehits', '0');
|
3264 |
|
3265 | $_ticketPostContainer = array();
|
3266 | $_oldPostDateline = $_lastPostDateline = 0;
|
3267 | $this->Database->Query("SELECT ticketpostid, dateline, creator FROM " . TABLE_PREFIX . "ticketposts WHERE ticketid = '" . intval($this->GetTicketID()) . "' ORDER BY ticketpostid ASC");
|
3268 | while ($this->Database->NextRecord()) {
|
3269 | $_ticketPostContainer[$this->Database->Record['ticketpostid']] = $this->Database->Record;
|
3270 | }
|
3271 |
|
3272 | $_firstResponseTime = 0;
|
3273 |
|
3274 | foreach ($_ticketPostContainer as $_ticketPostID => $_ticketPost) {
|
3275 | if (!empty($_lastPostDateline)) {
|
3276 | $_responseTime = $_ticketPost['dateline'] - $_lastPostDateline;
|
3277 |
|
3278 | $_postFirstResponseTime = 0;
|
3279 |
|
3280 | if (empty($_firstResponseTime) && $_ticketPost['creator'] == SWIFT_TicketPost::CREATOR_STAFF) {
|
3281 | $_firstResponseTime = $_ticketPost['dateline'] - $this->GetProperty('dateline');
|
3282 | $_postFirstResponseTime = $_firstResponseTime;
|
3283 | }
|
3284 |
|
3285 | $_updateContainer = array();
|
3286 | $_updateContainer['responsetime'] = $_responseTime;
|
3287 |
|
3288 | if (!empty($_postFirstResponseTime)) {
|
3289 | $_updateContainer['firstresponsetime'] = $_postFirstResponseTime;
|
3290 | }
|
3291 |
|
3292 | $this->Database->AutoExecute(TABLE_PREFIX . 'ticketposts', $_updateContainer, 'UPDATE', "ticketpostid = '" . intval($_ticketPostID) . "'");
|
3293 | }
|
3294 |
|
3295 | if ($_ticketPost['creator'] != SWIFT_TicketPost::CREATOR_STAFF) {
|
3296 | $_oldPostDateline = $_ticketPost['dateline'];
|
3297 | } else if (!empty($_oldPostDateline) && $_ticketPost['creator'] == SWIFT_TicketPost::CREATOR_STAFF) {
|
3298 | $_responseTime = $_ticketPost['dateline']-$_oldPostDateline;
|
3299 | $this->UpdateAverageResponseTime($_responseTime);
|
3300 |
|
3301 | $_oldPostDateline = 0;
|
3302 | }
|
3303 |
|
3304 | $_lastPostDateline = $_ticketPost['dateline'];
|
3305 | }
|
3306 |
|
3307 | if (!empty($_firstResponseTime)) {
|
3308 | $this->UpdatePool('firstresponsetime', intval($_firstResponseTime));
|
3309 | }
|
3310 |
|
3311 | return true;
|
3312 | }
|
3313 |
|
3314 | /**
|
3315 | * Change the ticket's hasattachments property to true
|
3316 | *
|
3317 | * @author Varun Shoor
|
3318 | * @return bool "true" on Success, "false" otherwise
|
3319 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3320 | */
|
3321 | public function MarkHasAttachments() {
|
3322 | if (!$this->GetIsClassLoaded()) {
|
3323 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3324 |
|
3325 | return false;
|
3326 | }
|
3327 |
|
3328 | $this->UpdatePool('hasattachments', '1');
|
3329 |
|
3330 | return true;
|
3331 | }
|
3332 |
|
3333 | /**
|
3334 | * Change the ticket's hasratings property to true
|
3335 | *
|
3336 | * @author Varun Shoor
|
3337 | * @return bool "true" on Success, "false" otherwise
|
3338 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3339 | */
|
3340 | public function MarkHasRatings() {
|
3341 | if (!$this->GetIsClassLoaded()) {
|
3342 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3343 |
|
3344 | return false;
|
3345 | }
|
3346 |
|
3347 | $this->UpdatePool('hasratings', '1');
|
3348 |
|
3349 | return true;
|
3350 | }
|
3351 |
|
3352 | /**
|
3353 | * Change the ticket's hasfollowup property to true
|
3354 | *
|
3355 | * @author Varun Shoor
|
3356 | * @return bool "true" on Success, "false" otherwise
|
3357 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3358 | */
|
3359 | public function MarkHasFollowUp() {
|
3360 | if (!$this->GetIsClassLoaded()) {
|
3361 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3362 |
|
3363 | return false;
|
3364 | }
|
3365 |
|
3366 | $this->UpdatePool('hasfollowup', '1');
|
3367 |
|
3368 | return true;
|
3369 | }
|
3370 |
|
3371 | /**
|
3372 | * Change the ticket's hasdraft property to true
|
3373 | *
|
3374 | * @author Varun Shoor
|
3375 | * @return bool "true" on Success, "false" otherwise
|
3376 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3377 | */
|
3378 | public function MarkHasDraft() {
|
3379 | if (!$this->GetIsClassLoaded()) {
|
3380 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3381 |
|
3382 | return false;
|
3383 | }
|
3384 |
|
3385 | $this->UpdatePool('hasdraft', '1');
|
3386 |
|
3387 | return true;
|
3388 | }
|
3389 |
|
3390 | /**
|
3391 | * Change the ticket's hasdraft property to false
|
3392 | *
|
3393 | * @author Varun Shoor
|
3394 | * @return bool "true" on Success, "false" otherwise
|
3395 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3396 | */
|
3397 | public function ClearHasDraft() {
|
3398 | if (!$this->GetIsClassLoaded()) {
|
3399 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3400 |
|
3401 | return false;
|
3402 | }
|
3403 |
|
3404 | $this->UpdatePool('hasdraft', '0');
|
3405 |
|
3406 | return true;
|
3407 | }
|
3408 |
|
3409 | /**
|
3410 | * Change the ticket's hasnotes property to true
|
3411 | *
|
3412 | * @author Varun Shoor
|
3413 | * @return bool "true" on Success, "false" otherwise
|
3414 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3415 | */
|
3416 | public function MarkHasNotes() {
|
3417 | if (!$this->GetIsClassLoaded()) {
|
3418 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3419 |
|
3420 | return false;
|
3421 | }
|
3422 |
|
3423 | $this->UpdatePool('hasnotes', '1');
|
3424 |
|
3425 | return true;
|
3426 | }
|
3427 |
|
3428 | /**
|
3429 | * Change the ticket's hasbilling property to true
|
3430 | *
|
3431 | * @author Varun Shoor
|
3432 | * @return bool "true" on Success, "false" otherwise
|
3433 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3434 | */
|
3435 | public function MarkHasBilling() {
|
3436 | if (!$this->GetIsClassLoaded()) {
|
3437 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3438 |
|
3439 | return false;
|
3440 | }
|
3441 |
|
3442 | $this->UpdatePool('hasbilling', '1');
|
3443 |
|
3444 | return true;
|
3445 | }
|
3446 |
|
3447 | /**
|
3448 | * Update the time tracking information
|
3449 | *
|
3450 | * @author Varun Shoor
|
3451 | * @param int $_timeSpent The Time Spent
|
3452 | * @param int $_timeBilled The Time Billed
|
3453 | * @return bool "true" on Success, "false" otherwise
|
3454 | * @throws SWIFT_Exception If the Class is not Loaded
|
3455 | */
|
3456 | public function UpdateTimeTrack($_timeSpent, $_timeBilled)
|
3457 | {
|
3458 | if (!$this->GetIsClassLoaded())
|
3459 | {
|
3460 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
3461 |
|
3462 | return false;
|
3463 | }
|
3464 |
|
3465 | $this->UpdatePool('timeworked', intval($_timeSpent));
|
3466 | $this->UpdatePool('timebilled', intval($_timeBilled));
|
3467 |
|
3468 | return true;
|
3469 | }
|
3470 |
|
3471 | /**
|
3472 | * Set the Message ID for this Ticket
|
3473 | *
|
3474 | * @author Varun Shoor
|
3475 | * @param string $_messageID The Message ID
|
3476 | * @return bool "true" on Success, "false" otherwise
|
3477 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
3478 | */
|
3479 | public function SetMessageID($_messageID) {
|
3480 | if (!$this->GetIsClassLoaded()) {
|
3481 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3482 |
|
3483 | return false;
|
3484 | } else if (empty($_messageID)) {
|
3485 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3486 | }
|
3487 |
|
3488 | $this->UpdatePool('messageid', $_messageID);
|
3489 |
|
3490 | return true;
|
3491 | }
|
3492 |
|
3493 | /**
|
3494 | * Check to see if the given staff/user can access the ticket
|
3495 | *
|
3496 | * @author Varun Shoor
|
3497 | * @param SWIFT_Base $_SWIFT_BaseObject The SWIFT_Base Object Pointer
|
3498 | * @return bool "true" on Success, "false" otherwise
|
3499 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
3500 | */
|
3501 | public function CanAccess($_SWIFT_BaseObject) {
|
3502 | if (!$this->GetIsClassLoaded()) {
|
3503 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3504 |
|
3505 | return false;
|
3506 | } else if ((!$_SWIFT_BaseObject instanceof SWIFT_Staff || !$_SWIFT_BaseObject->GetIsClassLoaded()) &&
|
3507 | (!$_SWIFT_BaseObject instanceof SWIFT_User || !$_SWIFT_BaseObject->GetIsClassLoaded())) {
|
3508 | return false;
|
3509 | }
|
3510 |
|
3511 | // Staff Check
|
3512 | if ($_SWIFT_BaseObject instanceof SWIFT_Staff)
|
3513 | {
|
3514 | $_assignedDepartmentIDList = $_SWIFT_BaseObject->GetAssignedDepartments(APP_TICKETS);
|
3515 |
|
3516 | if (in_array($this->GetProperty('departmentid'), $_assignedDepartmentIDList)) {
|
3517 | return true;
|
3518 | } else if ($this->GetProperty('departmentid') == '0'
|
3519 | && ($this->GetProperty('trasholddepartmentid') == '0' || in_array($this->GetProperty('trasholddepartmentid'), $_assignedDepartmentIDList))) {
|
3520 | return true;
|
3521 | }
|
3522 |
|
3523 | // User Check
|
3524 | } else if ($_SWIFT_BaseObject instanceof SWIFT_User) {
|
3525 | $_userEmailList = array();
|
3526 | $_userID = $_SWIFT_BaseObject->GetUserID();
|
3527 | $_userEmailList = array_merge($_userEmailList, $_SWIFT_BaseObject->GetEmailList());
|
3528 |
|
3529 | $_userIDList = array($_SWIFT_BaseObject->GetUserID());
|
3530 |
|
3531 | // Does this user have a shared organization or he is a manager in an organization?
|
3532 | $_SWIFT_UserOrganizationObject = $_SWIFT_BaseObject->GetOrganization();
|
3533 |
|
3534 | if (($_SWIFT_BaseObject->GetProperty('userrole') == SWIFT_User::ROLE_MANAGER && $_SWIFT_UserOrganizationObject instanceof SWIFT_UserOrganization && $_SWIFT_UserOrganizationObject->GetIsClassLoaded()) ||
|
3535 | ($_SWIFT_UserOrganizationObject instanceof SWIFT_UserOrganization && $_SWIFT_UserOrganizationObject->GetIsClassLoaded() && $_SWIFT_UserOrganizationObject->GetProperty('organizationtype') == SWIFT_UserOrganization::TYPE_SHARED))
|
3536 | {
|
3537 | $_userIDList_Organization = array();
|
3538 | $this->Database->Query("SELECT userid FROM " . TABLE_PREFIX . "users
|
3539 | WHERE userorganizationid = '" . intval($_SWIFT_UserOrganizationObject->GetUserOrganizationID()) . "'");
|
3540 | while ($this->Database->NextRecord())
|
3541 | {
|
3542 | $_userIDList_Organization[] = $this->Database->Record['userid'];
|
3543 |
|
3544 | $_userIDList[] = $this->Database->Record['userid'];
|
3545 | }
|
3546 |
|
3547 | $_userEmailList = array_merge($_userEmailList, SWIFT_UserEmail::RetrieveListOnUserIDList($_userIDList_Organization));
|
3548 | }
|
3549 |
|
3550 | if ($this->GetProperty('userid') != '0' && in_array($this->GetProperty('userid'), $_userIDList))
|
3551 | {
|
3552 | return true;
|
3553 | } else if (in_array(mb_strtolower($this->GetProperty('email')), $_userEmailList)) {
|
3554 | return true;
|
3555 | } else if ($this->GetProperty('creator') == SWIFT_Ticket::CREATOR_STAFF && in_array(mb_strtolower($this->GetProperty('replyto')), $_userEmailList)) {
|
3556 | return true;
|
3557 | }
|
3558 | }
|
3559 |
|
3560 | return false;
|
3561 | }
|
3562 |
|
3563 | /**
|
3564 | * Return the Ticket ID to be displayed according to relevant setting
|
3565 | *
|
3566 | * @author Varun Shoor
|
3567 | * @return mixed Ticket Mask ID or Ticket ID
|
3568 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3569 | */
|
3570 | public function GetTicketDisplayID() {
|
3571 | if (!$this->GetIsClassLoaded()) {
|
3572 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3573 |
|
3574 | return false;
|
3575 | }
|
3576 |
|
3577 | return IIF($this->Settings->Get('t_eticketid') == 'seq', $this->GetProperty('ticketid'), $this->GetProperty('ticketmaskid'));
|
3578 | }
|
3579 |
|
3580 | /**
|
3581 | * Recalculate the Ticket Link Property
|
3582 | *
|
3583 | * @author Varun Shoor
|
3584 | * @param array $_ticketIDList The Ticket ID List
|
3585 | * @return bool "true" on Success, "false" otherwise
|
3586 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
3587 | */
|
3588 | static public function RecalculateTicketLinkProperty($_ticketIDList) {
|
3589 | $_SWIFT = SWIFT::GetInstance();
|
3590 |
|
3591 | if (!_is_array($_ticketIDList)) {
|
3592 | return false;
|
3593 | }
|
3594 |
|
3595 | $_ticketContainer = $_ticketLinkStatus = array();
|
3596 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
3597 | while ($_SWIFT->Database->NextRecord()) {
|
3598 | $_ticketContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
3599 | }
|
3600 |
|
3601 | // Calculate the link chains
|
3602 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "ticketlinkchains WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
3603 | while ($_SWIFT->Database->NextRecord()) {
|
3604 | $_ticketLinkStatus[] = $_SWIFT->Database->Record['ticketid'];
|
3605 | }
|
3606 |
|
3607 | foreach ($_ticketContainer as $_ticketID => $_SWIFT_TicketObject) {
|
3608 | if (in_array($_ticketID, $_ticketLinkStatus)) {
|
3609 | $_SWIFT_TicketObject->MarkAsLinked();
|
3610 | } else {
|
3611 | $_SWIFT_TicketObject->MarkAsUnlinked();
|
3612 | }
|
3613 | }
|
3614 |
|
3615 | return true;
|
3616 | }
|
3617 |
|
3618 | /**
|
3619 | * Get the ticket post count
|
3620 | *
|
3621 | * @author Varun Shoor
|
3622 | * @return int The Ticket Post Count
|
3623 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3624 | */
|
3625 | public function GetTicketPostCount() {
|
3626 | if (!$this->GetIsClassLoaded()) {
|
3627 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3628 |
|
3629 | return false;
|
3630 | }
|
3631 |
|
3632 | $_totalCount = 0;
|
3633 |
|
3634 | $_totalItemContainer = $this->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "ticketposts WHERE ticketid = '" .
|
3635 | intval($this->GetTicketID()) . "'");
|
3636 | if (isset($_totalItemContainer['totalitems'])) {
|
3637 | $_totalCount = intval($_totalItemContainer['totalitems']);
|
3638 | }
|
3639 |
|
3640 | return $_totalCount;
|
3641 | }
|
3642 |
|
3643 | /**
|
3644 | * Retrieve the ticket posts associated with this ticket
|
3645 | *
|
3646 | * @author Varun Shoor
|
3647 | * @param int $_offset (OPTIONAL) The Starting Offset
|
3648 | * @param int $_limit (OPTIONAL) The Number of Results to Return
|
3649 | * @param string $_sortOrder (OPTIONAL) ASC/DESC The Sort Order
|
3650 | * @param constant $_creator (OPTIONAL) Filter by the Creator
|
3651 | * @return array The Ticket Post Object Container
|
3652 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
3653 | */
|
3654 | public function GetTicketPosts($_offset = 0, $_limit = false, $_sortOrder = 'ASC', $_creator = false) {
|
3655 | $_SWIFT = SWIFT::GetInstance();
|
3656 |
|
3657 | if (!$this->GetIsClassLoaded()) {
|
3658 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3659 |
|
3660 | return false;
|
3661 | }
|
3662 |
|
3663 | $_ticketPostObjectContainer = array();
|
3664 |
|
3665 | $_sqlQuery = "SELECT * FROM " . TABLE_PREFIX . "ticketposts WHERE ticketid = '" . intval($this->GetTicketID()) . "' ORDER BY ticketpostid " .
|
3666 | $_sortOrder;
|
3667 | if (!empty($_limit)) {
|
3668 | $this->Database->QueryLimit($_sqlQuery, $_limit, $_offset);
|
3669 | } else {
|
3670 | $this->Database->Query($_sqlQuery);
|
3671 | }
|
3672 |
|
3673 | while ($this->Database->NextRecord()) {
|
3674 | if (!empty($_creator) && $_creator != $this->Database->Record['creator']) {
|
3675 | continue;
|
3676 | }
|
3677 |
|
3678 | $_ticketPostObjectContainer[$this->Database->Record['ticketpostid']] = new SWIFT_TicketPost(new SWIFT_DataStore($this->Database->Record));
|
3679 | }
|
3680 |
|
3681 | return $_ticketPostObjectContainer;
|
3682 | }
|
3683 |
|
3684 | /**
|
3685 | * Train the given tickets
|
3686 | *
|
3687 | * @author Varun Shoor
|
3688 | * @param array $_ticketIDList The Ticket ID List
|
3689 | * @return bool "true" on Success, "false" otherwise
|
3690 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
3691 | */
|
3692 | static public function TrainBayesList($_ticketIDList, $_bayesCategoryID) {
|
3693 | $_SWIFT = SWIFT::GetInstance();
|
3694 |
|
3695 | if (!_is_array($_ticketIDList)) {
|
3696 | return false;
|
3697 | } else if (empty($_bayesCategoryID)) {
|
3698 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3699 | }
|
3700 |
|
3701 | $_bayesianCategoryCache = $_SWIFT->Cache->Get('bayesiancategorycache');
|
3702 |
|
3703 | $_SWIFT_BayesianObject = new SWIFT_Bayesian();
|
3704 | if (!$_SWIFT_BayesianObject instanceof SWIFT_Bayesian || !$_SWIFT_BayesianObject->GetIsClassLoaded()) {
|
3705 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3706 | }
|
3707 |
|
3708 | if (!isset($_bayesianCategoryCache[$_bayesCategoryID]))
|
3709 | {
|
3710 | throw new SWIFT_Ticket_Exception('Bayesian Category does not exist');
|
3711 | }
|
3712 |
|
3713 | $_ticketObjectContainer = array();
|
3714 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
3715 | while ($_SWIFT->Database->NextRecord()) {
|
3716 | $_ticketObjectContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
3717 | }
|
3718 |
|
3719 | foreach ($_ticketObjectContainer as $_ticketID => $_SWIFT_TicketObject) {
|
3720 | $_ticketPostContainer = $_SWIFT_TicketObject->GetTicketPosts(0, false, 'ASC', SWIFT_Ticket::CREATOR_CLIENT);
|
3721 | if (!_is_array($_ticketPostContainer)) {
|
3722 | continue;
|
3723 | }
|
3724 |
|
3725 | $_finalTicketPostText = $_SWIFT_TicketObject->GetProperty('subject');
|
3726 | foreach ($_ticketPostContainer as $_ticketPostID => $_SWIFT_TicketPostObject) {
|
3727 | $_finalTicketPostText .= $_SWIFT_TicketPostObject->GetProperty('contents') . SWIFT_CRLF;
|
3728 | }
|
3729 |
|
3730 | $_SWIFT_BayesianObject->Train($_ticketID, $_bayesCategoryID, $_finalTicketPostText);
|
3731 | }
|
3732 |
|
3733 | return true;
|
3734 | }
|
3735 |
|
3736 | /**
|
3737 | * Train the Bayesian
|
3738 | *
|
3739 | * @author Varun Shoor
|
3740 | * @param int $_bayesCategoryID The Bayesian Category ID
|
3741 | * @return bool "true" on Success, "false" otherwise
|
3742 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
3743 | */
|
3744 | public function TrainBayes($_bayesCategoryID)
|
3745 | {
|
3746 | if (!$this->GetIsClassLoaded())
|
3747 | {
|
3748 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3749 |
|
3750 | return false;
|
3751 | } else if (empty($_bayesCategoryID)) {
|
3752 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3753 | }
|
3754 |
|
3755 | self::TrainBayesList(array($this->GetTicketID()), $_bayesCategoryID);
|
3756 |
|
3757 | return true;
|
3758 | }
|
3759 |
|
3760 | /**
|
3761 | * Mark the given ticket ids as spam
|
3762 | *
|
3763 | * @author Varun Shoor
|
3764 | * @param array $_ticketIDList The Ticket ID List
|
3765 | * @return bool "true" on Success, "false" otherwise
|
3766 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
3767 | */
|
3768 | static public function MarkAsSpamList($_ticketIDList) {
|
3769 | $_SWIFT = SWIFT::GetInstance();
|
3770 |
|
3771 | if (!_is_array($_ticketIDList)) {
|
3772 | return false;
|
3773 | }
|
3774 |
|
3775 | $_bayesianCategoryCache = $_SWIFT->Cache->Get('bayesiancategorycache');
|
3776 |
|
3777 | $_SWIFT_BayesianObject = new SWIFT_Bayesian();
|
3778 | if (!$_SWIFT_BayesianObject instanceof SWIFT_Bayesian || !$_SWIFT_BayesianObject->GetIsClassLoaded()) {
|
3779 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3780 | }
|
3781 |
|
3782 | $_bayesCategoryID = false;
|
3783 | foreach ($_bayesianCategoryCache as $_bayesianCategoryID => $_bayesianCategoryContainer) {
|
3784 | if ($_bayesianCategoryContainer['categorytype'] == SWIFT_BayesianCategory::CATEGORY_SPAM) {
|
3785 | $_bayesCategoryID = $_bayesianCategoryContainer['bayescategoryid'];
|
3786 |
|
3787 | break;
|
3788 | }
|
3789 | }
|
3790 |
|
3791 | if (!$_bayesCategoryID) {
|
3792 | throw new SWIFT_Ticket_Exception('Spam Bayesian Category not found');
|
3793 | }
|
3794 |
|
3795 | $_ticketObjectContainer = array();
|
3796 |
|
3797 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
3798 | while ($_SWIFT->Database->NextRecord()) {
|
3799 | $_ticketObjectContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
3800 | }
|
3801 |
|
3802 | foreach ($_ticketObjectContainer as $_ticketID => $_SWIFT_TicketObject) {
|
3803 | $_ticketPostContainer = $_SWIFT_TicketObject->GetTicketPosts(0, false, 'ASC', SWIFT_Ticket::CREATOR_CLIENT);
|
3804 | if (!_is_array($_ticketPostContainer)) {
|
3805 | continue;
|
3806 | }
|
3807 |
|
3808 | $_finalTicketPostText = $_SWIFT_TicketObject->GetProperty('subject');
|
3809 | foreach ($_ticketPostContainer as $_ticketPostID => $_SWIFT_TicketPostObject) {
|
3810 | $_finalTicketPostText .= $_SWIFT_TicketPostObject->GetProperty('contents') . SWIFT_CRLF;
|
3811 | }
|
3812 |
|
3813 | $_SWIFT_BayesianObject->Train($_ticketID, $_bayesCategoryID, $_finalTicketPostText);
|
3814 | }
|
3815 |
|
3816 | if ($_SWIFT->Settings->Get('t_spammovetotrash') == '1') {
|
3817 | self::TrashList($_ticketIDList);
|
3818 | }
|
3819 |
|
3820 | if ($_SWIFT->Settings->Get('t_spamban') == '1') {
|
3821 | self::BanList($_ticketIDList, $_SWIFT->Staff->GetStaffID());
|
3822 | }
|
3823 |
|
3824 | return true;
|
3825 | }
|
3826 |
|
3827 | /**
|
3828 | * Watch a ticket list
|
3829 | *
|
3830 | * @author Varun Shoor
|
3831 | * @param array $_ticketIDList The Ticket ID List
|
3832 | * @return bool "true" on Success, "false" otherwise
|
3833 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
3834 | */
|
3835 | static public function Watch($_ticketIDList, SWIFT_Staff $_SWIFT_StaffObject) {
|
3836 | $_SWIFT = SWIFT::GetInstance();
|
3837 |
|
3838 | if (!$_SWIFT_StaffObject instanceof SWIFT_Staff || !$_SWIFT_StaffObject->GetIsClassLoaded()) {
|
3839 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3840 | } else if (!_is_array($_ticketIDList)) {
|
3841 | return false;
|
3842 | }
|
3843 |
|
3844 | $_ticketObjectContainer = array();
|
3845 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
3846 | while ($_SWIFT->Database->NextRecord()) {
|
3847 | $_ticketObjectContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
3848 | }
|
3849 |
|
3850 | if (!count($_ticketObjectContainer)) {
|
3851 | return false;
|
3852 | }
|
3853 |
|
3854 | foreach ($_ticketObjectContainer as $_ticketID => $_SWIFT_TicketObject) {
|
3855 | // Create Audit Log
|
3856 | SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_WATCH,
|
3857 | sprintf($_SWIFT->Language->Get('al_watch'), $_SWIFT_TicketObject->GetTicketDisplayID(), $_SWIFT_StaffObject->GetProperty('fullname')),
|
3858 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
3859 |
|
3860 | SWIFT_TicketWatcher::Create($_SWIFT_TicketObject, $_SWIFT_StaffObject);
|
3861 | }
|
3862 |
|
3863 | return true;
|
3864 | }
|
3865 |
|
3866 | /**
|
3867 | * Unwatch a ticket list
|
3868 | *
|
3869 | * @author Varun Shoor
|
3870 | * @param array $_ticketIDList The Ticket ID List
|
3871 | * @return bool "true" on Success, "false" otherwise
|
3872 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
3873 | */
|
3874 | static public function UnWatch($_ticketIDList, SWIFT_Staff $_SWIFT_StaffObject) {
|
3875 | $_SWIFT = SWIFT::GetInstance();
|
3876 |
|
3877 | if (!$_SWIFT_StaffObject instanceof SWIFT_Staff || !$_SWIFT_StaffObject->GetIsClassLoaded()) {
|
3878 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3879 | } else if (!_is_array($_ticketIDList)) {
|
3880 | return false;
|
3881 | }
|
3882 |
|
3883 | SWIFT_TicketWatcher::DeleteOnTicket($_ticketIDList, array($_SWIFT_StaffObject->GetStaffID()));
|
3884 |
|
3885 | return true;
|
3886 | }
|
3887 |
|
3888 | /**
|
3889 | * Add the object to the active workflow queue
|
3890 | *
|
3891 | * @author Varun Shoor
|
3892 | * @param SWIFT_Ticket $_SWIFT_TicketObject The SWIFT_Ticket Object Pointer
|
3893 | * @return bool "true" on Success, "false" otherwise
|
3894 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
3895 | */
|
3896 | static public function AddToWorkflowQueue(SWIFT_Ticket $_SWIFT_TicketObject) {
|
3897 | $_SWIFT = SWIFT::GetInstance();
|
3898 |
|
3899 | if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
|
3900 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3901 | } else if (isset(self::$_workflowQueue[$_SWIFT_TicketObject->GetTicketID()])) {
|
3902 | return true;
|
3903 | }
|
3904 |
|
3905 | self::$_workflowQueue[$_SWIFT_TicketObject->GetTicketID()] = $_SWIFT_TicketObject;
|
3906 |
|
3907 | if (self::$_isWorkflowQueueActive) {
|
3908 | return true;
|
3909 | }
|
3910 |
|
3911 | self::$_isWorkflowQueueActive = true;
|
3912 |
|
3913 | SWIFT::Shutdown('SWIFT_Ticket', 'ProcessWorkflowQueue', 9, false);
|
3914 |
|
3915 | return true;
|
3916 | }
|
3917 |
|
3918 | /**
|
3919 | * Process the workflow queue for each active ticket
|
3920 | *
|
3921 | * @author Varun Shoor
|
3922 | * @return bool "true" on Success, "false" otherwise
|
3923 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
3924 | */
|
3925 | static public function ProcessWorkflowQueue() {
|
3926 | $_SWIFT = SWIFT::GetInstance();
|
3927 |
|
3928 | if (!count(self::$_workflowQueue)) {
|
3929 | return true;
|
3930 | }
|
3931 |
|
3932 | $_ticketWorkflowIDContainer = $_ticketObjectContainer = $_ticketIDList = array();
|
3933 |
|
3934 | foreach (self::$_workflowQueue as $_ticketID => $_SWIFT_TicketObject) {
|
3935 | $_ticketWorkflowIDList = SWIFT_TicketWorkflow::ExecuteAll($_SWIFT_TicketObject);
|
3936 | $_ticketWorkflowIDContainer[$_SWIFT_TicketObject->GetTicketID()] = $_ticketWorkflowIDList;
|
3937 | $_ticketObjectContainer[$_SWIFT_TicketObject->GetTicketID()] = $_SWIFT_TicketObject;
|
3938 |
|
3939 | $_ticketIDList[] = $_SWIFT_TicketObject->GetTicketID();
|
3940 | }
|
3941 |
|
3942 | if (!count($_ticketWorkflowIDContainer)) {
|
3943 | self::$_workflowQueue = array();
|
3944 | self::$_isWorkflowQueueActive = false;
|
3945 |
|
3946 | return false;
|
3947 | }
|
3948 |
|
3949 | SWIFT_TicketLinkedTable::DeleteOnTicket($_ticketIDList, SWIFT_TicketLinkedTable::LINKTYPE_WORKFLOW);
|
3950 |
|
3951 | foreach ($_ticketWorkflowIDContainer as $_ticketID => $_ticketWorkflowIDList) {
|
3952 | if (!isset($_ticketObjectContainer[$_ticketID])) {
|
3953 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
3954 | }
|
3955 |
|
3956 | $_SWIFT_TicketObject = $_ticketObjectContainer[$_ticketID];
|
3957 | // Add the workflows to the ticket
|
3958 | if (_is_array($_ticketWorkflowIDList)) {
|
3959 | $_ticketLinkContainer = array();
|
3960 | $_ticketLinkContainer[SWIFT_TicketLinkedTable::LINKTYPE_WORKFLOW] = $_ticketWorkflowIDList;
|
3961 |
|
3962 | SWIFT_TicketLinkedTable::CreateIfNotExists($_SWIFT_TicketObject, $_ticketLinkContainer);
|
3963 | }
|
3964 | }
|
3965 |
|
3966 | self::$_workflowQueue = array();
|
3967 | self::$_isWorkflowQueueActive = false;
|
3968 |
|
3969 | return true;
|
3970 | }
|
3971 |
|
3972 | /**
|
3973 | * Processes the POST attachment field (ticketattachments) and adds the attachments to the ticket
|
3974 | *
|
3975 | * @author Varun Shoor
|
3976 | * @param SWIFT_TicketPost $_SWIFT_TicketPostObject (OPTIONAL) The Ticket Post Object
|
3977 | * @param string $_fieldName (OPTIONAL) The Custom Field Name
|
3978 | * @return bool "true" on Success, "false" otherwise
|
3979 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded or If Invalid Data is Provided
|
3980 | */
|
3981 | public function ProcessPostAttachments(SWIFT_TicketPost $_SWIFT_TicketPostObject = null, $_fieldName = '') {
|
3982 | if (!$this->GetIsClassLoaded()) {
|
3983 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
3984 |
|
3985 | return false;
|
3986 | }
|
3987 |
|
3988 | $_finalFieldName = 'ticketattachments';
|
3989 | if (!empty($_fieldName))
|
3990 | {
|
3991 | $_finalFieldName = $_fieldName;
|
3992 | }
|
3993 |
|
3994 | $_listFieldName = $_finalFieldName . 'list';
|
3995 |
|
3996 | // Link with first post if none specified
|
3997 | if ($_SWIFT_TicketPostObject == null) {
|
3998 | $_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($this->GetProperty('firstpostid')));
|
3999 | }
|
4000 |
|
4001 | if (!$_SWIFT_TicketPostObject instanceof SWIFT_TicketPost || !$_SWIFT_TicketPostObject->GetIsClassLoaded()) {
|
4002 | throw new SWIFT_Ticket_Exception(SWIFT_INVALIDDATA);
|
4003 | }
|
4004 |
|
4005 | $_attachmentCount = 0;
|
4006 |
|
4007 | if (isset($_POST[$_listFieldName]) && _is_array($_POST[$_listFieldName]))
|
4008 | {
|
4009 | foreach ($_POST[$_listFieldName] as $_attachmentID)
|
4010 | {
|
4011 | $_SWIFT_AttachmentObject = new SWIFT_Attachment($_attachmentID);
|
4012 |
|
4013 | SWIFT_Attachment::CloneOnTicket($this, $_SWIFT_TicketPostObject, $_SWIFT_AttachmentObject);
|
4014 |
|
4015 | $this->AddToNotificationAttachments($_SWIFT_AttachmentObject->GetProperty('filename'), $_SWIFT_AttachmentObject->GetProperty('filetype'),
|
4016 | $_SWIFT_AttachmentObject->Get());
|
4017 |
|
4018 | $_attachmentCount++;
|
4019 |
|
4020 | }
|
4021 |
|
4022 | if ($_attachmentCount > 0) {
|
4023 | $this->UpdatePool('hasattachments', '1');
|
4024 | }
|
4025 |
|
4026 | unset($_POST[$_listFieldName]);
|
4027 | }
|
4028 |
|
4029 | if (!isset($_FILES[$_finalFieldName]) || !_is_array($_FILES[$_finalFieldName]) || !_is_array($_FILES[$_finalFieldName]['name'])) {
|
4030 | return false;
|
4031 | }
|
4032 |
|
4033 | // Create the attachments
|
4034 | foreach ($_FILES[$_finalFieldName]['name'] as $_fileIndex => $_fileName) {
|
4035 | if (empty($_fileName) || empty($_FILES[$_finalFieldName]['type'][$_fileIndex]) || empty($_FILES[$_finalFieldName]['size'][$_fileIndex]) ||
|
4036 | !is_uploaded_file($_FILES[$_finalFieldName]['tmp_name'][$_fileIndex]))
|
4037 | {
|
4038 | continue;
|
4039 | }
|
4040 |
|
4041 | $_SWIFT_AttachmentStoreObject = new SWIFT_AttachmentStoreFile($_FILES[$_finalFieldName]['tmp_name'][$_fileIndex],
|
4042 | $_FILES[$_finalFieldName]['type'][$_fileIndex], $_fileName);
|
4043 |
|
4044 | $_SWIFT_AttachmentObject = SWIFT_Attachment::CreateOnTicket($this, $_SWIFT_TicketPostObject, $_SWIFT_AttachmentStoreObject);
|
4045 |
|
4046 | $this->AddToNotificationAttachments($_fileName, $_FILES[$_finalFieldName]['type'][$_fileIndex], file_get_contents($_FILES[$_finalFieldName]['tmp_name'][$_fileIndex]));
|
4047 |
|
4048 | $_attachmentCount++;
|
4049 | }
|
4050 |
|
4051 | if ($_attachmentCount > 0) {
|
4052 | $this->UpdatePool('hasattachments', '1');
|
4053 | }
|
4054 |
|
4055 | return true;
|
4056 | }
|
4057 |
|
4058 | /**
|
4059 | * Checks for valid input for attachments
|
4060 | *
|
4061 | * @author Varun Shoor
|
4062 | * @param string $_inputType The Input Type (staff/supportcenter/parser)
|
4063 | * @return array (result - bool, invalid file list)
|
4064 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
4065 | */
|
4066 | static public function CheckForValidAttachments($_inputType) {
|
4067 | $_SWIFT = SWIFT::GetInstance();
|
4068 |
|
4069 | // Always accept staff input
|
4070 | if ($_inputType == 'staff') {
|
4071 | return true;
|
4072 | }
|
4073 |
|
4074 | // If its coming from support center and we cant find anything then return true
|
4075 | if ($_inputType == 'supportcenter' && (!isset($_FILES['ticketattachments']) || !_is_array($_FILES['ticketattachments']) || !_is_array($_FILES['ticketattachments']['name']))) {
|
4076 | return true;
|
4077 | }
|
4078 |
|
4079 | $_fileTypeCache = $_SWIFT->Cache->Get('filetypecache');
|
4080 | $_fileTypeCacheMap = array();
|
4081 |
|
4082 | // Do we need to sanitize the data?
|
4083 | if ($_SWIFT->Settings->Get('tickets_resattachments') == '0') {
|
4084 | return true;
|
4085 | }
|
4086 |
|
4087 | // Sanitize the data.. do we need to sanitize the data?
|
4088 | foreach ($_fileTypeCache as $_ticketFileTypeID => $_ticketFileTypeContainer) {
|
4089 | $_fileTypeCacheMap[mb_strtolower($_ticketFileTypeContainer['extension'])] = $_ticketFileTypeContainer;
|
4090 | }
|
4091 |
|
4092 | $_resultArray = array();
|
4093 | $_result = true;
|
4094 |
|
4095 | // Check the attachments
|
4096 | foreach ($_FILES['ticketattachments']['name'] as $_fileIndex => $_fileName) {
|
4097 | $_fileExtension = mb_strtolower(substr($_fileName, (strrpos($_fileName, '.')+1)));
|
4098 |
|
4099 | // Extension isnt added in the list? || Check whether we can accept it from support center? || Invalid File Size?
|
4100 | if (!isset($_fileTypeCacheMap[$_fileExtension]) ||
|
4101 | ($_inputType == 'supportcenter' && $_fileTypeCacheMap[$_fileExtension]['acceptsupportcenter'] == '0') ||
|
4102 | ($_inputType == 'parser' && $_fileTypeCacheMap[$_fileExtension]['acceptmailparser'] == '0') ||
|
4103 | ($_fileTypeCacheMap[$_fileExtension]['maxsize'] != '0' && ($_FILES['ticketattachments']['size'][$_fileIndex]/1024) >= $_fileTypeCacheMap[$_fileExtension]['maxsize']))
|
4104 | {
|
4105 | $_result = false;
|
4106 | $_resultArray[] = $_fileName;
|
4107 | }
|
4108 | }
|
4109 |
|
4110 | return array($_result, $_resultArray);
|
4111 | }
|
4112 |
|
4113 | /**
|
4114 | * Retrieve the ticket attachment container
|
4115 | *
|
4116 | * @author Varun Shoor
|
4117 | * @return array $_ticketAttachmentContainer
|
4118 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4119 | */
|
4120 | public function GetAttachmentContainer() {
|
4121 | if (!$this->GetIsClassLoaded()) {
|
4122 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4123 |
|
4124 | return false;
|
4125 | }
|
4126 |
|
4127 | $_ticketAttachmentContainer = array();
|
4128 |
|
4129 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "attachments WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
4130 | while ($this->Database->NextRecord()) {
|
4131 | $_ticketAttachmentContainer[$this->Database->Record['linktypeid']][$this->Database->Record['attachmentid']] = $this->Database->Record;
|
4132 | }
|
4133 |
|
4134 | return $_ticketAttachmentContainer;
|
4135 | }
|
4136 |
|
4137 | /**
|
4138 | * Retrieve the history count for this user based on his userid & email address
|
4139 | *
|
4140 | * @author Varun Shoor
|
4141 | * @return int The History Count
|
4142 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4143 | */
|
4144 | public function GetHistoryCount() {
|
4145 | if (!$this->GetIsClassLoaded()) {
|
4146 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4147 |
|
4148 | return false;
|
4149 | }
|
4150 |
|
4151 | $_userID = '-1';
|
4152 | if ($this->GetProperty('userid') != '0')
|
4153 | {
|
4154 | $_userID = intval($this->GetProperty('userid'));
|
4155 | }
|
4156 |
|
4157 | $_countContainer = $this->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "tickets WHERE userid = '" .
|
4158 | intval($_userID) . "' OR email = '" . $this->Database->Escape($this->GetProperty('email')) . "'");
|
4159 |
|
4160 | if (isset($_countContainer['totalitems']) && intval($_countContainer['totalitems']) > 0) {
|
4161 | return $_countContainer['totalitems'] - 1;
|
4162 | }
|
4163 |
|
4164 | return 0;
|
4165 | }
|
4166 |
|
4167 | /**
|
4168 | * Retrieve the history for this ticket
|
4169 | *
|
4170 | * @author Varun Shoor
|
4171 | * @return array The History Container
|
4172 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4173 | */
|
4174 | public function RetrieveHistory() {
|
4175 | if (!$this->GetIsClassLoaded()) {
|
4176 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4177 |
|
4178 | return false;
|
4179 | }
|
4180 |
|
4181 | $_historyContainer = array();
|
4182 |
|
4183 | $_sqlExtend = '';
|
4184 | if ($this->GetProperty('userid') != '0')
|
4185 | {
|
4186 | $_sqlExtend = " OR userid = '" . intval($this->GetProperty('userid')) . "'";
|
4187 | }
|
4188 |
|
4189 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE email = '" . $this->Database->Escape($this->GetProperty('email')) . "'" . $_sqlExtend . " ORDER BY dateline DESC");
|
4190 | while ($this->Database->NextRecord()) {
|
4191 | $_historyContainer[$this->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($this->Database->Record));
|
4192 | }
|
4193 |
|
4194 | return $_historyContainer;
|
4195 | }
|
4196 |
|
4197 | /**
|
4198 | * Retrieve the relevant user object
|
4199 | *
|
4200 | * @author Varun Shoor
|
4201 | * @return mixed "SWIFT_User" (OBJECT) on Success, "false" otherwise
|
4202 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4203 | */
|
4204 | public function GetUserObject() {
|
4205 | if (!$this->GetIsClassLoaded()) {
|
4206 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4207 |
|
4208 | return false;
|
4209 | }
|
4210 |
|
4211 | // Have we already cached the user object?
|
4212 | if ($this->_isUserObjectCached == true) {
|
4213 | return $this->_UserObject;
|
4214 | }
|
4215 |
|
4216 | $_SWIFT_UserObject = false;
|
4217 | if ($this->GetProperty('userid') != '0') {
|
4218 | try {
|
4219 | $_SWIFT_UserObject = new SWIFT_User(new SWIFT_DataID($this->GetProperty('userid')));
|
4220 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
4221 |
|
4222 | return false;
|
4223 | }
|
4224 | }
|
4225 |
|
4226 | $this->_UserObject = $_SWIFT_UserObject;
|
4227 | $this->_isUserObjectCached = true;
|
4228 |
|
4229 | return $_SWIFT_UserObject;
|
4230 | }
|
4231 |
|
4232 | /**
|
4233 | * Retrieve the relevant user group object
|
4234 | *
|
4235 | * @author Varun Shoor
|
4236 | * @return mixed "SWIFT_UserGroup" (OBJECT) on Success, "false" otherwise
|
4237 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4238 | */
|
4239 | public function GetUserGroupObject() {
|
4240 | if (!$this->GetIsClassLoaded()) {
|
4241 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4242 |
|
4243 | return false;
|
4244 | }
|
4245 |
|
4246 | // Have we already cached the user object?
|
4247 | if ($this->_isUserGroupObjectCached == true) {
|
4248 | return $this->_UserGroupObject;
|
4249 | }
|
4250 |
|
4251 | $_SWIFT_UserObject = $this->GetUserObject();
|
4252 | $_SWIFT_UserGroupObject = false;
|
4253 |
|
4254 | if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded())
|
4255 | {
|
4256 | try {
|
4257 | $_SWIFT_UserGroupObject = new SWIFT_UserGroup($_SWIFT_UserObject->GetProperty('usergroupid'));
|
4258 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
4259 |
|
4260 | return false;
|
4261 | }
|
4262 | }
|
4263 |
|
4264 | $this->_UserGroupObject = $_SWIFT_UserGroupObject;
|
4265 | $this->_isUserGroupObjectCached = true;
|
4266 |
|
4267 | return $_SWIFT_UserGroupObject;
|
4268 | }
|
4269 |
|
4270 | /**
|
4271 | * Retrieve the user organization object associated with this ticket
|
4272 | *
|
4273 | * @author Varun Shoor
|
4274 | * @return mixed "SWIFT_UserOrganization" (OBJECT) on Success, "false" otherwise
|
4275 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4276 | */
|
4277 | public function GetUserOrganizationObject() {
|
4278 | if (!$this->GetIsClassLoaded()) {
|
4279 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4280 |
|
4281 | return false;
|
4282 | }
|
4283 |
|
4284 | // Have we already cached the user organization object?
|
4285 | if ($this->_isUserOrganizationObjectCached == true) {
|
4286 | return $this->_UserOrganizationObject;
|
4287 | }
|
4288 |
|
4289 | $_SWIFT_UserOrganizationObject = false;
|
4290 |
|
4291 | $_SWIFT_UserObject = $this->GetUserobject();
|
4292 |
|
4293 | if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded() &&
|
4294 | $_SWIFT_UserObject->GetProperty('userorganizationid') != '0')
|
4295 | {
|
4296 | try
|
4297 | {
|
4298 | $_SWIFT_UserOrganizationObject = new SWIFT_UserOrganization($_SWIFT_UserObject->GetProperty('userorganizationid'));
|
4299 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
4300 |
|
4301 | }
|
4302 | }
|
4303 |
|
4304 | $this->_UserOrganizationObject = $_SWIFT_UserOrganizationObject;
|
4305 | $this->_isUserOrganizationObjectCached = true;
|
4306 |
|
4307 | return $_SWIFT_UserOrganizationObject;
|
4308 | }
|
4309 |
|
4310 | /**
|
4311 | * Get the relevant mail subject based on mail type
|
4312 | *
|
4313 | * @author Varun Shoor
|
4314 | * @param constant $_mailType The Mail Type
|
4315 | * @param string $_customSubject (OPTIONAL) The Custom Subject
|
4316 | * @return mixed "Mail Subject" on Success, "false" otherwise
|
4317 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4318 | */
|
4319 | public function GetMailSubject($_mailType, $_customSubject = '') {
|
4320 | $_SWIFT = SWIFT::GetInstance();
|
4321 |
|
4322 | if (!$this->GetIsClassLoaded()) {
|
4323 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4324 |
|
4325 | return false;
|
4326 | }
|
4327 |
|
4328 | $_emailQueueCache = $_SWIFT->Cache->Get('queuecache');
|
4329 | $_emailQueueID = $this->GetProperty('emailqueueid');
|
4330 | $_templateGroupID = $this->GetProperty('tgroupid');
|
4331 |
|
4332 | /*
|
4333 | * BUG FIX - Varun Shoor
|
4334 | *
|
4335 | * SWIFT-1327 From name and From email address improvements in autoresponder email, if visitor sends an offline message and help desk create the ticket
|
4336 | * SWIFT-1651 From Email Address (in autoresponder email) should set according to the template group under email queue, if ticket is created from client support center in case of multi-domain installation
|
4337 | *
|
4338 | * Comments: None
|
4339 | */
|
4340 |
|
4341 | // First try to load up the email queue based on template group & department match
|
4342 | if (empty($_emailQueueID) && isset($_emailQueueCache['list']) && _is_array($_emailQueueCache['list']))
|
4343 | {
|
4344 | foreach ($_emailQueueCache['list'] as $_emailQueueContainer)
|
4345 | {
|
4346 | if ($_emailQueueContainer['departmentid'] == $this->GetProperty('departmentid') && $_emailQueueContainer['tgroupid'] == $_templateGroupID)
|
4347 | {
|
4348 | $_emailQueueID = $_emailQueueContainer['emailqueueid'];
|
4349 |
|
4350 | break;
|
4351 | }
|
4352 | }
|
4353 | }
|
4354 |
|
4355 | // No Queue Prefix set, itterate through queues looking for one for ONLY this department
|
4356 | if (empty($_emailQueueID) && isset($_emailQueueCache['list']) && _is_array($_emailQueueCache['list']))
|
4357 | {
|
4358 | foreach ($_emailQueueCache['list'] as $_emailQueueContainer)
|
4359 | {
|
4360 | if ($_emailQueueContainer['departmentid'] == $this->GetProperty('departmentid'))
|
4361 | {
|
4362 | $_emailQueueID = $_emailQueueContainer['emailqueueid'];
|
4363 |
|
4364 | break;
|
4365 | }
|
4366 | }
|
4367 | }
|
4368 |
|
4369 | $_subjectPrefix = $_finalSubjectPrefix = '';
|
4370 | if (isset($_emailQueueCache['list'][$_emailQueueID]))
|
4371 | {
|
4372 | $_emailQueueContainer = $_emailQueueCache['list'][$_emailQueueID];
|
4373 |
|
4374 | $_subjectPrefix = $_emailQueueContainer['prefix'];
|
4375 | }
|
4376 |
|
4377 | if (!empty($_subjectPrefix))
|
4378 | {
|
4379 | $_finalSubjectPrefix = $_subjectPrefix . ' ';
|
4380 | }
|
4381 |
|
4382 | $_finalSubject = $this->GetProperty('subject');
|
4383 | if (!empty($_customSubject)) {
|
4384 | $_finalSubject = $_customSubject;
|
4385 | }
|
4386 |
|
4387 | if ($this->Settings->Get('t_cleanmailsubjects') == '1') {
|
4388 | return $_finalSubject;
|
4389 | }
|
4390 |
|
4391 | switch ($_mailType) {
|
4392 | case self::MAIL_NOTIFICATION:
|
4393 | return '[' . $_finalSubjectPrefix . '!' . $this->GetTicketDisplayID() . ']: ' . $_finalSubject;
|
4394 | break;
|
4395 |
|
4396 | case self::MAIL_CLIENT:
|
4397 | return '[' . $_finalSubjectPrefix . '#' . $this->GetTicketDisplayID() . ']: ' . $_finalSubject;
|
4398 | break;
|
4399 |
|
4400 | case self::MAIL_THIRDPARTY:
|
4401 | return '[' . $_finalSubjectPrefix . '~' . $this->GetTicketDisplayID() . ']: ' . $_finalSubject;
|
4402 | break;
|
4403 |
|
4404 | default:
|
4405 | break;
|
4406 | }
|
4407 |
|
4408 | return false;
|
4409 | }
|
4410 |
|
4411 | /**
|
4412 | * Retrieve the default from name for the email
|
4413 | *
|
4414 | * @author Varun Shoor
|
4415 | * @param SWIFT_Staff $_SWIFT_StaffObject (OPTIONAL) The SWIFT_Staff Object Pointer
|
4416 | * @return string The Default From Name
|
4417 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4418 | */
|
4419 | public function GetMailFromName(SWIFT_Staff $_SWIFT_StaffObject = null)
|
4420 | {
|
4421 | $_SWIFT = SWIFT::GetInstance();
|
4422 |
|
4423 | if (!$this->GetIsClassLoaded())
|
4424 | {
|
4425 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4426 |
|
4427 | return false;
|
4428 | }
|
4429 |
|
4430 | $_emailQueueCache = $_SWIFT->Cache->Get('queuecache');
|
4431 | $_emailQueueID = $this->GetProperty('emailqueueid');
|
4432 | $_templateGroupID = $this->GetProperty('tgroupid');
|
4433 | if (empty($_templateGroupID) && isset($_SWIFT->TemplateGroup) && $_SWIFT->TemplateGroup instanceof SWIFT_TemplateGroup) {
|
4434 | $_templateGroupID = $_SWIFT->TemplateGroup->GetTemplateGroupID();
|
4435 | }
|
4436 |
|
4437 |
|
4438 | /*
|
4439 | * BUG FIX - Varun Shoor
|
4440 | *
|
4441 | * SWIFT-1327 From name and From email address improvements in autoresponder email, if visitor sends an offline message and help desk create the ticket
|
4442 | * SWIFT-1651 From Email Address (in autoresponder email) should set according to the template group under email queue, if ticket is created from client support center in case of multi-domain installation
|
4443 | *
|
4444 | * Comments: None
|
4445 | */
|
4446 |
|
4447 | // First try to lookup based on department and template group
|
4448 | if (empty($_emailQueueID) && isset($_emailQueueCache['list']) && _is_array($_emailQueueCache['list']))
|
4449 | {
|
4450 | foreach ($_emailQueueCache['list'] as $_emailQueueContainer)
|
4451 | {
|
4452 | if ($_emailQueueContainer['departmentid'] == $this->GetProperty('departmentid') && $_emailQueueContainer['tgroupid'] == $_templateGroupID)
|
4453 | {
|
4454 | $_emailQueueID = $_emailQueueContainer['emailqueueid'];
|
4455 |
|
4456 | break;
|
4457 | }
|
4458 | }
|
4459 | }
|
4460 |
|
4461 | // No Queue Prefix set, itterate through queues looking for one for ONLY this department
|
4462 | if (empty($_emailQueueID) && isset($_emailQueueCache['list']) && _is_array($_emailQueueCache['list']))
|
4463 | {
|
4464 | foreach ($_emailQueueCache['list'] as $_emailQueueContainer)
|
4465 | {
|
4466 | if ($_emailQueueContainer['departmentid'] == $this->GetProperty('departmentid'))
|
4467 | {
|
4468 | $_emailQueueID = $_emailQueueContainer['emailqueueid'];
|
4469 |
|
4470 | break;
|
4471 | }
|
4472 | }
|
4473 | }
|
4474 |
|
4475 | // Name Priority: Template Group > Settings > Staff > Email Queue
|
4476 |
|
4477 | $_defaultFromName = SWIFT::Get('companyname');
|
4478 | if (empty($_defaultFromName))
|
4479 | {
|
4480 | $_defaultFromName = $this->Settings->Get('general_companyname');
|
4481 | }
|
4482 |
|
4483 | if ($_SWIFT_StaffObject instanceof SWIFT_Staff && $_SWIFT_StaffObject->GetIsClassLoaded())
|
4484 | {
|
4485 | $_defaultFromName = $_SWIFT_StaffObject->GetProperty('fullname');
|
4486 | }
|
4487 |
|
4488 | if (isset($_emailQueueCache['list'][$_emailQueueID]))
|
4489 | {
|
4490 | $_emailQueueContainer = $_emailQueueCache['list'][$_emailQueueID];
|
4491 |
|
4492 | if (!empty($_emailQueueContainer['customfromname']))
|
4493 | {
|
4494 | $_defaultFromName = $_emailQueueContainer['customfromname'];
|
4495 | }
|
4496 | }
|
4497 |
|
4498 | return $_defaultFromName;
|
4499 | }
|
4500 |
|
4501 | /**
|
4502 | * Retrieve the default from email
|
4503 | *
|
4504 | * @author Varun Shoor
|
4505 | * @return string The Default Return Email
|
4506 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4507 | */
|
4508 | public function GetMailFromEmail()
|
4509 | {
|
4510 | $_SWIFT = SWIFT::GetInstance();
|
4511 |
|
4512 | if (!$this->GetIsClassLoaded())
|
4513 | {
|
4514 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4515 |
|
4516 | return false;
|
4517 | }
|
4518 |
|
4519 | $_emailQueueCache = $_SWIFT->Cache->Get('queuecache');
|
4520 | $_emailQueueID = $this->GetProperty('emailqueueid');
|
4521 | $_templateGroupID = $this->GetProperty('tgroupid');
|
4522 | if (empty($_templateGroupID) && isset($_SWIFT->TemplateGroup) && $_SWIFT->TemplateGroup instanceof SWIFT_TemplateGroup) {
|
4523 | $_templateGroupID = $_SWIFT->TemplateGroup->GetTemplateGroupID();
|
4524 | }
|
4525 |
|
4526 | /*
|
4527 | * BUG FIX - Varun Shoor
|
4528 | *
|
4529 | * SWIFT-1327 From name and From email address improvements in autoresponder email, if visitor sends an offline message and help desk create the ticket
|
4530 | * SWIFT-1651 From Email Address (in autoresponder email) should set according to the template group under email queue, if ticket is created from client support center in case of multi-domain installation
|
4531 | *
|
4532 | * Comments: None
|
4533 | */
|
4534 |
|
4535 | // First check against the template group id and department id
|
4536 | if (empty($_emailQueueID) && isset($_emailQueueCache['list']) && _is_array($_emailQueueCache['list']))
|
4537 | {
|
4538 | foreach ($_emailQueueCache['list'] as $_emailQueueContainer)
|
4539 | {
|
4540 | if ($_emailQueueContainer['departmentid'] == $this->GetProperty('departmentid') && $_templateGroupID == $_emailQueueContainer['tgroupid'])
|
4541 | {
|
4542 | $_emailQueueID = $_emailQueueContainer['emailqueueid'];
|
4543 |
|
4544 | break;
|
4545 | }
|
4546 | }
|
4547 | }
|
4548 |
|
4549 | // No Queue Prefix set, itterate through queues looking for one for ONLY this department
|
4550 | if (empty($_emailQueueID) && isset($_emailQueueCache['list']) && _is_array($_emailQueueCache['list']))
|
4551 | {
|
4552 | foreach ($_emailQueueCache['list'] as $_emailQueueContainer)
|
4553 | {
|
4554 | if ($_emailQueueContainer['departmentid'] == $this->GetProperty('departmentid'))
|
4555 | {
|
4556 | $_emailQueueID = $_emailQueueContainer['emailqueueid'];
|
4557 |
|
4558 | break;
|
4559 | }
|
4560 | }
|
4561 | }
|
4562 |
|
4563 | // Email Priority: Settings > Email Queue
|
4564 | $_defaultFromEmail = $this->Settings->Get('general_returnemail');
|
4565 |
|
4566 | if (isset($_emailQueueCache['list'][$_emailQueueID]))
|
4567 | {
|
4568 | $_emailQueueContainer = $_emailQueueCache['list'][$_emailQueueID];
|
4569 | if (!empty($_emailQueueContainer['customfromemail']))
|
4570 | {
|
4571 | $_defaultFromEmail = $_emailQueueContainer['customfromemail'];
|
4572 | } else {
|
4573 | $_defaultFromEmail = $_emailQueueContainer['email'];
|
4574 | }
|
4575 | }
|
4576 |
|
4577 | return $_defaultFromEmail;
|
4578 | }
|
4579 |
|
4580 | /**
|
4581 | * Load the Core Language Table
|
4582 | *
|
4583 | * @author Varun Shoor
|
4584 | * @return bool "true" on Success, "false" otherwise
|
4585 | */
|
4586 | static public function LoadLanguageTable() {
|
4587 | $_SWIFT = SWIFT::GetInstance();
|
4588 |
|
4589 | $_SWIFT->Language->Load('tickets_notifications', SWIFT_LanguageEngine::TYPE_FILE);
|
4590 | $_SWIFT->Language->Load('tickets_auditlogs', SWIFT_LanguageEngine::TYPE_FILE);
|
4591 |
|
4592 | return true;
|
4593 | }
|
4594 |
|
4595 | /**
|
4596 | * Retrieve the signature for this based on associated queue or given staff/user
|
4597 | *
|
4598 | * @author Varun Shoor
|
4599 | * @param bool $_isHTML Whether the reply is HTML
|
4600 | * @param object $_SWIFT_StaffObject (OPTIONAL) The SWIFT_Staff Object
|
4601 | * @return bool "true" on Success, "false" otherwise
|
4602 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4603 | */
|
4604 | public function GetSignature($_isHTML, $_SWIFT_StaffObject = null)
|
4605 | {
|
4606 | $_SWIFT = SWIFT::GetInstance();
|
4607 |
|
4608 | if (!$this->GetIsClassLoaded())
|
4609 | {
|
4610 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4611 |
|
4612 | return false;
|
4613 | }
|
4614 |
|
4615 | $_emailQueueCache = $_SWIFT->Cache->Get('queuecache');
|
4616 |
|
4617 | $_emailQueueID = $this->GetProperty('emailqueueid');
|
4618 |
|
4619 | $_signatureContents = '';
|
4620 |
|
4621 | if ($_isHTML == true)
|
4622 | {
|
4623 | $_signatureContents = '<br />';
|
4624 | } else {
|
4625 | $_signatureContents = SWIFT_CRLF;
|
4626 | }
|
4627 |
|
4628 | // First priority is given to Staff signature
|
4629 | if ($_SWIFT_StaffObject instanceof SWIFT_Staff && $_SWIFT_StaffObject->GetIsClassLoaded())
|
4630 | {
|
4631 | $_staffSignatureContents = '';
|
4632 | try {
|
4633 | $_staffSignatureContents = $_SWIFT_StaffObject->GetProperty('signature');
|
4634 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
4635 | }
|
4636 |
|
4637 | if ($_isHTML == true)
|
4638 | {
|
4639 | $_signatureContents .= nl2br($_staffSignatureContents);
|
4640 | } else {
|
4641 | $_signatureContents .= preg_replace("#(\r\n|\r|\n)#s", SWIFT_CRLF, $_staffSignatureContents);
|
4642 | }
|
4643 | }
|
4644 |
|
4645 | if (_is_array($_emailQueueCache) && isset($_emailQueueCache['list'][$_emailQueueID])) {
|
4646 | $_emailQueueContainer = $_emailQueueCache['list'][$_emailQueueID];
|
4647 | if ($_isHTML == true)
|
4648 | {
|
4649 | $_signatureContents .= nl2br($_emailQueueContainer['contents']);
|
4650 | } else {
|
4651 | $_signatureContents .= preg_replace("#(\r\n|\r|\n)#s", SWIFT_CRLF, $_emailQueueContainer['contents']);
|
4652 | }
|
4653 | }
|
4654 |
|
4655 | return $_signatureContents;
|
4656 | }
|
4657 |
|
4658 | /**
|
4659 | * Dispatch the auto responder msg
|
4660 | *
|
4661 | * @author Varun Shoor
|
4662 | * @return bool "true" on Success, "false" otherwise
|
4663 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4664 | */
|
4665 | public function DispatchAutoresponder()
|
4666 | {
|
4667 | if (!$this->GetIsClassLoaded())
|
4668 | {
|
4669 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
4670 |
|
4671 | return false;
|
4672 | }
|
4673 |
|
4674 | // We dispatch the auto responder to ALL registered emails of the user
|
4675 | $_ccEmailList = $this->GetCCUserEmails();
|
4676 |
|
4677 | $this->Load->Library('Ticket:TicketEmailDispatch', array($this));
|
4678 | $this->TicketEmailDispatch->DispatchAutoresponder('', $_ccEmailList);
|
4679 |
|
4680 | return true;
|
4681 | }
|
4682 |
|
4683 | /**
|
4684 | * Retrieves all other emails of the user excluding the one that was used to create the ticket
|
4685 | *
|
4686 | * @author Varun Shoor
|
4687 | * @return array The Email List
|
4688 | * @throws SWIFT_Exception If the Class is not Loaded
|
4689 | */
|
4690 | public function GetCCUserEmails()
|
4691 | {
|
4692 | if (!$this->GetIsClassLoaded())
|
4693 | {
|
4694 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
4695 |
|
4696 | return false;
|
4697 | }
|
4698 |
|
4699 | $_SWIFT_UserObject = $this->GetUserObject();
|
4700 |
|
4701 | $_ccEmailList = array();
|
4702 | if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded())
|
4703 | {
|
4704 | $_userEmailList = $_SWIFT_UserObject->GetEmailList();
|
4705 | if (_is_array($_userEmailList))
|
4706 | {
|
4707 | foreach ($_userEmailList as $_emailAddress)
|
4708 | {
|
4709 | if (mb_strtolower($_emailAddress) != mb_strtolower($this->GetProperty('email')))
|
4710 | {
|
4711 | $_ccEmailList[] = $_emailAddress;
|
4712 | }
|
4713 | }
|
4714 | }
|
4715 | }
|
4716 |
|
4717 | return $_ccEmailList;
|
4718 | }
|
4719 |
|
4720 | /**
|
4721 | * Retrieve the first ticket post object
|
4722 | *
|
4723 | * @author Varun Shoor
|
4724 | * @return SWIFT_TicketPost The SWIFT_TicketPost Object
|
4725 | * @throws SWIFT_Exception If the Class is not Loaded or If Invalid Data is Provided
|
4726 | */
|
4727 | public function GetFirstPostObject()
|
4728 | {
|
4729 | if (!$this->GetIsClassLoaded())
|
4730 | {
|
4731 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
4732 |
|
4733 | return false;
|
4734 | }
|
4735 |
|
4736 | $_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($this->GetProperty('firstpostid')));
|
4737 | if (!$_SWIFT_TicketPostObject instanceof SWIFT_TicketPost || !$_SWIFT_TicketPostObject->GetIsClassLoaded())
|
4738 | {
|
4739 | throw new SWIFT_Exception(SWIFT_INVALIDDATA);
|
4740 | }
|
4741 |
|
4742 | return $_SWIFT_TicketPostObject;
|
4743 | }
|
4744 |
|
4745 | /**
|
4746 | * Retrieve the time tracking count for the ticket
|
4747 | *
|
4748 | * @author Varun Shoor
|
4749 | * @return int The Count
|
4750 | * @throws SWIFT_Exception If the Class is not Loaded
|
4751 | */
|
4752 | public function GetTimeTrackCount()
|
4753 | {
|
4754 | if (!$this->GetIsClassLoaded())
|
4755 | {
|
4756 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
4757 |
|
4758 | return false;
|
4759 | }
|
4760 |
|
4761 | $_timeTrackCount = $this->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "tickettimetracks WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
4762 | if (isset($_timeTrackCount['totalitems']))
|
4763 | {
|
4764 | return intval($_timeTrackCount['totalitems']);
|
4765 | }
|
4766 |
|
4767 | return 0;
|
4768 | }
|
4769 |
|
4770 | /**
|
4771 | * Retrieve the list of all possible ticket ids created by a given user
|
4772 | *
|
4773 | * @author Varun Shoor
|
4774 | * @param SWIFT_User $_SWIFT_UserObject The SWIFT_User Object Pointer
|
4775 | * @return array The Ticket ID List
|
4776 | * @throws SWIFT_Exception If Invalid Data is Provided
|
4777 | */
|
4778 | static public function GetTicketIDListOnUser(SWIFT_User $_SWIFT_UserObject)
|
4779 | {
|
4780 | $_SWIFT = SWIFT::GetInstance();
|
4781 |
|
4782 | if (!$_SWIFT_UserObject instanceof SWIFT_User || !$_SWIFT_UserObject->GetIsClassLoaded())
|
4783 | {
|
4784 | throw new SWIFT_Exception(SWIFT_INVALIDDATA);
|
4785 | }
|
4786 |
|
4787 | $_ticketIDList = array();
|
4788 |
|
4789 | $_SWIFT->Database->Query("SELECT ticketid FROM " . TABLE_PREFIX . "tickets WHERE userid = '" . intval($_SWIFT_UserObject->GetUserID()) . "' OR email IN (" . BuildIN($_SWIFT_UserObject->GetEmailList()) . ")");
|
4790 | while ($_SWIFT->Database->NextRecord())
|
4791 | {
|
4792 | $_ticketIDList[] = intval($_SWIFT->Database->Record['ticketid']);
|
4793 | }
|
4794 |
|
4795 | return $_ticketIDList;
|
4796 | }
|
4797 |
|
4798 | /**
|
4799 | * Create a Note
|
4800 | *
|
4801 | * @author Varun Shoor
|
4802 | * @param SWIFT_User $_SWIFT_UserObject (OPTIONAL) The User Object
|
4803 | * @param string $_noteContents The Note Contents
|
4804 | * @param int $_noteColor The Note Color
|
4805 | * @param string $_noteType The Note Type
|
4806 | * @param int $_forStaffID (OPTIONAL) Restrict view to a given staff
|
4807 | * @param SWIFT_Staff $_SWIFT_StaffObject (OPTIONAL) The Staff Object to create note as
|
4808 | * @return bool "true" on Success, "false" otherwise
|
4809 | * @throws SWIFT_Exception If the Class is not Loaded
|
4810 | */
|
4811 | public function CreateNote($_SWIFT_UserObject, $_noteContents, $_noteColor, $_noteType, $_forStaffID = false, $_SWIFT_StaffObject = false) {
|
4812 | $_SWIFT = SWIFT::GetInstance();
|
4813 |
|
4814 | if (!$this->GetIsClassLoaded()) {
|
4815 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
4816 |
|
4817 | return false;
|
4818 | }
|
4819 |
|
4820 | $_isOrganizationNote = false;
|
4821 | $_SWIFT_UserOrganizationObject = $this->GetUserOrganizationObject();
|
4822 |
|
4823 | if ($_SWIFT_UserOrganizationObject instanceof SWIFT_UserOrganization && $_SWIFT_UserOrganizationObject->GetIsClassLoaded() &&
|
4824 | isset($_noteType) && $_noteType == 'userorganization')
|
4825 | {
|
4826 | $_isOrganizationNote = true;
|
4827 | }
|
4828 |
|
4829 | // Add notes
|
4830 | if (!empty($_noteContents))
|
4831 | {
|
4832 | if ($_isOrganizationNote)
|
4833 | {
|
4834 | SWIFT_UserOrganizationNote::Create($_SWIFT_UserOrganizationObject, $_noteContents, intval($_noteColor));
|
4835 |
|
4836 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_NEWNOTE,
|
4837 | $_SWIFT->Language->Get('al_usernote'),
|
4838 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
4839 | } else if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded() && isset($_noteType) && $_noteType == 'user') {
|
4840 | SWIFT_UserNote::Create($_SWIFT_UserObject, $_noteContents, intval($_noteColor));
|
4841 |
|
4842 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_NEWNOTE,
|
4843 | $_SWIFT->Language->Get('al_usernote'),
|
4844 | SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
4845 | } else {
|
4846 |
|
4847 | $_staffID = 0;
|
4848 | $_staffName = $this->Language->Get('system');
|
4849 | if ($_SWIFT_StaffObject instanceof SWIFT_Staff && $_SWIFT_StaffObject->GetIsClassLoaded()) {
|
4850 | $_staffID = $_SWIFT_StaffObject->GetStaffID();
|
4851 | $_staffName = $_SWIFT_StaffObject->GetProperty('fullname');
|
4852 | } else if ($_SWIFT->Staff instanceof SWIFT_Staff && $_SWIFT->Staff->GetIsClassLoaded()) {
|
4853 | $_staffID = $_SWIFT->Staff->GetStaffID();
|
4854 | $_staffName = $_SWIFT->Staff->GetProperty('fullname');
|
4855 | }
|
4856 |
|
4857 | SWIFT_TicketNote::Create($this, intval($_forStaffID), $_staffID, $_staffName, $_noteContents, intval($_noteColor));
|
4858 |
|
4859 | SWIFT_TicketAuditLog::AddToLog($this, null, SWIFT_TicketAuditLog::ACTION_NEWNOTE, $_SWIFT->Language->Get('al_ticketnote'), SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');
|
4860 | }
|
4861 |
|
4862 | if ( $this->Settings->Get('t_ticketnoteresetsupdatetime') == 1 ) {
|
4863 | $this->UpdatePool('lastactivity', DATENOW);
|
4864 | }
|
4865 |
|
4866 | }
|
4867 |
|
4868 | return true;
|
4869 | }
|
4870 |
|
4871 | /**
|
4872 | * Retrieve the Ticket ID from a Ticket Mask ID
|
4873 | *
|
4874 | * @author Varun Shoor
|
4875 | * @param string $_ticketMaskID The Ticket Mask ID
|
4876 | * @return int The Ticket ID
|
4877 | * @throws SWIFT_Exception If Invalid Data is Provided
|
4878 | */
|
4879 | static public function GetTicketIDFromMask($_ticketMaskID)
|
4880 | {
|
4881 | $_SWIFT = SWIFT::GetInstance();
|
4882 |
|
4883 | if (empty($_ticketMaskID))
|
4884 | {
|
4885 | throw new SWIFT_Exception(SWIFT_INVALIDDATA);
|
4886 | }
|
4887 |
|
4888 | $_ticketIDContainer = $_SWIFT->Database->QueryFetch("SELECT ticketid FROM " . TABLE_PREFIX . "tickets WHERE ticketmaskid = '" . $_SWIFT->Database->Escape($_ticketMaskID) . "'");
|
4889 | if (isset($_ticketIDContainer['ticketid']) && !empty($_ticketIDContainer['ticketid']))
|
4890 | {
|
4891 | return $_ticketIDContainer['ticketid'];
|
4892 | }
|
4893 |
|
4894 | return false;
|
4895 | }
|
4896 |
|
4897 | /**
|
4898 | * Retrieve the history count for this user based on his userid & email addresses
|
4899 | *
|
4900 | * @author Varun Shoor
|
4901 | * @param SWIFT_User $_SWIFT_UserObject
|
4902 | * @param array $_userEmailList
|
4903 | * @return int The History Count
|
4904 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
4905 | */
|
4906 | static public function GetHistoryCountOnUser($_SWIFT_UserObject, $_userEmailList = array()) {
|
4907 | $_SWIFT = SWIFT::GetInstance();
|
4908 |
|
4909 | $_userID = '-1';
|
4910 | if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded())
|
4911 | {
|
4912 | $_userID = $_SWIFT_UserObject->GetUserID();
|
4913 | }
|
4914 |
|
4915 | if (!_is_array($_userEmailList))
|
4916 | {
|
4917 | $_userEmailList = $_SWIFT_UserObject->GetEmailList();
|
4918 | }
|
4919 |
|
4920 | $_countContainer = $_SWIFT->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "tickets WHERE userid = '" .
|
4921 | intval($_userID) . "' OR email IN (" . BuildIN($_userEmailList) . ")");
|
4922 |
|
4923 | if (isset($_countContainer['totalitems']) && intval($_countContainer['totalitems']) > 0) {
|
4924 | return $_countContainer['totalitems'];
|
4925 | }
|
4926 |
|
4927 | return 0;
|
4928 | }
|
4929 |
|
4930 | /**
|
4931 | * Retrieve the history for this user
|
4932 | *
|
4933 | * @author Varun Shoor
|
4934 | * @param SWIFT_User $_SWIFT_UserObject
|
4935 | * @param array $_emailList The Email List
|
4936 | * @param string $_sortBy (OPTIONAL) The Custom Sort By
|
4937 | * @param string $_sortOrder (OPTIONAL) The Custom Sort Order
|
4938 | * @return array The History Container
|
4939 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4940 | */
|
4941 | static public function RetrieveHistoryOnUser($_SWIFT_UserObject, $_emailList = array(), $_sortBy = false, $_sortOrder = false) {
|
4942 | $_SWIFT = SWIFT::GetInstance();
|
4943 |
|
4944 | $_userID = '-1';
|
4945 | $_userEmailList = $_emailList;
|
4946 | if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded())
|
4947 | {
|
4948 | $_userID = $_SWIFT_UserObject->GetUserID();
|
4949 | $_userEmailList = array_merge($_userEmailList, $_SWIFT_UserObject->GetEmailList());
|
4950 | }
|
4951 |
|
4952 | $_historyContainer = array();
|
4953 |
|
4954 | $_ticketSortBy = 'dateline';
|
4955 | $_ticketSortOrder = 'DESC';
|
4956 | if (!empty($_sortBy) && !empty($_sortOrder))
|
4957 | {
|
4958 | $_ticketSortBy = $_sortBy;
|
4959 | $_ticketSortOrder = $_sortOrder;
|
4960 | }
|
4961 |
|
4962 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets WHERE userid = '" . intval($_userID) .
|
4963 | "' OR email IN (" . BuildIN($_userEmailList) . ") ORDER BY " . $_ticketSortBy . " " . $_ticketSortOrder);
|
4964 | while ($_SWIFT->Database->NextRecord()) {
|
4965 | $_historyContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
4966 | }
|
4967 |
|
4968 | return $_historyContainer;
|
4969 | }
|
4970 |
|
4971 | /**
|
4972 | * Retrieve the Support Center Tickets for this user
|
4973 | *
|
4974 | * @author Varun Shoor
|
4975 | * @param SWIFT_User $_SWIFT_UserObject
|
4976 | * @param string $_sortBy (OPTIONAL) The Custom Sort By
|
4977 | * @param string $_sortOrder (OPTIONAL) The Custom Sort Order
|
4978 | * @param int $_offset (OPTIONAL) The Starting Offset
|
4979 | * @param int $_limit (OPTIONAL) The Number of Results to Return
|
4980 | * @param bool $_excludeResolved
|
4981 | * @return array The History Container
|
4982 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
4983 | */
|
4984 | static public function RetrieveSCTicketsOnUser(SWIFT_User $_SWIFT_UserObject, $_sortBy = false, $_sortOrder = false, $_offset = 0, $_limit = false, $_excludeResolved = false) {
|
4985 | $_SWIFT = SWIFT::GetInstance();
|
4986 |
|
4987 | $_userID = '-1';
|
4988 | $_userEmailList = array();
|
4989 | if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded())
|
4990 | {
|
4991 | $_userID = $_SWIFT_UserObject->GetUserID();
|
4992 | $_userEmailList = array_merge($_userEmailList, $_SWIFT_UserObject->GetEmailList());
|
4993 | }
|
4994 |
|
4995 | $_historyContainer = array();
|
4996 |
|
4997 | $_ticketSortBy = 'dateline';
|
4998 | $_ticketSortOrder = 'DESC';
|
4999 | if (!empty($_sortBy) && !empty($_sortOrder))
|
5000 | {
|
5001 | $_ticketSortBy = $_sortBy;
|
5002 | $_ticketSortOrder = $_sortOrder;
|
5003 | }
|
5004 |
|
5005 | $_userIDList = array($_SWIFT_UserObject->GetUserID());
|
5006 |
|
5007 | // Does this user have a shared organization or he is a manager in an organization?
|
5008 | $_SWIFT_UserOrganizationObject = $_SWIFT_UserObject->GetOrganization();
|
5009 |
|
5010 | if (($_SWIFT_UserObject->GetProperty('userrole') == SWIFT_User::ROLE_MANAGER && $_SWIFT_UserOrganizationObject instanceof SWIFT_UserOrganization && $_SWIFT_UserOrganizationObject->GetIsClassLoaded()) ||
|
5011 | ($_SWIFT_UserOrganizationObject instanceof SWIFT_UserOrganization && $_SWIFT_UserOrganizationObject->GetIsClassLoaded() && $_SWIFT_UserOrganizationObject->GetProperty('organizationtype') == SWIFT_UserOrganization::TYPE_SHARED))
|
5012 | {
|
5013 | $_userIDList_Organization = array();
|
5014 | $_SWIFT->Database->Query("SELECT userid FROM " . TABLE_PREFIX . "users WHERE userorganizationid = '" . intval($_SWIFT_UserOrganizationObject->GetUserOrganizationID()) . "'");
|
5015 | while ($_SWIFT->Database->NextRecord())
|
5016 | {
|
5017 | $_userIDList_Organization[] = $_SWIFT->Database->Record['userid'];
|
5018 |
|
5019 | $_userIDList[] = $_SWIFT->Database->Record['userid'];
|
5020 | }
|
5021 |
|
5022 | $_userEmailList = array_merge($_userEmailList, SWIFT_UserEmail::RetrieveListOnUserIDList($_userIDList_Organization));
|
5023 | }
|
5024 |
|
5025 | $_whereExtended = '';
|
5026 | if ($_excludeResolved) {
|
5027 | $_whereExtended .= ' AND isresolved = "0"';
|
5028 | }
|
5029 | if ($_limit) {
|
5030 | $_SWIFT->Database->QueryLimit("SELECT * FROM " . TABLE_PREFIX . "tickets
|
5031 | WHERE (userid IN (" . BuildIN($_userIDList) . ") OR email IN (" . BuildIN($_userEmailList) . ") OR replyto IN (" . BuildIN($_userEmailList) . "))
|
5032 | AND departmentid <> '0'
|
5033 | " . $_whereExtended . "
|
5034 | ORDER BY " . $_ticketSortBy . " " . $_ticketSortOrder, $_limit, $_offset);
|
5035 | } else {
|
5036 | $_SWIFT->Database->QueryLimit("SELECT * FROM " . TABLE_PREFIX . "tickets
|
5037 | WHERE (userid IN (" . BuildIN($_userIDList) . ") OR email IN (" . BuildIN($_userEmailList) . ") OR replyto IN (" . BuildIN($_userEmailList) . "))
|
5038 | AND departmentid <> '0'
|
5039 | " . $_whereExtended . "
|
5040 | ORDER BY " . $_ticketSortBy . " " . $_ticketSortOrder);
|
5041 | }
|
5042 |
|
5043 | while ($_SWIFT->Database->NextRecord()) {
|
5044 | if ($_SWIFT->Database->Record['creator'] == SWIFT_Ticket::CREATOR_STAFF && !in_array(mb_strtolower($_SWIFT->Database->Record['replyto']), $_userEmailList))
|
5045 | {
|
5046 | continue;
|
5047 | }
|
5048 |
|
5049 | $_historyContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
5050 | }
|
5051 |
|
5052 | return $_historyContainer;
|
5053 | }
|
5054 |
|
5055 | /**
|
5056 | * Retrieve the Support Center Tickets count for this user
|
5057 | *
|
5058 | * @author Varun Shoor
|
5059 | * @param SWIFT_User $_SWIFT_UserObject
|
5060 | * @param bool $_excludeResolved
|
5061 | * @param bool $_resolvedOnly
|
5062 | * @return int The History Count
|
5063 | * @throws SWIFT_Ticket_Exception If Invalid Data is Provided
|
5064 | */
|
5065 | static public function RetrieveSCTicketsCountOnUser($_SWIFT_UserObject, $_excludeResolved = false, $_resolvedOnly = false) {
|
5066 | $_SWIFT = SWIFT::GetInstance();
|
5067 |
|
5068 | $_userID = '-1';
|
5069 | $_userEmailList = array();
|
5070 | if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded())
|
5071 | {
|
5072 | $_userID = $_SWIFT_UserObject->GetUserID();
|
5073 | $_userEmailList = array_merge($_userEmailList, $_SWIFT_UserObject->GetEmailList());
|
5074 | }
|
5075 |
|
5076 | $_userIDList = array($_SWIFT_UserObject->GetUserID());
|
5077 |
|
5078 | // Does this user have a shared organization or he is a manager in an organization?
|
5079 | $_SWIFT_UserOrganizationObject = $_SWIFT_UserObject->GetOrganization();
|
5080 |
|
5081 | if (($_SWIFT_UserObject->GetProperty('userrole') == SWIFT_User::ROLE_MANAGER && $_SWIFT_UserOrganizationObject instanceof SWIFT_UserOrganization && $_SWIFT_UserOrganizationObject->GetIsClassLoaded()) ||
|
5082 | ($_SWIFT_UserOrganizationObject instanceof SWIFT_UserOrganization && $_SWIFT_UserOrganizationObject->GetIsClassLoaded() && $_SWIFT_UserOrganizationObject->GetProperty('organizationtype') == SWIFT_UserOrganization::TYPE_SHARED))
|
5083 | {
|
5084 | $_userIDList_Organization = array();
|
5085 | $_SWIFT->Database->Query("SELECT userid FROM " . TABLE_PREFIX . "users WHERE userorganizationid = '" . intval($_SWIFT_UserOrganizationObject->GetUserOrganizationID()) . "'");
|
5086 | while ($_SWIFT->Database->NextRecord())
|
5087 | {
|
5088 | $_userIDList_Organization[] = $_SWIFT->Database->Record['userid'];
|
5089 |
|
5090 | $_userIDList[] = $_SWIFT->Database->Record['userid'];
|
5091 | }
|
5092 |
|
5093 | $_userEmailList = array_merge($_userEmailList, SWIFT_UserEmail::RetrieveListOnUserIDList($_userIDList_Organization));
|
5094 | }
|
5095 |
|
5096 | $_whereExtended = '';
|
5097 | if ($_excludeResolved) {
|
5098 | $_whereExtended = ' AND isresolved = "0"';
|
5099 | }
|
5100 |
|
5101 | if ($_resolvedOnly) {
|
5102 | $_whereExtended = ' AND isresolved = "1"';
|
5103 | }
|
5104 |
|
5105 | $_countContainer = $_SWIFT->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "tickets
|
5106 | WHERE (userid = '" . intval($_userID) . "' OR email IN (" . BuildIN($_userEmailList) . ") OR replyto IN (" . BuildIN($_userEmailList) . "))
|
5107 | AND departmentid <> '0'
|
5108 | " . $_whereExtended . "
|
5109 | ");
|
5110 |
|
5111 | if (isset($_countContainer['totalitems']) && intval($_countContainer['totalitems']) > 0) {
|
5112 | return $_countContainer['totalitems'];
|
5113 | }
|
5114 |
|
5115 | return 0;
|
5116 | }
|
5117 |
|
5118 | /**
|
5119 | * Set the Watcher Notification Message
|
5120 | *
|
5121 | * @author Varun Shoor
|
5122 | * @param string $_watcherName The Watcher Name
|
5123 | * @param string $_watcherMessage The Watcher Message
|
5124 | * @return bool "true" on Success, "false" otherwise
|
5125 | * @throws SWIFT_Exception If the Class is not Loaded
|
5126 | */
|
5127 | public function SetWatcherProperties($_watcherName, $_watcherMessage)
|
5128 | {
|
5129 | if (!$this->GetIsClassLoaded())
|
5130 | {
|
5131 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5132 |
|
5133 | return false;
|
5134 | }
|
5135 |
|
5136 | $this->_watcherCustomName = $_watcherName;
|
5137 | $this->_watchNotificationMessage = $_watcherMessage;
|
5138 |
|
5139 | return true;
|
5140 | }
|
5141 |
|
5142 | /**
|
5143 | * Process the Notification for Ticket Watchers
|
5144 | *
|
5145 | * @author Varun Shoor
|
5146 | * @return bool "true" on Success, "false" otherwise
|
5147 | * @throws SWIFT_Exception If the Class is not Loaded
|
5148 | */
|
5149 | public function ProcessWatchers()
|
5150 | {
|
5151 | chdir(SWIFT_BASEPATH);
|
5152 | $_ticketID = $this->GetTicketID();
|
5153 |
|
5154 | if (!$this->GetIsClassLoaded())
|
5155 | {
|
5156 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5157 |
|
5158 | return false;
|
5159 | } else if (isset(self::$_watcherExecutedCache[$_ticketID]) && self::$_watcherExecutedCache[$_ticketID] == 1) {
|
5160 | return true;
|
5161 | }
|
5162 |
|
5163 | $_staffCache = $this->Cache->Get('staffcache');
|
5164 |
|
5165 | $_emailList = array();
|
5166 | $_ticketWatchContainer = SWIFT_TicketWatcher::RetrieveOnTicket($this);
|
5167 | if (_is_array($_ticketWatchContainer))
|
5168 | {
|
5169 | foreach ($_ticketWatchContainer as $_ticketWatch)
|
5170 | {
|
5171 | $_staffID = $_ticketWatch['staffid'];
|
5172 |
|
5173 | if (!isset($_staffCache[$_staffID]))
|
5174 | {
|
5175 | continue;
|
5176 | }
|
5177 |
|
5178 | $_emailList[] = $_staffCache[$_staffID]['email'];
|
5179 | }
|
5180 | }
|
5181 |
|
5182 | if (!count($_emailList))
|
5183 | {
|
5184 | return false;
|
5185 | }
|
5186 |
|
5187 | $this->Notification->Dispatch(SWIFT_TicketNotification::TYPE_CUSTOM, $_emailList, $this->GetProperty('subject'), $this->_watchNotificationMessage, $this->_watcherCustomName, '', true);
|
5188 |
|
5189 | self::$_watcherExecutedCache[$_ticketID] = 1;
|
5190 |
|
5191 | return true;
|
5192 | }
|
5193 |
|
5194 | /**
|
5195 | * Queue the Watcher Execution
|
5196 | *
|
5197 | * @author Varun Shoor
|
5198 | * @return bool "true" on Success, "false" otherwise
|
5199 | * @throws SWIFT_Exception If the Class is not Loaded
|
5200 | */
|
5201 | public function QueueWatcherExecution()
|
5202 | {
|
5203 | $_ticketID = $this->GetTicketID();
|
5204 |
|
5205 | if (!$this->GetIsClassLoaded())
|
5206 | {
|
5207 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5208 |
|
5209 | return false;
|
5210 | } else if (isset(self::$_watcherPendingCache[$_ticketID]) && self::$_watcherPendingCache[$_ticketID] == '1') {
|
5211 | return true;
|
5212 | }
|
5213 |
|
5214 | // SWIFT::Shutdown($this, 'ProcessWatchers', -1, false);
|
5215 |
|
5216 | self::$_watcherPendingCache[$_ticketID] = 1;
|
5217 |
|
5218 | return true;
|
5219 | }
|
5220 |
|
5221 | /**
|
5222 | * Process the Notification Rules
|
5223 | *
|
5224 | * @author Varun Shoor
|
5225 | * @return bool "true" on Success, "false" otherwise
|
5226 | * @throws SWIFT_Exception If the Class is not Loaded
|
5227 | */
|
5228 | public function ProcessNotifications()
|
5229 | {
|
5230 | chdir(SWIFT_BASEPATH);
|
5231 | $_ticketID = $this->GetTicketID();
|
5232 |
|
5233 | if (!$this->GetIsClassLoaded())
|
5234 | {
|
5235 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5236 |
|
5237 | return false;
|
5238 | } else if (isset(self::$_notificationExecutionCache[$_ticketID]) && self::$_notificationExecutionCache[$_ticketID] == '1') {
|
5239 | return true;
|
5240 | }
|
5241 |
|
5242 | $this->NotificationManager->Trigger();
|
5243 |
|
5244 | self::$_notificationExecutionCache[$_ticketID] = 1;
|
5245 |
|
5246 | return true;
|
5247 | }
|
5248 |
|
5249 | /**
|
5250 | * Dispatch a Notification via Email on this Ticket
|
5251 | *
|
5252 | * @author Varun Shoor
|
5253 | * @param constant $_notificationType The Notification Type
|
5254 | * @param array $_customEmailList The Custom Email List
|
5255 | * @param string $_emailPrefix (OPTIONAL) The Custom Email Prefix
|
5256 | * @param string $_notificationEvent (OPTIONAL) The Notification Event
|
5257 | * @return bool "true" on Success, "false" otherwise
|
5258 | * @throws SWIFT_Exception If the Class is not Loaded
|
5259 | */
|
5260 | public function DispatchNotification($_notificationType, $_customEmailList, $_emailPrefix = '', $_notificationEvent = '')
|
5261 | {
|
5262 | if (!$this->GetIsClassLoaded())
|
5263 | {
|
5264 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5265 |
|
5266 | return false;
|
5267 | }
|
5268 |
|
5269 | $_finalEmailPrefix = '';
|
5270 | if (!empty($_emailPrefix))
|
5271 | {
|
5272 | $_finalEmailPrefix = $_emailPrefix . ' - ';
|
5273 | }
|
5274 |
|
5275 | $_notificationMessage = $this->_watchNotificationMessage;
|
5276 | if (empty($_notificationMessage)) {
|
5277 | $_notificationMessage = $this->_lastPostNotificationMessage;
|
5278 | }
|
5279 |
|
5280 | $this->Notification->Dispatch($_notificationType, $_customEmailList, $_finalEmailPrefix . $this->GetProperty('subject'), $_notificationMessage, $this->_watcherCustomName, '', false, $_notificationEvent);
|
5281 |
|
5282 | return true;
|
5283 | }
|
5284 |
|
5285 | /**
|
5286 | * Dispatch a Notification via Pool (DESKTOP APP) on this Ticket
|
5287 | *
|
5288 | * @author Varun Shoor
|
5289 | * @param constant $_notificationType The Notification Type
|
5290 | * @param array $_customStaffIDList The Custom Staff ID List
|
5291 | * @param string $_notificationEvent (OPTIONAL) The Notification Event
|
5292 | * @return bool "true" on Success, "false" otherwise
|
5293 | * @throws SWIFT_Exception If the Class is not Loaded
|
5294 | */
|
5295 | public function DispatchNotificationPool($_notificationType, $_customStaffIDList, $_notificationEvent = '')
|
5296 | {
|
5297 | if (!$this->GetIsClassLoaded())
|
5298 | {
|
5299 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5300 |
|
5301 | return false;
|
5302 | }
|
5303 |
|
5304 | // $this->Notification->DispatchPool($_notificationType, $_customStaffIDList, $this->GetProperty('subject'), $this->_watchNotificationMessage, $this->_watcherCustomName);
|
5305 |
|
5306 | return true;
|
5307 | }
|
5308 |
|
5309 | /**
|
5310 | * Add to Attachments
|
5311 | *
|
5312 | * @author Varun Shoor
|
5313 | * @param string $_fileName The File Name
|
5314 | * @param string $_fileType The File Type
|
5315 | * @param string $_fileContents The File Contents
|
5316 | * @return bool "true" on Success, "false" otherwise
|
5317 | * @throws SWIFT_Exception If the Class is not Loaded
|
5318 | */
|
5319 | public function AddToAttachments($_fileName, $_fileType, $_fileContents)
|
5320 | {
|
5321 | if (!$this->GetIsClassLoaded())
|
5322 | {
|
5323 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5324 |
|
5325 | return false;
|
5326 | }
|
5327 |
|
5328 | if (!isset(self::$_attachmentsContainer[$this->GetTicketID()]))
|
5329 | {
|
5330 | self::$_attachmentsContainer[$this->GetTicketID()] = array();
|
5331 | }
|
5332 |
|
5333 | self::$_attachmentsContainer[$this->GetTicketID()][] = array('name' => $_fileName, 'type' => $_fileType, 'contents' => $_fileContents);
|
5334 |
|
5335 | return true;
|
5336 | }
|
5337 |
|
5338 | /**
|
5339 | * Retrieve the Attachments Container
|
5340 | *
|
5341 | * @author Varun Shoor
|
5342 | * @return array The Attachments Container
|
5343 | * @throws SWIFT_Exception If the Class is not Loaded
|
5344 | */
|
5345 | public function GetAttachments()
|
5346 | {
|
5347 | if (!$this->GetIsClassLoaded())
|
5348 | {
|
5349 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5350 |
|
5351 | return false;
|
5352 | }
|
5353 |
|
5354 | if (!isset(self::$_attachmentsContainer[$this->GetTicketID()]))
|
5355 | {
|
5356 | return false;
|
5357 | }
|
5358 |
|
5359 | return self::$_attachmentsContainer[$this->GetTicketID()];
|
5360 | }
|
5361 |
|
5362 | /**
|
5363 | * Add to Active Attachments (for notifications)
|
5364 | *
|
5365 | * @author Varun Shoor
|
5366 | * @param string $_fileName The File Name
|
5367 | * @param string $_fileType The File Type
|
5368 | * @param string $_fileContents The File Contents
|
5369 | * @return bool "true" on Success, "false" otherwise
|
5370 | * @throws SWIFT_Exception If the Class is not Loaded
|
5371 | */
|
5372 | public function AddToNotificationAttachments($_fileName, $_fileType, $_fileContents)
|
5373 | {
|
5374 | if (!$this->GetIsClassLoaded())
|
5375 | {
|
5376 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5377 |
|
5378 | return false;
|
5379 | }
|
5380 |
|
5381 | if (!isset(self::$_notificationAttachmentsContainer[$this->GetTicketID()]))
|
5382 | {
|
5383 | self::$_notificationAttachmentsContainer[$this->GetTicketID()] = array();
|
5384 | }
|
5385 |
|
5386 | self::$_notificationAttachmentsContainer[$this->GetTicketID()][] = array('name' => $_fileName, 'type' => $_fileType, 'contents' => $_fileContents);
|
5387 |
|
5388 | return true;
|
5389 | }
|
5390 |
|
5391 | /**
|
5392 | * Retrieve the Attachments Container
|
5393 | *
|
5394 | * @author Varun Shoor
|
5395 | * @return array The Attachments Container
|
5396 | * @throws SWIFT_Exception If the Class is not Loaded
|
5397 | */
|
5398 | public function GetNotificationAttachments()
|
5399 | {
|
5400 | if (!$this->GetIsClassLoaded())
|
5401 | {
|
5402 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5403 |
|
5404 | return false;
|
5405 | }
|
5406 |
|
5407 | if (!isset(self::$_notificationAttachmentsContainer[$this->GetTicketID()]))
|
5408 | {
|
5409 | return false;
|
5410 | }
|
5411 |
|
5412 | return self::$_notificationAttachmentsContainer[$this->GetTicketID()];
|
5413 | }
|
5414 |
|
5415 | /**
|
5416 | * Move the tickets to trash
|
5417 | *
|
5418 | * @author Varun Shoor
|
5419 | * @param array $_departmentIDList The Department ID List
|
5420 | * @return bool "true" on Success, "false" otherwise
|
5421 | */
|
5422 | static public function MoveToTrashBulk($_departmentIDList) {
|
5423 | $_SWIFT = SWIFT::GetInstance();
|
5424 |
|
5425 | if (!_is_array($_departmentIDList)) {
|
5426 | return false;
|
5427 | }
|
5428 |
|
5429 | /**
|
5430 | * BUG FIX - Parminder Singh
|
5431 | *
|
5432 | * SWIFT-1894: 'Trash' count does not clear the ticket count in case a department is deleted
|
5433 | *
|
5434 | */
|
5435 |
|
5436 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('departmentid' => '0', 'trasholddepartmentid' => '0'), 'UPDATE', "departmentid IN (" . BuildIN($_departmentIDList) . ") OR trasholddepartmentid IN (" . BuildIN($_departmentIDList) . ")");
|
5437 |
|
5438 | return true;
|
5439 | }
|
5440 |
|
5441 | /**
|
5442 | * Move the tickets status to trash
|
5443 | *
|
5444 | * @author Varun Shoor
|
5445 | * @param array $_ticketStatusIDList The Ticket Status ID List
|
5446 | * @return bool "true" on Success, "false" otherwise
|
5447 | */
|
5448 | static public function ChangeStatusToTrash($_ticketStatusIDList) {
|
5449 | $_SWIFT = SWIFT::GetInstance();
|
5450 |
|
5451 | if (!_is_array($_ticketStatusIDList)) {
|
5452 | return false;
|
5453 | }
|
5454 |
|
5455 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('ticketstatusid' => '0'), 'UPDATE', "ticketstatusid IN (" . BuildIN($_ticketStatusIDList) . ")");
|
5456 |
|
5457 | return true;
|
5458 | }
|
5459 |
|
5460 | /**
|
5461 | * Update the User record
|
5462 | *
|
5463 | * @author Varun Shoor
|
5464 | * @param int $_userID The User ID
|
5465 | * @return bool "true" on Success, "false" otherwise
|
5466 | * @throws SWIFT_Exception If the Class is not Loaded
|
5467 | */
|
5468 | public function UpdateUser($_userID)
|
5469 | {
|
5470 | if (!$this->GetIsClassLoaded())
|
5471 | {
|
5472 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5473 |
|
5474 | return false;
|
5475 | }
|
5476 |
|
5477 | $this->UpdatePool('userid', $_userID);
|
5478 | $this->ProcessUpdatePool();
|
5479 |
|
5480 | return true;
|
5481 | }
|
5482 |
|
5483 | /**
|
5484 | * Retrieve the last post contents
|
5485 | *
|
5486 | * @author Varun Shoor
|
5487 | * @return string The last post contents
|
5488 | * @throws SWIFT_Exception If the Class is not Loaded
|
5489 | */
|
5490 | public function GetLastPostContents()
|
5491 | {
|
5492 | if (!$this->GetIsClassLoaded())
|
5493 | {
|
5494 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5495 |
|
5496 | return false;
|
5497 | }
|
5498 |
|
5499 | try {
|
5500 | $_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($this->GetProperty('lastpostid')));
|
5501 |
|
5502 | if ($_SWIFT_TicketPostObject->GetProperty('ticketid') == $this->GetTicketID())
|
5503 | {
|
5504 | return $_SWIFT_TicketPostObject->GetDisplayContents();
|
5505 | }
|
5506 |
|
5507 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
5508 |
|
5509 |
|
5510 | return '';
|
5511 | }
|
5512 |
|
5513 |
|
5514 |
|
5515 | return '';
|
5516 | }
|
5517 |
|
5518 | /**
|
5519 | * Retrieve the Ticket Post IDs linked with this ticket
|
5520 | *
|
5521 | * @author Varun Shoor
|
5522 | * @param bool $_ignoreForwardedPosts (OPTIONAL) Whether to ignore forwarded posts
|
5523 | * @return array The Ticket Post ID List
|
5524 | * @throws SWIFT_Exception If the Class is not Loaded
|
5525 | */
|
5526 | public function GetTicketPostIDList($_ignoreForwardedPosts = false)
|
5527 | {
|
5528 | if (!$this->GetIsClassLoaded())
|
5529 | {
|
5530 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5531 |
|
5532 | return false;
|
5533 | }
|
5534 |
|
5535 | $_ticketPostIDList = array();
|
5536 |
|
5537 | /*
|
5538 | * BUG FIX - Parminder Singh
|
5539 | *
|
5540 | * SWIFT-2286 Staff creates a ticket with attachment. When forward, attachment does not go with the ticket.
|
5541 | *
|
5542 | */
|
5543 | $this->Database->Query("SELECT ticketpostid, creator, emailto, isthirdparty FROM " . TABLE_PREFIX . "ticketposts WHERE ticketid = '" . intval($this->GetTicketID()) . "'");
|
5544 | while ($this->Database->NextRecord()) {
|
5545 | if ($_ignoreForwardedPosts == true && $this->Database->Record['creator'] == SWIFT_TicketPost::CREATOR_STAFF && $this->Database->Record['emailto'] != '' && $this->Database->Record['isthirdparty'] == '1')
|
5546 | {
|
5547 | continue;
|
5548 | }
|
5549 |
|
5550 | $_ticketPostIDList[] = $this->Database->Record['ticketpostid'];
|
5551 | }
|
5552 |
|
5553 | return $_ticketPostIDList;
|
5554 | }
|
5555 |
|
5556 | /**
|
5557 | * Update the Average Response Time
|
5558 | *
|
5559 | * @author Varun Shoor
|
5560 | * @param int $_responseTime
|
5561 | * @return bool "true" on Success, "false" otherwise
|
5562 | * @throws SWIFT_Exception If the Class is not Loaded
|
5563 | */
|
5564 | public function UpdateAverageResponseTime($_responseTime) {
|
5565 | if (!$this->GetIsClassLoaded()) {
|
5566 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5567 |
|
5568 | return false;
|
5569 | }
|
5570 |
|
5571 | $_oldHitCount = intval($this->GetProperty('averageresponsetimehits'));
|
5572 | $_oldAverageResponseTime = intval($this->GetProperty('averageresponsetime'));
|
5573 |
|
5574 | $_newHitCount = $_oldHitCount + 1;
|
5575 |
|
5576 | $_newAverageResponseTime = (($_oldAverageResponseTime*$_oldHitCount)+$_responseTime)/$_newHitCount;
|
5577 |
|
5578 | $this->UpdatePool('averageresponsetime', intval($_newAverageResponseTime));
|
5579 | $this->UpdatePool('averageresponsetimehits', intval($_newHitCount));
|
5580 |
|
5581 | return true;
|
5582 | }
|
5583 |
|
5584 | /**
|
5585 | * Update the Email Queue
|
5586 | *
|
5587 | * @author Varun Shoor
|
5588 | * @param int $_emailQueueID The Email Queue ID
|
5589 | * @return bool "true" on Success, "false" otherwise
|
5590 | * @throws SWIFT_Exception If the Class is not Loaded
|
5591 | */
|
5592 | public function UpdateQueue($_emailQueueIDIncoming) {
|
5593 | $_SWIFT = SWIFT::GetInstance();
|
5594 |
|
5595 | if (!$this->GetIsClassLoaded()) {
|
5596 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5597 |
|
5598 | return false;
|
5599 | } else if ($this->GetProperty('emailqueueid') == $_emailQueueIDIncoming) {
|
5600 | return true;
|
5601 | }
|
5602 |
|
5603 | $_emailQueueCache = $this->Cache->Get('queuecache');
|
5604 | $_templateGroupCache = $this->Cache->Get('templategroupcache');
|
5605 | $_emailQueueID = 0;
|
5606 | if (isset($_emailQueueCache['list'][$_emailQueueIDIncoming]))
|
5607 | {
|
5608 | $_emailQueueID = $_emailQueueIDIncoming;
|
5609 | }
|
5610 |
|
5611 | $_emailQueueContainer = false;
|
5612 | if (isset($_emailQueueCache['list'][$_emailQueueID]))
|
5613 | {
|
5614 | $_emailQueueContainer = $_emailQueueCache['list'][$_emailQueueID];
|
5615 | }
|
5616 |
|
5617 | $_templateGroupID = SWIFT_TemplateGroup::GetDefaultGroupID();
|
5618 |
|
5619 | if (_is_array($_emailQueueContainer) && isset($_templateGroupCache[$_emailQueueContainer['tgroupid']]))
|
5620 | {
|
5621 | $_templateGroupID = $_emailQueueContainer['tgroupid'];
|
5622 | }
|
5623 |
|
5624 | $this->UpdatePool('emailqueueid', intval($_emailQueueID));
|
5625 | $this->UpdatePool('tgroupid', intval($_templateGroupID));
|
5626 |
|
5627 | return true;
|
5628 | }
|
5629 |
|
5630 | /**
|
5631 | * Load the Last Post Notification Message
|
5632 | *
|
5633 | * @author Varun Shoor
|
5634 | * @return bool "true" on Success, "false" otherwise
|
5635 | * @throws SWIFT_Exception If the Class is not Loaded
|
5636 | */
|
5637 | protected function LoadLastPostNotificationMessage() {
|
5638 | if (!$this->GetIsClassLoaded()) {
|
5639 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5640 |
|
5641 | return false;
|
5642 | }
|
5643 |
|
5644 | try {
|
5645 | $_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($this->GetProperty('lastpostid')));
|
5646 | $this->_lastPostNotificationMessage = $_SWIFT_TicketPostObject->GetProperty('contents');
|
5647 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
5648 |
|
5649 | return false;
|
5650 | }
|
5651 |
|
5652 | return true;
|
5653 | }
|
5654 |
|
5655 | /**
|
5656 | * Retrieve the Ticket ID Object on the provided Ticket ID
|
5657 | *
|
5658 | * @author Varun Shoor
|
5659 | * @param mixed $_ticketID The Numeric or Mask Ticket ID
|
5660 | * @return SWIFT_Ticket
|
5661 | */
|
5662 | static public function GetObjectOnID($_ticketID)
|
5663 | {
|
5664 | $_SWIFT = SWIFT::GetInstance();
|
5665 |
|
5666 | $_SWIFT_TicketObject = false;
|
5667 |
|
5668 | if (is_numeric($_ticketID)) {
|
5669 | try {
|
5670 | $_SWIFT_TicketObject = new SWIFT_Ticket(new SWIFT_DataID($_ticketID));
|
5671 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
5672 | }
|
5673 | } else {
|
5674 | $_ticketID = SWIFT_Ticket::GetTicketIDFromMask($_ticketID);
|
5675 | if (empty($_ticketID)) {
|
5676 | return false;
|
5677 | }
|
5678 |
|
5679 | try {
|
5680 | $_SWIFT_TicketObject = new SWIFT_Ticket(new SWIFT_DataID($_ticketID));
|
5681 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
5682 | }
|
5683 | }
|
5684 |
|
5685 | if ($_SWIFT_TicketObject instanceof SWIFT_Ticket && $_SWIFT_TicketObject->GetIsClassLoaded()) {
|
5686 | return $_SWIFT_TicketObject;
|
5687 | }
|
5688 |
|
5689 | // By now we couldnt get the ticket object, we have to lookup the merge logs
|
5690 | $_mergeTicketID = false;
|
5691 | if (is_numeric($_ticketID)) {
|
5692 | $_mergeTicketID = SWIFT_TicketMergeLog::GetTicketIDFromMergedTicketID($_ticketID);
|
5693 | } else {
|
5694 | $_mergeTicketID = SWIFT_TicketMergeLog::GetTicketIDFromMergedTicketMaskID($_ticketID);
|
5695 | }
|
5696 |
|
5697 | if (!empty($_mergeTicketID)) {
|
5698 | try
|
5699 | {
|
5700 | $_SWIFT_TicketObject = new SWIFT_Ticket(new SWIFT_DataID($_mergeTicketID));
|
5701 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
5702 | }
|
5703 |
|
5704 | if ($_SWIFT_TicketObject instanceof SWIFT_Ticket && $_SWIFT_TicketObject->GetIsClassLoaded())
|
5705 | {
|
5706 | return $_SWIFT_TicketObject;
|
5707 | }
|
5708 | }
|
5709 |
|
5710 | return false;
|
5711 | }
|
5712 |
|
5713 | /**
|
5714 | * Mark the Tickets as Pending Auto Closure
|
5715 | *
|
5716 | * @author Varun Shoor
|
5717 | * @param array $_ticketIDList
|
5718 | * @param SWIFT_AutoCloseRule $_SWIFT_AutoCloseRuleObject
|
5719 | * @return bool "true" on Success, "false" otherwise
|
5720 | * @throws SWIFT_Exception If Invalid Data is Provided
|
5721 | */
|
5722 | static public function MarkAsAutoClosePending($_ticketIDList, SWIFT_AutoCloseRule $_SWIFT_AutoCloseRuleObject)
|
5723 | {
|
5724 | $_SWIFT = SWIFT::GetInstance();
|
5725 |
|
5726 | if (!$_SWIFT_AutoCloseRuleObject instanceof SWIFT_AutoCloseRule || !$_SWIFT_AutoCloseRuleObject->GetIsClassLoaded()) {
|
5727 | throw new SWIFT_Exception(SWIFT_INVALIDDATA);
|
5728 | }
|
5729 |
|
5730 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('isautoclosed' => '0', 'autocloseruleid' => intval($_SWIFT_AutoCloseRuleObject->GetAutoCloseRuleID()),
|
5731 | 'autoclosestatus' => self::AUTOCLOSESTATUS_PENDING, 'autoclosetimeline' => DATENOW), 'UPDATE', "ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
5732 |
|
5733 | // Do we need to send the pending notification?
|
5734 | if ($_SWIFT_AutoCloseRuleObject->GetProperty('sendpendingnotification') == '0') {
|
5735 | return true;
|
5736 | }
|
5737 |
|
5738 | $_ticketsContainer = array();
|
5739 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets
|
5740 | WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
5741 | while ($_SWIFT->Database->NextRecord()) {
|
5742 | $_ticketsContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
5743 | }
|
5744 |
|
5745 | foreach ($_ticketsContainer as $_SWIFT_TicketObject) {
|
5746 | if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
|
5747 | continue;
|
5748 | }
|
5749 |
|
5750 | $_SWIFT_TicketEmailDispatch = new SWIFT_TicketEmailDispatch($_SWIFT_TicketObject);
|
5751 | $_SWIFT_TicketEmailDispatch->DispatchPendingAutoClose($_SWIFT_AutoCloseRuleObject);
|
5752 | }
|
5753 |
|
5754 | return true;
|
5755 | }
|
5756 |
|
5757 | /**
|
5758 | * Mark the Tickets as Closed via Auto Closed
|
5759 | *
|
5760 | * @author Varun Shoor
|
5761 | * @param array $_ticketIDList
|
5762 | * @param SWIFT_AutoCloseRule $_SWIFT_AutoCloseRuleObject
|
5763 | * @return bool "true" on Success, "false" otherwise
|
5764 | * @throws SWIFT_Exception If Invalid Data is Provided
|
5765 | */
|
5766 | static public function MarkAsAutoClosed($_ticketIDList, SWIFT_AutoCloseRule $_SWIFT_AutoCloseRuleObject)
|
5767 | {
|
5768 | $_SWIFT = SWIFT::GetInstance();
|
5769 |
|
5770 | if (!$_SWIFT_AutoCloseRuleObject instanceof SWIFT_AutoCloseRule || !$_SWIFT_AutoCloseRuleObject->GetIsClassLoaded()) {
|
5771 | throw new SWIFT_Exception(SWIFT_INVALIDDATA);
|
5772 | }
|
5773 |
|
5774 | $_ticketsContainer = array();
|
5775 | $_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . "tickets
|
5776 | WHERE ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
5777 | while ($_SWIFT->Database->NextRecord()) {
|
5778 | $_ticketsContainer[$_SWIFT->Database->Record['ticketid']] = new SWIFT_Ticket(new SWIFT_DataStore($_SWIFT->Database->Record));
|
5779 | }
|
5780 |
|
5781 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array('isautoclosed' => '1', 'autocloseruleid' => intval($_SWIFT_AutoCloseRuleObject->GetAutoCloseRuleID()),
|
5782 | 'autoclosestatus' => self::AUTOCLOSESTATUS_CLOSED, 'autoclosetimeline' => DATENOW), 'UPDATE', "ticketid IN (" . BuildIN($_ticketIDList) . ")");
|
5783 |
|
5784 | foreach ($_ticketsContainer as $_SWIFT_TicketObject) {
|
5785 | if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
|
5786 | continue;
|
5787 | }
|
5788 |
|
5789 | $_SWIFT_TicketObject->SetStatus($_SWIFT_AutoCloseRuleObject->GetProperty('targetticketstatusid'), true, $_SWIFT_AutoCloseRuleObject->GetProperty('suppresssurveyemail'));
|
5790 |
|
5791 | // Do we need to send the final notification?
|
5792 | if ($_SWIFT_AutoCloseRuleObject->GetProperty('sendfinalnotification') == '1') {
|
5793 | $_SWIFT_TicketEmailDispatch = new SWIFT_TicketEmailDispatch($_SWIFT_TicketObject);
|
5794 | $_SWIFT_TicketEmailDispatch->DispatchFinalAutoClose($_SWIFT_AutoCloseRuleObject);
|
5795 | }
|
5796 |
|
5797 | $_SWIFT_TicketObject->RebuildProperties();
|
5798 | }
|
5799 |
|
5800 | return true;
|
5801 | }
|
5802 |
|
5803 | /**
|
5804 | * Retrieve the from email with proper suffix
|
5805 | *
|
5806 | * @author Varun Shoor
|
5807 | * @param string $_fromEmailAddress
|
5808 | * @param constant $_mailType
|
5809 | * @return bool "true" on Success, "false" otherwise
|
5810 | * @throws SWIFT_Exception If the Class is not Loaded
|
5811 | */
|
5812 | public function RetrieveFromEmailWithSuffix($_fromEmailAddress, $_mailType)
|
5813 | {
|
5814 | if (!$this->GetIsClassLoaded()) {
|
5815 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5816 |
|
5817 | return false;
|
5818 | }
|
5819 |
|
5820 | // Have we enabled clean subjects?
|
5821 | if ($this->Settings->Get('t_cleanmailsubjects') != '1') {
|
5822 | return $_fromEmailAddress;
|
5823 | }
|
5824 |
|
5825 | $_finalReturnEmailAddress = '';
|
5826 |
|
5827 | $_matches = array();
|
5828 | if (preg_match('/^(.*?)@(.*?)$/i', $_fromEmailAddress, $_matches)) {
|
5829 | $_dispatchType = 'r';
|
5830 | if ($_mailType == self::MAIL_NOTIFICATION) {
|
5831 | $_dispatchType = 'a';
|
5832 | } else if ($_mailType == self::MAIL_THIRDPARTY) {
|
5833 | $_dispatchType = 't';
|
5834 | }
|
5835 |
|
5836 | $_hashChunk = substr($this->GetProperty('tickethash'), 0, 5);
|
5837 |
|
5838 | $_finalReturnEmailAddress = $_matches[1] . '+' . $_dispatchType . '.' . $_hashChunk . '.' . $this->GetTicketID() . '@' . $_matches[2];
|
5839 |
|
5840 | } else {
|
5841 | return $_fromEmailAddress;
|
5842 | }
|
5843 |
|
5844 |
|
5845 | return $_finalReturnEmailAddress;
|
5846 | }
|
5847 |
|
5848 | /**
|
5849 | * Reset SLA Calculations
|
5850 | *
|
5851 | * @author Mahesh Salaria
|
5852 | * @return bool "true" on Success, "false" otherwise
|
5853 | * @throws SWIFT_Exception If the Class is not Loaded
|
5854 | */
|
5855 | public function ResetSLA()
|
5856 | {
|
5857 | if (!$this->GetIsClassLoaded()) {
|
5858 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5859 |
|
5860 | return false;
|
5861 | }
|
5862 |
|
5863 | $this->_noSLACalculation = false;
|
5864 |
|
5865 | return true;
|
5866 | }
|
5867 |
|
5868 | /**
|
5869 | * Return the total ticket count
|
5870 | *
|
5871 | * @author Varun Shoor
|
5872 | * @return int The Total Ticket Count
|
5873 | */
|
5874 | static public function GetTicketCount()
|
5875 | {
|
5876 | $_SWIFT = SWIFT::GetInstance();
|
5877 |
|
5878 | $_ticketCountContainer = $_SWIFT->Database->QueryFetch("SELECT COUNT(*) AS totalitems FROM " . TABLE_PREFIX . "tickets");
|
5879 | if (isset($_ticketCountContainer['totalitems']) && !empty($_ticketCountContainer['totalitems'])) {
|
5880 | return intval($_ticketCountContainer['totalitems']);
|
5881 | }
|
5882 |
|
5883 | return 0;
|
5884 | }
|
5885 |
|
5886 | /**
|
5887 | * Update the global property on all tickets, used to update stuff like departmentname etc.
|
5888 | *
|
5889 | * @author Varun Shoor
|
5890 | * @param string $_updateFieldName
|
5891 | * @param string $_updateFieldValue
|
5892 | * @param string $_whereFieldName
|
5893 | * @param string $_whereFieldValue
|
5894 | * @return bool "true" on Success, "false" otherwise
|
5895 | */
|
5896 | static public function UpdateGlobalProperty($_updateFieldName, $_updateFieldValue, $_whereFieldName, $_whereFieldValue)
|
5897 | {
|
5898 | $_SWIFT = SWIFT::GetInstance();
|
5899 |
|
5900 | $_updateFieldName = $_SWIFT->Database->Escape($_updateFieldName);
|
5901 | $_whereFieldName = $_SWIFT->Database->Escape($_whereFieldName);
|
5902 | $_whereFieldValue = intval($_whereFieldValue); // Expected to be always int
|
5903 |
|
5904 | $_SWIFT->Database->AutoExecute(TABLE_PREFIX . 'tickets', array($_updateFieldName => $_updateFieldValue), 'UPDATE', $_whereFieldName . " = '" . $_whereFieldValue . "'");
|
5905 |
|
5906 | return true;
|
5907 | }
|
5908 |
|
5909 | /**
|
5910 | * Set alert rules for ticket
|
5911 | *
|
5912 | * @author Ruchi Kothari
|
5913 | * @param bool $_noAlerts Alert rules
|
5914 | * @return bool "true" on Success, "false" otherwise
|
5915 | * @throws SWIFT_Exception If the Class is not Loaded
|
5916 | */
|
5917 | public function SetNoAlerts($_noAlerts)
|
5918 | {
|
5919 | if (!$this->GetIsClassLoaded()) {
|
5920 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5921 |
|
5922 | return false;
|
5923 | }
|
5924 |
|
5925 | $this->_noAlerts = $_noAlerts;
|
5926 | }
|
5927 |
|
5928 | /**
|
5929 | * Get alert rules for ticket
|
5930 | *
|
5931 | * @author Ruchi Kothari
|
5932 | * @return bool Alert rules status
|
5933 | * @throws SWIFT_Exception If the Class is not Loaded
|
5934 | */
|
5935 | public function GetNoAlerts()
|
5936 | {
|
5937 | if (!$this->GetIsClassLoaded()) {
|
5938 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
5939 |
|
5940 | return false;
|
5941 | }
|
5942 |
|
5943 | return $this->_noAlerts;
|
5944 | }
|
5945 |
|
5946 | /**
|
5947 | * Set Old Ticket properties. This array is used to Keep previous ticket properties after execution.
|
5948 | *
|
5949 | * @author Mahesh Salaria
|
5950 | * @return bool "true" on Success, "false" otherwise
|
5951 | * @throws SWIFT_Ticket_Exception If the Class is not Loaded
|
5952 | */
|
5953 | public function SetOldTicketProperties()
|
5954 | {
|
5955 | if (!$this->GetIsClassLoaded()) {
|
5956 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
5957 |
|
5958 | return false;
|
5959 | }
|
5960 |
|
5961 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETSTATUS] = $this->GetProperty('ticketstatusid');
|
5962 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETPRIORITY] = $this->GetProperty('priorityid');
|
5963 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETDEPARTMENT] = $this->GetProperty('departmentid');
|
5964 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETOWNER] = intval($this->GetProperty('ownerstaffid'));
|
5965 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETEMAILQUEUE] = $this->GetProperty('emailqueueid');
|
5966 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETFLAGTYPE] = $this->GetProperty('flagtype');
|
5967 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETCREATOR] = $this->GetProperty('creator');
|
5968 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETUSERGROUP] = $this->GetUserGroupID();
|
5969 |
|
5970 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETFULLNAME] = $this->GetProperty('fullname');
|
5971 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETEMAIL] = $this->GetProperty('email');
|
5972 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETLASTREPLIER] = $this->GetProperty('lastreplier');
|
5973 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETSUBJECT] = $this->GetProperty('subject');
|
5974 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETCHARSET] = $this->GetProperty('charset');
|
5975 |
|
5976 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETTEMPLATEGROUP] = $this->GetProperty('tgroupid');
|
5977 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETISRESOLVED] = $this->GetProperty('isresolved');
|
5978 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETTYPE] = intval($this->GetProperty('tickettypeid'));
|
5979 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETWASREOPENED] = $this->GetProperty('wasreopened');
|
5980 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETTOTALREPLIES] = $this->GetProperty('totalreplies');
|
5981 | $this->_oldTicketProperties[SWIFT_SLA::SLA_TICKETBAYESCATEGORY] = $this->GetProperty('bayescategoryid');
|
5982 |
|
5983 | return true;
|
5984 | }
|
5985 |
|
5986 | /**
|
5987 | * Get Old ticket properties
|
5988 | *
|
5989 | * @author Mahesh Salaria
|
5990 | * @return array of old ticket properties
|
5991 | * @throws SWIFT_Exception If the Class is not Loaded
|
5992 | */
|
5993 | public function GetOldTicketProperties()
|
5994 | {
|
5995 | if (!$this->GetIsClassLoaded()) {
|
5996 | throw new SWIFT_Ticket_Exception(SWIFT_CLASSNOTLOADED);
|
5997 |
|
5998 | return false;
|
5999 | }
|
6000 |
|
6001 | return $this->_oldTicketProperties;
|
6002 | }
|
6003 | } |