dolibarr  17.0.2
ticket.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2013-2018 Jean-François Ferry <hello@librethic.io>
3  * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
4  * Copyright (C) 2019-2022 Frédéric France <frederic.france@netlogic.fr>
5  * Copyright (C) 2020 Laurent Destailleur <eldy@users.sourceforge.net>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
27 // Put here all includes required by your class file
28 require_once DOL_DOCUMENT_ROOT."/core/class/commonobject.class.php";
29 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php';
31 
32 
36 class Ticket extends CommonObject
37 {
41  public $element = 'ticket';
42 
46  public $table_element = 'ticket';
47 
51  public $fk_element = 'fk_ticket';
52 
56  public $ismultientitymanaged = 1;
57 
61  public $isextrafieldmanaged = 1;
62 
66  public $picto = 'ticket';
67 
68 
72  public $track_id;
73 
77  public $fk_soc;
78 
82  public $fk_project;
83 
87  public $origin_email;
88 
92  public $fk_user_create;
93 
97  public $fk_user_assign;
98 
102  public $subject;
103 
107  public $message;
108 
114  public $fk_statut;
115 
119  public $status;
120 
124  public $resolution;
125 
129  public $progress;
130 
134  public $timing;
135 
139  public $type_code;
140 
144  public $category_code;
145 
149  public $severity_code;
150 
154  public $type_label;
155 
160 
165 
169  public $email_from;
170 
174  public $datec = '';
175 
179  public $date_read = '';
180 
184  public $date_last_msg_sent = '';
185 
189  public $date_close = '';
190 
194  public $cache_types_tickets;
195 
199  public $cache_category_tickets;
200 
204  public $notify_tiers_at_create;
205 
209  public $email_msgid;
210 
214  public $email_date;
215 
219  public $ip;
220 
224  public $oldcopy;
225 
229  public $lines;
230 
231 
235  public $regeximgext = '\.gif|\.jpg|\.jpeg|\.png|\.bmp|\.webp|\.xpm|\.xbm'; // See also into images.lib.php
236 
240  const STATUS_NOT_READ = 0;
241  const STATUS_READ = 1;
242  const STATUS_ASSIGNED = 2;
243  const STATUS_IN_PROGRESS = 3;
244  const STATUS_NEED_MORE_INFO = 5; // waiting requester feedback
245  const STATUS_WAITING = 7; // on hold
246  const STATUS_CLOSED = 8; // Closed - Solved
247  const STATUS_CANCELED = 9; // Closed - Not solved
248 
249 
276  // BEGIN MODULEBUILDER PROPERTIES
277  public $fields = array(
278  'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>-2, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>"Id"),
279  'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>5, 'notnull'=>1, 'index'=>1),
280  'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'visible'=>1, 'enabled'=>1, 'position'=>10, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'css'=>'', 'showoncombobox'=>1),
281  'track_id' => array('type'=>'varchar(255)', 'label'=>'TicketTrackId', 'visible'=>-2, 'enabled'=>1, 'position'=>11, 'notnull'=>-1, 'searchall'=>1, 'help'=>"Help text"),
282  'fk_user_create' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'Author', 'visible'=>1, 'enabled'=>1, 'position'=>15, 'notnull'=>1, 'csslist'=>'tdoverflowmax100 maxwidth150onsmartphone'),
283  'origin_email' => array('type'=>'mail', 'label'=>'OriginEmail', 'visible'=>-2, 'enabled'=>1, 'position'=>16, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'csslist'=>'tdoverflowmax150'),
284  'subject' => array('type'=>'varchar(255)', 'label'=>'Subject', 'visible'=>1, 'enabled'=>1, 'position'=>18, 'notnull'=>-1, 'searchall'=>1, 'help'=>"", 'css'=>'maxwidth200 tdoverflowmax200', 'autofocusoncreate'=>1),
285  'type_code' => array('type'=>'varchar(32)', 'label'=>'Type', 'visible'=>1, 'enabled'=>1, 'position'=>20, 'notnull'=>-1, 'help'=>"", 'csslist'=>'maxwidth125 tdoverflowmax50'),
286  'category_code' => array('type'=>'varchar(32)', 'label'=>'TicketCategory', 'visible'=>-1, 'enabled'=>1, 'position'=>21, 'notnull'=>-1, 'help'=>"", 'css'=>'maxwidth100 tdoverflowmax200'),
287  'severity_code' => array('type'=>'varchar(32)', 'label'=>'Severity', 'visible'=>1, 'enabled'=>1, 'position'=>22, 'notnull'=>-1, 'help'=>"", 'css'=>'maxwidth100'),
288  'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php', 'label'=>'ThirdParty', 'visible'=>1, 'enabled'=>'$conf->societe->enabled', 'position'=>50, 'notnull'=>-1, 'index'=>1, 'searchall'=>1, 'help'=>"OrganizationEventLinkToThirdParty", 'css'=>'tdoverflowmax150 maxwidth150onsmartphone'),
289  'notify_tiers_at_create' => array('type'=>'integer', 'label'=>'NotifyThirdparty', 'visible'=>-1, 'enabled'=>0, 'position'=>51, 'notnull'=>1, 'index'=>1),
290  'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php', 'label'=>'Project', 'visible'=>-1, 'enabled'=>'$conf->project->enabled', 'position'=>52, 'notnull'=>-1, 'index'=>1, 'help'=>"LinkToProject"),
291  //'timing' => array('type'=>'varchar(20)', 'label'=>'Timing', 'visible'=>-1, 'enabled'=>1, 'position'=>42, 'notnull'=>-1, 'help'=>""), // what is this ?
292  'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'visible'=>1, 'enabled'=>1, 'position'=>500, 'notnull'=>1, 'csslist'=>'nowraponall'),
293  'date_read' => array('type'=>'datetime', 'label'=>'TicketReadOn', 'visible'=>-1, 'enabled'=>1, 'position'=>501, 'notnull'=>1),
294  'date_last_msg_sent' => array('type'=>'datetime', 'label'=>'TicketLastMessageDate', 'visible'=>0, 'enabled'=>1, 'position'=>502, 'notnull'=>-1),
295  'fk_user_assign' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'AssignedTo', 'visible'=>1, 'enabled'=>1, 'position'=>505, 'notnull'=>1, 'csslist'=>'tdoverflowmax100 maxwidth150onsmartphone'),
296  'date_close' => array('type'=>'datetime', 'label'=>'TicketCloseOn', 'visible'=>-1, 'enabled'=>1, 'position'=>510, 'notnull'=>1),
297  'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'visible'=>-1, 'enabled'=>1, 'position'=>520, 'notnull'=>1),
298  'message' => array('type'=>'text', 'label'=>'Message', 'visible'=>-2, 'enabled'=>1, 'position'=>540, 'notnull'=>-1,),
299  'email_msgid' => array('type'=>'varchar(255)', 'label'=>'EmailMsgID', 'visible'=>-2, 'enabled'=>1, 'position'=>540, 'notnull'=>-1, 'help'=>'EmailMsgIDDesc'),
300  'email_date' => array('type'=>'datetime', 'label'=>'EmailDate', 'visible'=>-2, 'enabled'=>1, 'position'=>541),
301  'progress' => array('type'=>'integer', 'label'=>'Progression', 'visible'=>-1, 'enabled'=>1, 'position'=>540, 'notnull'=>-1, 'css'=>'right', 'help'=>"", 'isameasure'=>2, 'csslist'=>'width50'),
302  'resolution' => array('type'=>'integer', 'label'=>'Resolution', 'visible'=>-1, 'enabled'=>'getDolGlobalString("TICKET_ENABLE_RESOLUTION")', 'position'=>550, 'notnull'=>1),
303  'fk_statut' => array('type'=>'integer', 'label'=>'Status', 'visible'=>1, 'enabled'=>1, 'position'=>600, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array(0 => 'Unread', 1 => 'Read', 3 => 'Answered', 4 => 'Assigned', 5 => 'InProgress', 6 => 'Waiting', 8 => 'SolvedClosed', 9 => 'Deleted')),
304  'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>900),
305  );
306  // END MODULEBUILDER PROPERTIES
307 
308 
314  public function __construct($db)
315  {
316  global $conf;
317 
318  $this->db = $db;
319 
320  $this->statuts_short = array(
321  self::STATUS_NOT_READ => 'Unread',
322  self::STATUS_READ => 'Read',
323  self::STATUS_ASSIGNED => 'Assigned',
324  self::STATUS_IN_PROGRESS => 'InProgress',
325  self::STATUS_WAITING => 'OnHold',
326  self::STATUS_NEED_MORE_INFO => 'NeedMoreInformationShort',
327  self::STATUS_CLOSED => 'SolvedClosed',
328  self::STATUS_CANCELED => 'Canceled'
329  );
330  $this->statuts = array(
331  self::STATUS_NOT_READ => 'Unread',
332  self::STATUS_READ => 'Read',
333  self::STATUS_ASSIGNED => 'Assigned',
334  self::STATUS_IN_PROGRESS => 'InProgress',
335  self::STATUS_WAITING => 'OnHold',
336  self::STATUS_NEED_MORE_INFO => 'NeedMoreInformation',
337  self::STATUS_CLOSED => 'SolvedClosed',
338  self::STATUS_CANCELED => 'Canceled'
339  );
340  }
341 
348  private function verify()
349  {
350  $this->errors = array();
351 
352  $result = 0;
353 
354  // Clean parameters
355  if (isset($this->ref)) {
356  $this->ref = trim($this->ref);
357  }
358 
359  if (isset($this->track_id)) {
360  $this->track_id = trim($this->track_id);
361  }
362 
363  if (isset($this->fk_soc)) {
364  $this->fk_soc = (int) $this->fk_soc;
365  }
366 
367  if (isset($this->fk_project)) {
368  $this->fk_project = (int) $this->fk_project;
369  }
370 
371  if (isset($this->origin_email)) {
372  $this->origin_email = trim($this->origin_email);
373  }
374 
375  if (isset($this->fk_user_create)) {
376  $this->fk_user_create = (int) $this->fk_user_create;
377  }
378 
379  if (isset($this->fk_user_assign)) {
380  $this->fk_user_assign = (int) $this->fk_user_assign;
381  }
382 
383  if (isset($this->subject)) {
384  $this->subject = trim($this->subject);
385  }
386 
387  if (isset($this->message)) {
388  $this->message = trim($this->message);
389  }
390 
391  if (isset($this->fk_statut)) {
392  $this->fk_statut = (int) $this->fk_statut;
393  }
394 
395  if (isset($this->resolution)) {
396  $this->resolution = trim($this->resolution);
397  }
398 
399  if (isset($this->progress)) {
400  $this->progress = trim($this->progress);
401  }
402 
403  if (isset($this->timing)) {
404  $this->timing = trim($this->timing);
405  }
406 
407  if (isset($this->type_code)) {
408  $this->type_code = trim($this->type_code);
409  }
410 
411  if (isset($this->category_code)) {
412  $this->category_code = trim($this->category_code);
413  }
414 
415  if (isset($this->severity_code)) {
416  $this->severity_code = trim($this->severity_code);
417  }
418 
419  if (empty($this->ref)) {
420  $this->errors[] = 'ErrorTicketRefRequired';
421  dol_syslog(get_class($this)."::create error -1 ref null", LOG_ERR);
422  $result = -1;
423  }
424 
425  return $result;
426  }
427 
435  public function create($user, $notrigger = 0)
436  {
437  global $conf, $langs;
438  $error = 0;
439 
440  // Clean parameters
441  $this->datec = dol_now();
442  if (empty($this->track_id)) {
443  $this->track_id = generate_random_id(16);
444  }
445 
446  // Check more parameters
447  // If error, this->errors[] is filled
448  $result = $this->verify();
449 
450  if ($result >= 0) {
451  // Insert request
452  $sql = "INSERT INTO ".MAIN_DB_PREFIX."ticket(";
453  $sql .= "ref,";
454  $sql .= "track_id,";
455  $sql .= "fk_soc,";
456  $sql .= "fk_project,";
457  $sql .= "origin_email,";
458  $sql .= "fk_user_create,";
459  $sql .= "fk_user_assign,";
460  $sql .= "email_msgid,";
461  $sql .= "email_date,";
462  $sql .= "subject,";
463  $sql .= "message,";
464  $sql .= "fk_statut,";
465  $sql .= "resolution,";
466  $sql .= "progress,";
467  $sql .= "timing,";
468  $sql .= "type_code,";
469  $sql .= "category_code,";
470  $sql .= "severity_code,";
471  $sql .= "datec,";
472  $sql .= "date_read,";
473  $sql .= "date_close,";
474  $sql .= "entity,";
475  $sql .= "notify_tiers_at_create,";
476  $sql .= "ip";
477  $sql .= ") VALUES (";
478  $sql .= " ".(!isset($this->ref) ? '' : "'".$this->db->escape($this->ref)."'").",";
479  $sql .= " ".(!isset($this->track_id) ? 'NULL' : "'".$this->db->escape($this->track_id)."'").",";
480  $sql .= " ".($this->fk_soc > 0 ? $this->db->escape($this->fk_soc) : "null").",";
481  $sql .= " ".($this->fk_project > 0 ? $this->db->escape($this->fk_project) : "null").",";
482  $sql .= " ".(!isset($this->origin_email) ? 'NULL' : "'".$this->db->escape($this->origin_email)."'").",";
483  $sql .= " ".($this->fk_user_create > 0 ? $this->fk_user_create : ($user->id > 0 ? $user->id : 'NULL')).",";
484  $sql .= " ".($this->fk_user_assign > 0 ? $this->fk_user_assign : 'NULL').",";
485  $sql .= " ".(empty($this->email_msgid) ? 'NULL' : "'".$this->db->escape($this->email_msgid)."'").",";
486  $sql .= " ".(empty($this->email_date) ? 'NULL' : "'".$this->db->idate($this->email_date)."'").",";
487  $sql .= " ".(!isset($this->subject) ? 'NULL' : "'".$this->db->escape($this->subject)."'").",";
488  $sql .= " ".(!isset($this->message) ? 'NULL' : "'".$this->db->escape($this->message)."'").",";
489  $sql .= " ".(!isset($this->fk_statut) ? '0' : "'".$this->db->escape($this->fk_statut)."'").",";
490  $sql .= " ".(!isset($this->resolution) ? 'NULL' : "'".$this->db->escape($this->resolution)."'").",";
491  $sql .= " ".(!isset($this->progress) ? '0' : "'".$this->db->escape($this->progress)."'").",";
492  $sql .= " ".(!isset($this->timing) ? 'NULL' : "'".$this->db->escape($this->timing)."'").",";
493  $sql .= " ".(!isset($this->type_code) ? 'NULL' : "'".$this->db->escape($this->type_code)."'").",";
494  $sql .= " ".(empty($this->category_code) || $this->category_code == '-1' ? 'NULL' : "'".$this->db->escape($this->category_code)."'").",";
495  $sql .= " ".(!isset($this->severity_code) ? 'NULL' : "'".$this->db->escape($this->severity_code)."'").",";
496  $sql .= " ".(!isset($this->datec) || dol_strlen($this->datec) == 0 ? 'NULL' : "'".$this->db->idate($this->datec)."'").",";
497  $sql .= " ".(!isset($this->date_read) || dol_strlen($this->date_read) == 0 ? 'NULL' : "'".$this->db->idate($this->date_read)."'").",";
498  $sql .= " ".(!isset($this->date_close) || dol_strlen($this->date_close) == 0 ? 'NULL' : "'".$this->db->idate($this->date_close)."'")."";
499  $sql .= ", ".((int) $conf->entity);
500  $sql .= ", ".(!isset($this->notify_tiers_at_create) ? '1' : "'".$this->db->escape($this->notify_tiers_at_create)."'");
501  $sql .= ", ".(!isset($this->ip) ? 'NULL' : "'".$this->db->escape($this->ip)."'");
502  $sql .= ")";
503 
504  $this->db->begin();
505 
506  dol_syslog(get_class($this)."::create", LOG_DEBUG);
507  $resql = $this->db->query($sql);
508  if (!$resql) {
509  $error++;
510  $this->errors[] = "Error ".$this->db->lasterror();
511  }
512 
513  if (!$error) {
514  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."ticket");
515  }
516 
517  if (!$error && !empty($conf->global->TICKET_ADD_AUTHOR_AS_CONTACT)) {
518  // add creator as contributor
519  if ($this->add_contact($user->id, 'CONTRIBUTOR', 'internal') < 0) {
520  $error++;
521  }
522  }
523 
524  if (!$error && $this->fk_user_assign > 0) {
525  if ($this->add_contact($this->fk_user_assign, 'SUPPORTTEC', 'internal') < 0) {
526  $error++;
527  }
528  }
529 
530 
531  //Update extrafield
532  if (!$error) {
533  $result = $this->insertExtraFields();
534  if ($result < 0) {
535  $error++;
536  }
537  }
538 
539  if (!$error && !$notrigger) {
540  // Call trigger
541  $result = $this->call_trigger('TICKET_CREATE', $user);
542  if ($result < 0) {
543  $error++;
544  }
545  // End call triggers
546  }
547 
548  // Commit or rollback
549  if ($error) {
550  foreach ($this->errors as $errmsg) {
551  dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
552  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
553  }
554  $this->db->rollback();
555  return -1 * $error;
556  } else {
557  $this->db->commit();
558  return $this->id;
559  }
560  } else {
561  $this->db->rollback();
562  dol_syslog(get_class($this)."::Create fails verify ".join(',', $this->errors), LOG_WARNING);
563  return -3;
564  }
565  }
566 
576  public function fetch($id = '', $ref = '', $track_id = '', $email_msgid = '')
577  {
578  global $langs;
579 
580  // Check parameters
581  if (empty($id) && empty($ref) && empty($track_id) && empty($email_msgid)) {
582  $this->error = 'ErrorWrongParameters';
583  dol_print_error(get_class($this)."::fetch ".$this->error);
584  return -1;
585  }
586 
587  $sql = "SELECT";
588  $sql .= " t.rowid,";
589  $sql .= " t.entity,";
590  $sql .= " t.ref,";
591  $sql .= " t.track_id,";
592  $sql .= " t.fk_soc,";
593  $sql .= " t.fk_project,";
594  $sql .= " t.origin_email,";
595  $sql .= " t.fk_user_create,";
596  $sql .= " t.fk_user_assign,";
597  $sql .= " t.email_msgid,";
598  $sql .= " t.email_date,";
599  $sql .= " t.subject,";
600  $sql .= " t.message,";
601  $sql .= " t.fk_statut as status,";
602  $sql .= " t.resolution,";
603  $sql .= " t.progress,";
604  $sql .= " t.timing,";
605  $sql .= " t.type_code,";
606  $sql .= " t.category_code,";
607  $sql .= " t.severity_code,";
608  $sql .= " t.datec,";
609  $sql .= " t.date_read,";
610  $sql .= " t.date_last_msg_sent,";
611  $sql .= " t.date_close,";
612  $sql .= " t.tms,";
613  $sql .= " t.ip,";
614  $sql .= " type.label as type_label, category.label as category_label, severity.label as severity_label";
615  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
616  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code=t.type_code";
617  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code=t.category_code";
618  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_severity as severity ON severity.code=t.severity_code";
619 
620  if ($id) {
621  $sql .= " WHERE t.rowid = ".((int) $id);
622  } else {
623  $sql .= " WHERE t.entity IN (".getEntity($this->element, 1).")";
624  if (!empty($ref)) {
625  $sql .= " AND t.ref = '".$this->db->escape($ref)."'";
626  } elseif ($track_id) {
627  $sql .= " AND t.track_id = '".$this->db->escape($track_id)."'";
628  } else {
629  $sql .= " AND t.email_msgid = '".$this->db->escape($email_msgid)."'";
630  }
631  }
632 
633  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
634  $resql = $this->db->query($sql);
635  if ($resql) {
636  if ($this->db->num_rows($resql)) {
637  $obj = $this->db->fetch_object($resql);
638 
639  $this->id = $obj->rowid;
640  $this->entity = $obj->entity;
641  $this->ref = $obj->ref;
642  $this->track_id = $obj->track_id;
643  $this->fk_soc = $obj->fk_soc;
644  $this->socid = $obj->fk_soc; // for fetch_thirdparty() method
645  $this->fk_project = $obj->fk_project;
646  $this->origin_email = $obj->origin_email;
647  $this->fk_user_create = $obj->fk_user_create;
648  $this->fk_user_assign = $obj->fk_user_assign;
649  $this->email_msgid = $obj->email_msgid;
650  $this->email_date = $this->db->jdate($obj->email_date);
651  $this->subject = $obj->subject;
652  $this->message = $obj->message;
653  $this->ip = $obj->ip;
654 
655  $this->status = $obj->status;
656  $this->fk_statut = $this->status; // For backward compatibility
657 
658  $this->resolution = $obj->resolution;
659  $this->progress = $obj->progress;
660  $this->timing = $obj->timing;
661 
662  $this->type_code = $obj->type_code;
663  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
664  $label_type = ($langs->trans("TicketTypeShort".$obj->type_code) != ("TicketTypeShort".$obj->type_code) ? $langs->trans("TicketTypeShort".$obj->type_code) : ($obj->type_label != '-' ? $obj->type_label : ''));
665  $this->type_label = $label_type;
666 
667  $this->category_code = $obj->category_code;
668  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
669  $label_category = ($langs->trans("TicketCategoryShort".$obj->category_code) != ("TicketCategoryShort".$obj->category_code) ? $langs->trans("TicketCategoryShort".$obj->category_code) : ($obj->category_label != '-' ? $obj->category_label : ''));
670  $this->category_label = $label_category;
671 
672  $this->severity_code = $obj->severity_code;
673  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
674  $label_severity = ($langs->trans("TicketSeverityShort".$obj->severity_code) != ("TicketSeverityShort".$obj->severity_code) ? $langs->trans("TicketSeverityShort".$obj->severity_code) : ($obj->severity_label != '-' ? $obj->severity_label : ''));
675  $this->severity_label = $label_severity;
676 
677  $this->datec = $this->db->jdate($obj->datec);
678  $this->date_creation = $this->db->jdate($obj->datec);
679  $this->date_read = $this->db->jdate($obj->date_read);
680  $this->date_validation = $this->db->jdate($obj->date_read);
681  $this->date_last_msg_sent = $this->db->jdate($obj->date_last_msg_sent);
682  $this->date_close = $this->db->jdate($obj->date_close);
683  $this->tms = $this->db->jdate($obj->tms);
684  $this->date_modification = $this->db->jdate($obj->tms);
685 
686  $this->fetch_optionals();
687 
688  $this->db->free($resql);
689  return 1;
690  } else {
691  return 0;
692  }
693  } else {
694  $this->error = "Error ".$this->db->lasterror();
695  dol_syslog(get_class($this)."::fetch ".$this->error, LOG_ERR);
696  return -1;
697  }
698  }
699 
713  public function fetchAll($user, $sortorder = 'ASC', $sortfield = 't.datec', $limit = '', $offset = 0, $arch = '', $filter = '')
714  {
715  global $langs;
716 
717  $extrafields = new ExtraFields($this->db);
718 
719  // fetch optionals attributes and labels
720  $extrafields->fetch_name_optionals_label($this->table_element);
721 
722  $sql = "SELECT";
723  $sql .= " t.rowid,";
724  $sql .= " t.ref,";
725  $sql .= " t.track_id,";
726  $sql .= " t.fk_soc,";
727  $sql .= " t.fk_project,";
728  $sql .= " t.origin_email,";
729  $sql .= " t.fk_user_create, uc.lastname as user_create_lastname, uc.firstname as user_create_firstname,";
730  $sql .= " t.fk_user_assign, ua.lastname as user_assign_lastname, ua.firstname as user_assign_firstname,";
731  $sql .= " t.subject,";
732  $sql .= " t.message,";
733  $sql .= " t.fk_statut,";
734  $sql .= " t.resolution,";
735  $sql .= " t.progress,";
736  $sql .= " t.timing,";
737  $sql .= " t.type_code,";
738  $sql .= " t.category_code,";
739  $sql .= " t.severity_code,";
740  $sql .= " t.datec,";
741  $sql .= " t.date_read,";
742  $sql .= " t.date_last_msg_sent,";
743  $sql .= " t.date_close,";
744  $sql .= " t.tms";
745  $sql .= ", type.label as type_label, category.label as category_label, severity.label as severity_label";
746  // Add fields for extrafields
747  foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) {
748  $sql .= ($extrafields->attributes[$this->table_element]['type'][$key] != 'separate' ? ",ef.".$key." as options_".$key : '');
749  }
750  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
751  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_type as type ON type.code=t.type_code";
752  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_category as category ON category.code=t.category_code";
753  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_ticket_severity as severity ON severity.code=t.severity_code";
754  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid=t.fk_soc";
755  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as uc ON uc.rowid=t.fk_user_create";
756  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as ua ON ua.rowid=t.fk_user_assign";
757  if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label'])) {
758  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."ticket_extrafields as ef on (t.rowid = ef.fk_object)";
759  }
760  if (empty($user->rights->societe->client->voir) && !$user->socid) {
761  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
762  }
763 
764  $sql .= " WHERE t.entity IN (".getEntity('ticket').")";
765 
766  // Manage filter
767  if (!empty($filter)) {
768  foreach ($filter as $key => $value) {
769  if (strpos($key, 'date')) { // To allow $filter['YEAR(s.dated)']=>$year
770  $sql .= " AND ".$key." = '".$this->db->escape($value)."'";
771  } elseif (($key == 't.fk_user_assign') || ($key == 't.type_code') || ($key == 't.category_code') || ($key == 't.severity_code') || ($key == 't.fk_soc')) {
772  $sql .= " AND ".$key." = '".$this->db->escape($value)."'";
773  } elseif ($key == 't.fk_statut') {
774  if (is_array($value) && count($value) > 0) {
775  $sql .= " AND ".$key." IN (".$this->db->sanitize(implode(',', $value)).")";
776  } else {
777  $sql .= " AND ".$key.' = '.((int) $value);
778  }
779  } else {
780  $sql .= " AND ".$key." LIKE '%".$this->db->escape($value)."%'";
781  }
782  }
783  }
784  if (empty($user->rights->societe->client->voir) && !$user->socid) {
785  $sql .= " AND t.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
786  } elseif ($user->socid) {
787  $sql .= " AND t.fk_soc = ".((int) $user->socid);
788  }
789 
790  $sql .= $this->db->order($sortfield, $sortorder);
791  if (!empty($limit)) {
792  $sql .= $this->db->plimit($limit + 1, $offset);
793  }
794 
795  dol_syslog(get_class($this)."::fetchAll", LOG_DEBUG);
796  $resql = $this->db->query($sql);
797 
798  if ($resql) {
799  $this->lines = array();
800 
801  $num = $this->db->num_rows($resql);
802  $i = 0;
803 
804  if ($num) {
805  while ($i < $num) {
806  $obj = $this->db->fetch_object($resql);
807 
808  $line = new TicketsLine();
809 
810  $line->id = $obj->rowid;
811  $line->rowid = $obj->rowid;
812  $line->ref = $obj->ref;
813  $line->track_id = $obj->track_id;
814  $line->fk_soc = $obj->fk_soc;
815  $line->fk_project = $obj->fk_project;
816  $line->origin_email = $obj->origin_email;
817 
818  $line->fk_user_create = $obj->fk_user_create;
819  $line->user_create_lastname = $obj->user_create_lastname;
820  $line->user_create_firstname = $obj->user_create_firstname;
821 
822  $line->fk_user_assign = $obj->fk_user_assign;
823  $line->user_assign_lastname = $obj->user_assign_lastname;
824  $line->user_assign_firstname = $obj->user_assign_firstname;
825 
826  $line->subject = $obj->subject;
827  $line->message = $obj->message;
828  $line->fk_statut = $obj->fk_statut;
829  $line->resolution = $obj->resolution;
830  $line->progress = $obj->progress;
831  $line->timing = $obj->timing;
832 
833  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
834  $label_type = ($langs->trans("TicketTypeShort".$obj->type_code) != ("TicketTypeShort".$obj->type_code) ? $langs->trans("TicketTypeShort".$obj->type_code) : ($obj->type_label != '-' ? $obj->type_label : ''));
835  $line->type_label = $label_type;
836 
837  $this->category_code = $obj->category_code;
838  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
839  $label_category = ($langs->trans("TicketCategoryShort".$obj->category_code) != ("TicketCategoryShort".$obj->category_code) ? $langs->trans("TicketCategoryShort".$obj->category_code) : ($obj->category_label != '-' ? $obj->category_label : ''));
840  $line->category_label = $label_category;
841 
842  $this->severity_code = $obj->severity_code;
843  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
844  $label_severity = ($langs->trans("TicketSeverityShort".$obj->severity_code) != ("TicketSeverityShort".$obj->severity_code) ? $langs->trans("TicketSeverityShort".$obj->severity_code) : ($obj->severity_label != '-' ? $obj->severity_label : ''));
845  $line->severity_label = $label_severity;
846 
847  $line->datec = $this->db->jdate($obj->datec);
848  $line->date_read = $this->db->jdate($obj->date_read);
849  $line->date_last_msg_sent = $this->db->jdate($obj->date_last_msg_sent);
850  $line->date_close = $this->db->jdate($obj->date_close);
851 
852  // Extra fields
853  if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label'])) {
854  foreach ($extrafields->attributes[$this->table_element]['label'] as $key => $val) {
855  $tmpkey = 'options_'.$key;
856  $line->{$tmpkey} = $obj->$tmpkey;
857  }
858  }
859 
860  $this->lines[$i] = $line;
861  $i++;
862  }
863  }
864  $this->db->free($resql);
865  return $num;
866  } else {
867  $this->error = "Error ".$this->db->lasterror();
868  dol_syslog(get_class($this)."::fetchAll ".$this->error, LOG_ERR);
869  return -1;
870  }
871  }
872 
880  public function update($user = 0, $notrigger = 0)
881  {
882  global $conf, $langs, $hookmanager;
883  $error = 0;
884 
885  // $this->oldcopy should have been set by the caller of update (here properties were already modified)
886  //if (empty($this->oldcopy)) {
887  // $this->oldcopy = dol_clone($this);
888  //}
889 
890  // Clean parameters
891  if (isset($this->ref)) {
892  $this->ref = trim($this->ref);
893  }
894 
895  if (isset($this->track_id)) {
896  $this->track_id = trim($this->track_id);
897  }
898 
899  if (isset($this->fk_soc)) {
900  $this->fk_soc = (int) $this->fk_soc;
901  }
902 
903  if (isset($this->fk_project)) {
904  $this->fk_project = (int) $this->fk_project;
905  }
906 
907  if (isset($this->origin_email)) {
908  $this->origin_email = trim($this->origin_email);
909  }
910 
911  if (isset($this->fk_user_create)) {
912  $this->fk_user_create = (int) $this->fk_user_create;
913  }
914 
915  if (isset($this->fk_user_assign)) {
916  $this->fk_user_assign = (int) $this->fk_user_assign;
917  }
918 
919  if (isset($this->subject)) {
920  $this->subject = trim($this->subject);
921  }
922 
923  if (isset($this->message)) {
924  $this->message = trim($this->message);
925  }
926 
927  if (isset($this->fk_statut)) {
928  $this->fk_statut = (int) $this->fk_statut;
929  }
930 
931  if (isset($this->resolution)) {
932  $this->resolution = trim($this->resolution);
933  }
934 
935  if (isset($this->progress)) {
936  $this->progress = trim($this->progress);
937  }
938 
939  if (isset($this->timing)) {
940  $this->timing = trim($this->timing);
941  }
942 
943  if (isset($this->type_code)) {
944  $this->timing = trim($this->type_code);
945  }
946 
947  if (isset($this->category_code)) {
948  $this->timing = trim($this->category_code);
949  }
950 
951  if (isset($this->severity_code)) {
952  $this->timing = trim($this->severity_code);
953  }
954 
955  // Check parameters
956  // Put here code to add a control on parameters values
957  // Update request
958  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket SET";
959  $sql .= " ref=".(isset($this->ref) ? "'".$this->db->escape($this->ref)."'" : "").",";
960  $sql .= " track_id=".(isset($this->track_id) ? "'".$this->db->escape($this->track_id)."'" : "null").",";
961  $sql .= " fk_soc=".(isset($this->fk_soc) ? "'".$this->db->escape($this->fk_soc)."'" : "null").",";
962  $sql .= " fk_project=".(isset($this->fk_project) ? "'".$this->db->escape($this->fk_project)."'" : "null").",";
963  $sql .= " origin_email=".(isset($this->origin_email) ? "'".$this->db->escape($this->origin_email)."'" : "null").",";
964  $sql .= " fk_user_create=".(isset($this->fk_user_create) ? $this->fk_user_create : "null").",";
965  $sql .= " fk_user_assign=".(isset($this->fk_user_assign) ? $this->fk_user_assign : "null").",";
966  $sql .= " subject=".(isset($this->subject) ? "'".$this->db->escape($this->subject)."'" : "null").",";
967  $sql .= " message=".(isset($this->message) ? "'".$this->db->escape($this->message)."'" : "null").",";
968  $sql .= " fk_statut=".(isset($this->fk_statut) ? $this->fk_statut : "null").",";
969  $sql .= " resolution=".(isset($this->resolution) ? $this->resolution : "null").",";
970  $sql .= " progress=".(isset($this->progress) ? "'".$this->db->escape($this->progress)."'" : "null").",";
971  $sql .= " timing=".(isset($this->timing) ? "'".$this->db->escape($this->timing)."'" : "null").",";
972  $sql .= " type_code=".(isset($this->type_code) ? "'".$this->db->escape($this->type_code)."'" : "null").",";
973  $sql .= " category_code=".(isset($this->category_code) ? "'".$this->db->escape($this->category_code)."'" : "null").",";
974  $sql .= " severity_code=".(isset($this->severity_code) ? "'".$this->db->escape($this->severity_code)."'" : "null").",";
975  $sql .= " datec=".(dol_strlen($this->datec) != 0 ? "'".$this->db->idate($this->datec)."'" : 'null').",";
976  $sql .= " date_read=".(dol_strlen($this->date_read) != 0 ? "'".$this->db->idate($this->date_read)."'" : 'null').",";
977  $sql .= " date_last_msg_sent=".(dol_strlen($this->date_last_msg_sent) != 0 ? "'".$this->db->idate($this->date_last_msg_sent)."'" : 'null').",";
978  $sql .= " date_close=".(dol_strlen($this->date_close) != 0 ? "'".$this->db->idate($this->date_close)."'" : 'null')."";
979  $sql .= " WHERE rowid=".((int) $this->id);
980 
981  $this->db->begin();
982 
983  $resql = $this->db->query($sql);
984  if (!$resql) {
985  $error++;
986  $this->errors[] = "Error ".$this->db->lasterror();
987  }
988 
989  if (!$error) {
990  // Update extrafields
991  $result = $this->insertExtraFields();
992  if ($result < 0) {
993  $error++;
994  }
995  }
996 
997  if (!$error && !$notrigger) {
998  // Call trigger
999  $result = $this->call_trigger('TICKET_MODIFY', $user);
1000  if ($result < 0) {
1001  $error++;
1002  }
1003  // End call triggers
1004  }
1005 
1006  // Commit or rollback
1007  if ($error) {
1008  foreach ($this->errors as $errmsg) {
1009  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1010  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1011  }
1012  $this->db->rollback();
1013  return -1 * $error;
1014  } else {
1015  $this->db->commit();
1016  return 1;
1017  }
1018  }
1019 
1027  public function delete($user, $notrigger = 0)
1028  {
1029  global $conf, $langs;
1030  $error = 0;
1031 
1032  $this->db->begin();
1033 
1034  if (!$error) {
1035  if (!$notrigger) {
1036  // Call trigger
1037  $result = $this->call_trigger('TICKET_DELETE', $user);
1038  if ($result < 0) {
1039  $error++;
1040  }
1041  // End call triggers
1042  }
1043  }
1044 
1045  if (!$error) {
1046  // Delete linked contacts
1047  $res = $this->delete_linked_contact();
1048  if ($res < 0) {
1049  dol_syslog(get_class($this)."::delete error", LOG_ERR);
1050  $error++;
1051  }
1052  }
1053 
1054  if (!$error) {
1055  // Delete linked object
1056  $res = $this->deleteObjectLinked();
1057  if ($res < 0) {
1058  $error++;
1059  }
1060  }
1061 
1062  // Removed extrafields
1063  if (!$error) {
1064  $result = $this->deleteExtraFields();
1065  if ($result < 0) {
1066  $error++;
1067  dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
1068  }
1069  }
1070 
1071  // Delete all child tables
1072 
1073  if (!$error) {
1074  $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_ticket";
1075  $sql .= " WHERE fk_ticket = ".(int) $this->id;
1076 
1077  $result = $this->db->query($sql);
1078  if (!$result) {
1079  $error++;
1080  $this->errors[] = $this->db->lasterror();
1081  }
1082  }
1083 
1084  if (!$error) {
1085  $sql = "DELETE FROM ".MAIN_DB_PREFIX."ticket";
1086  $sql .= " WHERE rowid=".((int) $this->id);
1087 
1088  dol_syslog(get_class($this)."::delete sql=".$sql);
1089  $resql = $this->db->query($sql);
1090  if (!$resql) {
1091  $error++;
1092  $this->errors[] = "Error ".$this->db->lasterror();
1093  }
1094  }
1095 
1096  // Commit or rollback
1097  if ($error) {
1098  foreach ($this->errors as $errmsg) {
1099  dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
1100  $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1101  }
1102  $this->db->rollback();
1103  return -1 * $error;
1104  } else {
1105  $this->db->commit();
1106  return 1;
1107  }
1108  }
1109 
1117  public function createFromClone(User $user, $fromid)
1118  {
1119  $error = 0;
1120 
1121  $object = new Ticket($this->db);
1122 
1123  $this->db->begin();
1124 
1125  // Load source object
1126  $object->fetch($fromid);
1127  $object->id = 0;
1128  $object->statut = 0;
1129 
1130  // Clear fields
1131  // ...
1132  // Create clone
1133  $object->context['createfromclone'] = 'createfromclone';
1134  $result = $object->create($user);
1135 
1136  // Other options
1137  if ($result < 0) {
1138  $this->error = $object->error;
1139  $error++;
1140  }
1141 
1142  if (!$error) {
1143  }
1144 
1145  unset($object->context['createfromclone']);
1146 
1147  // End
1148  if (!$error) {
1149  $this->db->commit();
1150  return $object->id;
1151  } else {
1152  $this->db->rollback();
1153  return -1;
1154  }
1155  }
1156 
1163  public function initAsSpecimen()
1164  {
1165  $this->id = 0;
1166  $this->entity = 1;
1167  $this->ref = 'TI0501-001';
1168  $this->track_id = 'XXXXaaaa';
1169  $this->origin_email = 'email@email.com';
1170  $this->fk_project = 1;
1171  $this->fk_user_create = 1;
1172  $this->fk_user_assign = 1;
1173  $this->subject = 'Subject of ticket';
1174  $this->message = 'Message of ticket';
1175  $this->status = 0;
1176  $this->resolution = '1';
1177  $this->progress = '10';
1178  //$this->timing = '30';
1179  $this->type_code = 'TYPECODE';
1180  $this->category_code = 'CATEGORYCODE';
1181  $this->severity_code = 'SEVERITYCODE';
1182  $this->datec = '';
1183  $this->date_read = '';
1184  $this->date_last_msg_sent = '';
1185  $this->date_close = '';
1186  $this->tms = '';
1187  return 1;
1188  }
1189 
1196  public function printSelectStatus($selected = "")
1197  {
1198  print Form::selectarray('search_fk_statut', $this->statuts_short, $selected, $show_empty = 1, $key_in_label = 0, $value_as_key = 0, $option = '', $translate = 1, $maxlen = 0, $disabled = 0, $sort = '', $morecss = '');
1199  }
1200 
1201 
1207  public function loadCacheTypesTickets()
1208  {
1209  global $langs;
1210 
1211  if (!empty($this->cache_types_tickets) && count($this->cache_types_tickets)) {
1212  return 0;
1213  }
1214  // Cache deja charge
1215 
1216  $sql = "SELECT rowid, code, label, use_default, pos, description";
1217  $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_type";
1218  $sql .= " WHERE active > 0";
1219  $sql .= " ORDER BY pos";
1220  dol_syslog(get_class($this)."::load_cache_type_tickets", LOG_DEBUG);
1221  $resql = $this->db->query($sql);
1222  if ($resql) {
1223  $num = $this->db->num_rows($resql);
1224  $i = 0;
1225  while ($i < $num) {
1226  $obj = $this->db->fetch_object($resql);
1227  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
1228  $label = ($langs->trans("TicketTypeShort".$obj->code) != ("TicketTypeShort".$obj->code) ? $langs->trans("TicketTypeShort".$obj->code) : ($obj->label != '-' ? $obj->label : ''));
1229  $this->cache_types_tickets[$obj->rowid]['code'] = $obj->code;
1230  $this->cache_types_tickets[$obj->rowid]['label'] = $label;
1231  $this->cache_types_tickets[$obj->rowid]['use_default'] = $obj->use_default;
1232  $this->cache_types_tickets[$obj->rowid]['pos'] = $obj->pos;
1233  $i++;
1234  }
1235  return $num;
1236  } else {
1237  dol_print_error($this->db);
1238  return -1;
1239  }
1240  }
1241 
1248  public function loadCacheCategoriesTickets($publicgroup = -1)
1249  {
1250  global $conf, $langs;
1251 
1252  if ($publicgroup == -1 && !empty($this->cache_category_ticket) && count($this->cache_category_tickets)) {
1253  // Cache already loaded
1254  return 0;
1255  }
1256 
1257  $sql = "SELECT rowid, code, label, use_default, pos, description, public, active, force_severity, fk_parent";
1258  $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_category";
1259  $sql .= " WHERE active > 0 AND entity = ".((int) $conf->entity);
1260  if ($publicgroup > -1) {
1261  $sql .= " AND public = ".((int) $publicgroup);
1262  }
1263  $sql .= " ORDER BY pos";
1264 
1265  dol_syslog(get_class($this)."::load_cache_categories_tickets", LOG_DEBUG);
1266 
1267  $resql = $this->db->query($sql);
1268  if ($resql) {
1269  $num = $this->db->num_rows($resql);
1270  $i = 0;
1271  while ($i < $num) {
1272  $obj = $this->db->fetch_object($resql);
1273  $this->cache_category_tickets[$obj->rowid]['code'] = $obj->code;
1274  $this->cache_category_tickets[$obj->rowid]['use_default'] = $obj->use_default;
1275  $this->cache_category_tickets[$obj->rowid]['pos'] = $obj->pos;
1276  $this->cache_category_tickets[$obj->rowid]['public'] = $obj->public;
1277  $this->cache_category_tickets[$obj->rowid]['active'] = $obj->active;
1278  $this->cache_category_tickets[$obj->rowid]['force_severity'] = $obj->force_severity;
1279  $this->cache_category_tickets[$obj->rowid]['fk_parent'] = $obj->fk_parent;
1280 
1281  // If translation exists, we use it to store already translated string.
1282  // Warning: You should not use this and recompute the translated string into caller code to get the value into expected language
1283  $label = ($langs->trans("TicketCategoryShort".$obj->code) != ("TicketCategoryShort".$obj->code) ? $langs->trans("TicketCategoryShort".$obj->code) : ($obj->label != '-' ? $obj->label : ''));
1284  $this->cache_category_tickets[$obj->rowid]['label'] = $label;
1285 
1286  $i++;
1287  }
1288  return $num;
1289  } else {
1290  dol_print_error($this->db);
1291  return -1;
1292  }
1293  }
1294 
1300  public function loadCacheSeveritiesTickets()
1301  {
1302  global $langs;
1303 
1304  if (!empty($this->cache_severity_tickets) && count($this->cache_severity_tickets)) {
1305  return 0;
1306  }
1307  // Cache deja charge
1308 
1309  $sql = "SELECT rowid, code, label, use_default, pos, description";
1310  $sql .= " FROM ".MAIN_DB_PREFIX."c_ticket_severity";
1311  $sql .= " WHERE active > 0";
1312  $sql .= " ORDER BY pos";
1313  dol_syslog(get_class($this)."::loadCacheSeveritiesTickets", LOG_DEBUG);
1314  $resql = $this->db->query($sql);
1315  if ($resql) {
1316  $num = $this->db->num_rows($resql);
1317  $i = 0;
1318  while ($i < $num) {
1319  $obj = $this->db->fetch_object($resql);
1320 
1321  $this->cache_severity_tickets[$obj->rowid]['code'] = $obj->code;
1322  // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut
1323  $label = ($langs->trans("TicketSeverityShort".$obj->code) != ("TicketSeverityShort".$obj->code) ? $langs->trans("TicketSeverityShort".$obj->code) : ($obj->label != '-' ? $obj->label : ''));
1324  $this->cache_severity_tickets[$obj->rowid]['label'] = $label;
1325  $this->cache_severity_tickets[$obj->rowid]['use_default'] = $obj->use_default;
1326  $this->cache_severity_tickets[$obj->rowid]['pos'] = $obj->pos;
1327  $i++;
1328  }
1329  return $num;
1330  } else {
1331  dol_print_error($this->db);
1332  return -1;
1333  }
1334  }
1335 
1336 
1343  public function getLibStatut($mode = 0)
1344  {
1345  return $this->libStatut($this->fk_statut, $mode, 0, $this->progress);
1346  }
1347 
1348 
1349  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1359  public function LibStatut($status, $mode = 0, $notooltip = 0, $progress = 0)
1360  {
1361  // phpcs:enable
1362  global $langs, $hookmanager;
1363 
1364  $labelStatus = $this->statuts[$status];
1365  $labelStatusShort = $this->statuts_short[$status];
1366 
1367  if ($status == self::STATUS_NOT_READ) {
1368  $statusType = 'status0';
1369  } elseif ($status == self::STATUS_READ) {
1370  $statusType = 'status1';
1371  } elseif ($status == self::STATUS_ASSIGNED) {
1372  $statusType = 'status2';
1373  } elseif ($status == self::STATUS_IN_PROGRESS) {
1374  $statusType = 'status4';
1375  } elseif ($status == self::STATUS_WAITING) {
1376  $statusType = 'status7';
1377  } elseif ($status == self::STATUS_NEED_MORE_INFO) {
1378  $statusType = 'status3';
1379  } elseif ($status == self::STATUS_CANCELED) {
1380  $statusType = 'status9';
1381  } elseif ($status == self::STATUS_CLOSED) {
1382  $statusType = 'status6';
1383  } else {
1384  $labelStatus = 'Unknown';
1385  $labelStatusShort = 'Unknown';
1386  $statusType = 'status0';
1387  $mode = 0;
1388  }
1389 
1390  $parameters = array(
1391  'status' => $status,
1392  'mode' => $mode,
1393  );
1394 
1395  // Note that $action and $object may have been modified by hook
1396  $reshook = $hookmanager->executeHooks('LibStatut', $parameters, $this);
1397 
1398  if ($reshook > 0) {
1399  return $hookmanager->resPrint;
1400  }
1401 
1402  $params = array();
1403  if ($notooltip) {
1404  $params = array('tooltip' => 'no');
1405  }
1406 
1407  $labelStatus = $langs->transnoentitiesnoconv($labelStatus);
1408  $labelStatusShort = $langs->transnoentitiesnoconv($labelStatusShort);
1409 
1410  if ($status == self::STATUS_IN_PROGRESS && $progress > 0) {
1411  $labelStatus .= ' ('.round($progress).'%)';
1412  $labelStatusShort .= ' ('.round($progress).'%)';
1413  }
1414 
1415  return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode, '', $params);
1416  }
1417 
1418 
1429  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
1430  {
1431  global $db, $conf, $langs;
1432  global $dolibarr_main_authentication, $dolibarr_main_demo;
1433  global $menumanager;
1434 
1435  if (!empty($conf->dol_no_mouse_hover)) {
1436  $notooltip = 1; // Force disable tooltips
1437  }
1438 
1439  $result = '';
1440 
1441  $label = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Ticket").'</u>';
1442  $label .= ' '.$this->getLibStatut(4);
1443  $label .= '<br>';
1444  $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref.'<br>';
1445  $label .= '<b>'.$langs->trans('TicketTrackId').':</b> '.$this->track_id.'<br>';
1446  $label .= '<b>'.$langs->trans('Subject').':</b> '.$this->subject;
1447  if ($this->date_creation) {
1448  $label .= '<br><b>'.$langs->trans('DateCreation').':</b> '.$this->date_creation;
1449  }
1450  if ($this->date_modification) {
1451  $label .= '<br><b>'.$langs->trans('DateModification').':</b> '.$this->date_modification;
1452  }
1453  $url = DOL_URL_ROOT.'/ticket/card.php?id='.$this->id;
1454 
1455  if ($option != 'nolink') {
1456  // Add param to save lastsearch_values or not
1457  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1458  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1459  $add_save_lastsearch_values = 1;
1460  }
1461  if ($add_save_lastsearch_values) {
1462  $url .= '&save_lastsearch_values=1';
1463  }
1464  }
1465 
1466  $linkclose = '';
1467  if (empty($notooltip)) {
1468  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1469  $label = $langs->trans("ShowTicket");
1470  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
1471  }
1472  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
1473  $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
1474  } else {
1475  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
1476  }
1477 
1478  $linkstart = '<a href="'.$url.'"';
1479  $linkstart .= $linkclose.'>';
1480  $linkend = '</a>';
1481 
1482  $result .= $linkstart;
1483  if ($withpicto) {
1484  $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1485  }
1486  if ($withpicto != 2) {
1487  $result .= $this->ref;
1488  }
1489  $result .= $linkend;
1490  //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
1491 
1492  return $result;
1493  }
1494 
1495 
1503  public function markAsRead($user, $notrigger = 0)
1504  {
1505  global $conf, $langs;
1506 
1507  $error = 0;
1508 
1509  if ($this->statut != self::STATUS_CANCELED) { // no closed
1510  $this->oldcopy = dol_clone($this);
1511 
1512  $this->db->begin();
1513 
1514  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1515  $sql .= " SET fk_statut = ".Ticket::STATUS_READ.", date_read = '".$this->db->idate(dol_now())."'";
1516  $sql .= " WHERE rowid = ".((int) $this->id);
1517 
1518  dol_syslog(get_class($this)."::markAsRead");
1519  $resql = $this->db->query($sql);
1520  if ($resql) {
1521  $this->actionmsg = $langs->trans('TicketLogMesgReadBy', $this->ref, $user->getFullName($langs));
1522  $this->actionmsg2 = $langs->trans('TicketLogMesgReadBy', $this->ref, $user->getFullName($langs));
1523 
1524  if (!$error && !$notrigger) {
1525  // Call trigger
1526  $result = $this->call_trigger('TICKET_MODIFY', $user);
1527  if ($result < 0) {
1528  $error++;
1529  }
1530  // End call triggers
1531  }
1532 
1533  if (!$error) {
1534  $this->db->commit();
1535  return 1;
1536  } else {
1537  $this->db->rollback();
1538  $this->error = join(',', $this->errors);
1539  dol_syslog(get_class($this)."::markAsRead ".$this->error, LOG_ERR);
1540  return -1;
1541  }
1542  } else {
1543  $this->db->rollback();
1544  $this->error = $this->db->lasterror();
1545  dol_syslog(get_class($this)."::markAsRead ".$this->error, LOG_ERR);
1546  return -1;
1547  }
1548  }
1549  }
1550 
1559  public function assignUser($user, $id_assign_user, $notrigger = 0)
1560  {
1561  global $conf, $langs;
1562 
1563  $error = 0;
1564 
1565  $this->oldcopy = dol_clone($this);
1566 
1567  $this->db->begin();
1568 
1569  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1570  if ($id_assign_user > 0) {
1571  $sql .= " SET fk_user_assign=".((int) $id_assign_user).", fk_statut = ".Ticket::STATUS_ASSIGNED;
1572  } else {
1573  $sql .= " SET fk_user_assign=null, fk_statut = ".Ticket::STATUS_READ;
1574  }
1575  $sql .= " WHERE rowid = ".((int) $this->id);
1576 
1577  dol_syslog(get_class($this)."::assignUser sql=".$sql);
1578  $resql = $this->db->query($sql);
1579  if ($resql) {
1580  $this->fk_user_assign = $id_assign_user; // May be used by trigger
1581 
1582  if (!$notrigger) {
1583  // Call trigger
1584  $result = $this->call_trigger('TICKET_ASSIGNED', $user);
1585  if ($result < 0) {
1586  $error++;
1587  }
1588  // End call triggers
1589  }
1590 
1591  if (!$error) {
1592  $this->db->commit();
1593  return 1;
1594  } else {
1595  $this->db->rollback();
1596  $this->error = join(',', $this->errors);
1597  dol_syslog(get_class($this)."::assignUser ".$this->error, LOG_ERR);
1598  return -1;
1599  }
1600  } else {
1601  $this->db->rollback();
1602  $this->error = $this->db->lasterror();
1603  dol_syslog(get_class($this)."::assignUser ".$this->error, LOG_ERR);
1604  return -1;
1605  }
1606  }
1607 
1619  public function createTicketMessage($user, $notrigger = 0, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array(), $send_email = false)
1620  {
1621  global $conf, $langs;
1622  $error = 0;
1623 
1624  $now = dol_now();
1625 
1626  // Clean parameters
1627  if (isset($this->fk_track_id)) {
1628  $this->fk_track_id = trim($this->fk_track_id);
1629  }
1630 
1631  if (isset($this->message)) {
1632  $this->message = trim($this->message);
1633  }
1634 
1635  $this->db->begin();
1636 
1637  // Insert entry into agenda with code 'TICKET_MSG'
1638  include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
1639  $actioncomm = new ActionComm($this->db);
1640  $actioncomm->type_code = 'AC_OTH_AUTO'; // This is not an entry that must appears into manual calendar but only into CRM calendar
1641  $actioncomm->code = 'TICKET_MSG';
1642  if ($this->private) {
1643  $actioncomm->code = 'TICKET_MSG_PRIVATE';
1644  }
1645  if ($send_email) {
1646  $actioncomm->code .= '_SENTBYMAIL';
1647  }
1648  $actioncomm->socid = $this->socid;
1649  $actioncomm->label = $this->subject;
1650  $actioncomm->note_private = $this->message;
1651  $actioncomm->userassigned = array($user->id);
1652  $actioncomm->userownerid = $user->id;
1653  $actioncomm->datep = $now;
1654  $actioncomm->percentage = -1; // percentage is not relevant for punctual events
1655  $actioncomm->elementtype = 'ticket';
1656  $actioncomm->fk_element = $this->id;
1657  $actioncomm->fk_project = $this->fk_project;
1658 
1659  $attachedfiles = array();
1660  $attachedfiles['paths'] = $filename_list;
1661  $attachedfiles['names'] = $mimefilename_list;
1662  $attachedfiles['mimes'] = $mimetype_list;
1663  if (is_array($attachedfiles) && count($attachedfiles) > 0) {
1664  $actioncomm->attachedfiles = $attachedfiles;
1665  }
1666 
1667  if (!empty($mimefilename_list) && is_array($mimefilename_list)) {
1668  $actioncomm->note_private = dol_concatdesc($actioncomm->note_private, "\n".$langs->transnoentities("AttachedFiles").': '.join(';', $mimefilename_list));
1669  }
1670 
1671  $actionid = $actioncomm->create($user);
1672  if ($actionid <= 0) {
1673  $error++;
1674  $this->error = $actioncomm->error;
1675  $this->errors = $actioncomm->errors;
1676  }
1677 
1678  // Commit or rollback
1679  if ($error) {
1680  $this->db->rollback();
1681  return -1 * $error;
1682  } else {
1683  $this->db->commit();
1684  return 1;
1685  }
1686  }
1687 
1693  public function loadCacheMsgsTicket()
1694  {
1695  if (!empty($this->cache_msgs_ticket) && is_array($this->cache_msgs_ticket) && count($this->cache_msgs_ticket)) {
1696  return 0;
1697  }
1698 
1699  // Cache already loaded
1700 
1701  $sql = "SELECT id as rowid, fk_user_author, datec, label, note as message, code";
1702  $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm";
1703  $sql .= " WHERE fk_element = ".(int) $this->id;
1704  $sql .= " AND elementtype = 'ticket'";
1705  $sql .= " ORDER BY datec DESC";
1706 
1707  dol_syslog(get_class($this)."::load_cache_actions_ticket", LOG_DEBUG);
1708  $resql = $this->db->query($sql);
1709  if ($resql) {
1710  $num = $this->db->num_rows($resql);
1711  $i = 0;
1712  while ($i < $num) {
1713  $obj = $this->db->fetch_object($resql);
1714  $this->cache_msgs_ticket[$i]['id'] = $obj->rowid;
1715  $this->cache_msgs_ticket[$i]['fk_user_author'] = $obj->fk_user_author;
1716  $this->cache_msgs_ticket[$i]['datec'] = $this->db->jdate($obj->datec);
1717  $this->cache_msgs_ticket[$i]['subject'] = $obj->label;
1718  $this->cache_msgs_ticket[$i]['message'] = $obj->message;
1719  $this->cache_msgs_ticket[$i]['private'] = (preg_match('/^TICKET_MSG_PRIVATE/', $obj->code) ? 1 : 0);
1720  $i++;
1721  }
1722  return $num;
1723  } else {
1724  $this->error = "Error ".$this->db->lasterror();
1725  dol_syslog(get_class($this)."::load_cache_actions_ticket ".$this->error, LOG_ERR);
1726  return -1;
1727  }
1728  }
1729 
1737  public function close(User $user, $mode = 0)
1738  {
1739  global $conf, $langs;
1740 
1741  if ($this->fk_statut != Ticket::STATUS_CLOSED && $this->fk_statut != Ticket::STATUS_CANCELED) { // not closed
1742  $this->db->begin();
1743 
1744  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1745  $sql .= " SET fk_statut=".($mode ? Ticket::STATUS_CANCELED : Ticket::STATUS_CLOSED).", progress=100, date_close='".$this->db->idate(dol_now())."'";
1746  $sql .= " WHERE rowid = ".((int) $this->id);
1747 
1748  dol_syslog(get_class($this)."::close mode=".$mode);
1749  $resql = $this->db->query($sql);
1750  if ($resql) {
1751  $error = 0;
1752 
1753  // Valid and close fichinter linked
1754  if (isModEnabled('ficheinter') && !empty($conf->global->WORKFLOW_TICKET_CLOSE_INTERVENTION)) {
1755  dol_syslog("We have closed the ticket, so we close all linked interventions");
1756  $this->fetchObjectLinked($this->id, $this->element, null, 'fichinter');
1757  if ($this->linkedObjectsIds) {
1758  foreach ($this->linkedObjectsIds['fichinter'] as $fichinter_id) {
1759  $fichinter = new Fichinter($this->db);
1760  $fichinter->fetch($fichinter_id);
1761  if ($fichinter->statut == 0) {
1762  $result = $fichinter->setValid($user);
1763  if (!$result) {
1764  $this->errors[] = $fichinter->error;
1765  $error++;
1766  }
1767  }
1768  if ($fichinter->statut < 3) {
1769  $result = $fichinter->setStatut(3);
1770  if (!$result) {
1771  $this->errors[] = $fichinter->error;
1772  $error++;
1773  }
1774  }
1775  }
1776  }
1777  }
1778 
1779  // Call trigger
1780  $result = $this->call_trigger('TICKET_CLOSE', $user);
1781  if ($result < 0) {
1782  $error++;
1783  }
1784  // End call triggers
1785 
1786  if (!$error) {
1787  $this->db->commit();
1788  return 1;
1789  } else {
1790  $this->db->rollback();
1791  $this->error = join(',', $this->errors);
1792  dol_syslog(get_class($this)."::close ".$this->error, LOG_ERR);
1793  return -1;
1794  }
1795  } else {
1796  $this->db->rollback();
1797  $this->error = $this->db->lasterror();
1798  dol_syslog(get_class($this)."::close ".$this->error, LOG_ERR);
1799  return -1;
1800  }
1801  }
1802  }
1803 
1813  public function searchSocidByEmail($email, $type = '0', $filters = array(), $clause = 'AND')
1814  {
1815  $thirdparties = array();
1816  $exact = 0;
1817 
1818  // Generation requete recherche
1819  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe";
1820  $sql .= " WHERE entity IN (".getEntity('ticket', 1).")";
1821  if (!empty($type)) {
1822  if ($type == 1 || $type == 2) {
1823  $sql .= " AND client = ".((int) $type);
1824  } elseif ($type == 3) {
1825  $sql .= " AND fournisseur = 1";
1826  }
1827  }
1828  if (!empty($email)) {
1829  if (empty($exact)) {
1830  $regs = array();
1831  if (preg_match('/^([\*])?[^*]+([\*])?$/', $email, $regs) && count($regs) > 1) {
1832  $email = str_replace('*', '%', $email);
1833  } else {
1834  $email = '%'.$email.'%';
1835  }
1836  }
1837  $sql .= " AND ";
1838  if (is_array($filters) && !empty($filters)) {
1839  $sql .= "(";
1840  }
1841 
1842  $sql .= "email LIKE '".$this->db->escape($email)."'";
1843  }
1844  if (is_array($filters) && !empty($filters)) {
1845  foreach ($filters as $field => $value) {
1846  $sql .= " ".$clause." ".$field." LIKE '".$this->db->escape($value)."'";
1847  }
1848  if (!empty($email)) {
1849  $sql .= ")";
1850  }
1851  }
1852 
1853  $res = $this->db->query($sql);
1854  if ($res) {
1855  while ($rec = $this->db->fetch_array($res)) {
1856  $soc = new Societe($this->db);
1857  $soc->fetch($rec['rowid']);
1858  $thirdparties[] = $soc;
1859  }
1860 
1861  return $thirdparties;
1862  } else {
1863  $this->error = $this->db->error().' sql='.$sql;
1864  dol_syslog(get_class($this)."::searchSocidByEmail ".$this->error, LOG_ERR);
1865  return -1;
1866  }
1867  }
1868 
1877  public function searchContactByEmail($email, $socid = '', $case = '')
1878  {
1879  $contacts = array();
1880 
1881  // Forge the search SQL
1882  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."socpeople";
1883  $sql .= " WHERE entity IN (".getEntity('contact').")";
1884  if (!empty($socid)) {
1885  $sql .= " AND fk_soc = ".((int) $socid);
1886  }
1887  if (!empty($email)) {
1888  $sql .= " AND ";
1889  if (!$case) {
1890  $sql .= "email = '".$this->db->escape($email)."'";
1891  } else {
1892  $sql .= "email LIKE BINARY '".$this->db->escape($this->db->escapeforlike($email))."'";
1893  }
1894  }
1895 
1896  $res = $this->db->query($sql);
1897  if ($res) {
1898  while ($rec = $this->db->fetch_object($res)) {
1899  include_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
1900  $contactstatic = new Contact($this->db);
1901  $contactstatic->fetch($rec->rowid);
1902  $contacts[] = $contactstatic;
1903  }
1904 
1905  return $contacts;
1906  } else {
1907  $this->error = $this->db->error().' sql='.$sql;
1908  dol_syslog(get_class($this)."::searchContactByEmail ".$this->error, LOG_ERR);
1909  return -1;
1910  }
1911  }
1912 
1919  public function setCustomer($id)
1920  {
1921  if ($this->id) {
1922  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1923  $sql .= " SET fk_soc = ".($id > 0 ? $id : "null");
1924  $sql .= " WHERE rowid = ".((int) $this->id);
1925  dol_syslog(get_class($this).'::setCustomer sql='.$sql);
1926  $resql = $this->db->query($sql);
1927  if ($resql) {
1928  return 1;
1929  } else {
1930  return -1;
1931  }
1932  } else {
1933  return -1;
1934  }
1935  }
1936 
1943  public function setProgression($percent)
1944  {
1945  if ($this->id) {
1946  $sql = "UPDATE ".MAIN_DB_PREFIX."ticket";
1947  $sql .= " SET progress = ".($percent > 0 ? $percent : "null");
1948  $sql .= " WHERE rowid = ".((int) $this->id);
1949  dol_syslog(get_class($this).'::set_progression sql='.$sql);
1950  $resql = $this->db->query($sql);
1951  if ($resql) {
1952  return 1;
1953  } else {
1954  return -1;
1955  }
1956  } else {
1957  return -1;
1958  }
1959  }
1960 
1967  public function setContract($contractid)
1968  {
1969  if (!$this->table_element) {
1970  dol_syslog(get_class($this)."::setContract was called on objet with property table_element not defined", LOG_ERR);
1971  return -1;
1972  }
1973 
1974  $result = $this->add_object_linked('contrat', $contractid);
1975  if ($result) {
1976  $this->fk_contract = $contractid;
1977  return 1;
1978  } else {
1979  dol_print_error($this->db);
1980  return -1;
1981  }
1982  }
1983 
1984  /* gestion des contacts d'un ticket */
1985 
1991  public function getIdTicketInternalContact()
1992  {
1993  return $this->getIdContact('internal', 'SUPPORTTEC');
1994  }
1995 
2002  {
2003  return $this->listeContact(-1, 'internal');
2004  }
2005 
2011  public function getIdTicketCustomerContact()
2012  {
2013  return $this->getIdContact('external', 'SUPPORTCLI');
2014  }
2015 
2022  {
2023  return $this->listeContact(-1, 'external');
2024  }
2025 
2032  {
2033  return $this->getIdContact('internal', 'CONTRIBUTOR');
2034  }
2035 
2042  {
2043  return $this->getIdContact('external', 'CONTRIBUTOR');
2044  }
2045 
2051  public function getTicketAllContacts()
2052  {
2053  $array_contact = array();
2054 
2055  $array_contact = $this->getIdTicketInternalContact();
2056 
2057  $array_contact = array_merge($array_contact, $this->getIdTicketCustomerContact());
2058 
2059  $array_contact = array_merge($array_contact, $this->getIdTicketInternalInvolvedContact());
2060 
2061  $array_contact = array_merge($array_contact, $this->getIdTicketCustomerInvolvedContact());
2062 
2063  return $array_contact;
2064  }
2065 
2072  {
2073  $array_contact = array();
2074 
2075  $array_contact = array_merge($array_contact, $this->getIdTicketCustomerContact());
2076 
2077  $array_contact = array_merge($array_contact, $this->getIdTicketCustomerInvolvedContact());
2078 
2079  return $array_contact;
2080  }
2081 
2082 
2093  public function listeContact($status = -1, $source = 'external', $list = 0, $code = '')
2094  {
2095  global $langs;
2096 
2097  $tab = array();
2098 
2099  $sql = "SELECT ec.rowid, ec.statut as statuslink, ec.fk_socpeople as id, ec.fk_c_type_contact"; // This field contains id of llx_socpeople or id of llx_user
2100  if ($source == 'internal') {
2101  $sql .= ", '-1' as socid, t.statut as statuscontact";
2102  }
2103 
2104  if ($source == 'external' || $source == 'thirdparty') {
2105  $sql .= ", t.fk_soc as socid, t.statut as statuscontact";
2106  }
2107 
2108  $sql .= ", t.civility, t.lastname as lastname, t.firstname, t.email";
2109  if ($source == 'internal') {
2110  $sql .= ", t.office_phone as phone, t.user_mobile as phone_mobile";
2111  }
2112 
2113  if ($source == 'external') {
2114  $sql .= ", t.phone as phone, t.phone_mobile as phone_mobile, t.phone_perso as phone_perso";
2115  }
2116 
2117  $sql .= ", tc.source, tc.element, tc.code, tc.libelle as type_contact_label";
2118  $sql .= " FROM ".MAIN_DB_PREFIX."c_type_contact tc";
2119  $sql .= ", ".MAIN_DB_PREFIX."element_contact ec";
2120  if ($source == 'internal') {
2121  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user t on ec.fk_socpeople = t.rowid";
2122  }
2123 
2124  if ($source == 'external' || $source == 'thirdparty') {
2125  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople t on ec.fk_socpeople = t.rowid";
2126  }
2127 
2128  $sql .= " WHERE ec.element_id = ".((int) $this->id);
2129  $sql .= " AND ec.fk_c_type_contact=tc.rowid";
2130  $sql .= " AND tc.element='".$this->db->escape($this->element)."'";
2131  if ($source == 'internal') {
2132  $sql .= " AND tc.source = 'internal'";
2133  }
2134 
2135  if ($source == 'external' || $source == 'thirdparty') {
2136  $sql .= " AND tc.source = 'external'";
2137  }
2138 
2139  if (!empty($code)) {
2140  $sql .= " AND tc.code = '".$this->db->escape($code)."'";
2141  }
2142 
2143  $sql .= " AND tc.active=1";
2144  if ($status >= 0) {
2145  $sql .= " AND ec.statut = ".((int) $status);
2146  }
2147 
2148  $sql .= " ORDER BY t.lastname ASC";
2149 
2150  $resql = $this->db->query($sql);
2151  if ($resql) {
2152  $num = $this->db->num_rows($resql);
2153  $i = 0;
2154  while ($i < $num) {
2155  $obj = $this->db->fetch_object($resql);
2156 
2157  if (!$list) {
2158  $transkey = "TypeContact_".$obj->element."_".$obj->source."_".$obj->code;
2159  $libelle_type = ($langs->trans($transkey) != $transkey ? $langs->trans($transkey) : $obj->type_contact_label);
2160  $tab[$i] = array(
2161  'source' => $obj->source,
2162  'socid' => $obj->socid,
2163  'id' => $obj->id,
2164  'nom' => $obj->lastname, // For backward compatibility
2165  'civility' => $obj->civility,
2166  'lastname' => $obj->lastname,
2167  'firstname' => $obj->firstname,
2168  'email' => $obj->email,
2169  'rowid' => $obj->rowid,
2170  'code' => $obj->code,
2171  'libelle' => $libelle_type,
2172  'status' => $obj->statuslink,
2173  'statuscontact'=>$obj->statuscontact,
2174  'fk_c_type_contact' => $obj->fk_c_type_contact,
2175  'phone' => $obj->phone,
2176  'phone_mobile' => $obj->phone_mobile);
2177  } else {
2178  $tab[$i] = $obj->id;
2179  }
2180 
2181  $i++;
2182  }
2183 
2184  return $tab;
2185  } else {
2186  $this->error = $this->db->error();
2187  dol_print_error($this->db);
2188  return -1;
2189  }
2190  }
2191 
2198  public function getDefaultRef($thirdparty = '')
2199  {
2200  global $conf;
2201 
2202  $defaultref = '';
2203  $modele = empty($conf->global->TICKET_ADDON) ? 'mod_ticket_simple' : $conf->global->TICKET_ADDON;
2204 
2205  // Search template files
2206  $file = '';
2207  $classname = '';
2208  $filefound = 0;
2209  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
2210  foreach ($dirmodels as $reldir) {
2211  $file = dol_buildpath($reldir."core/modules/ticket/".$modele.'.php', 0);
2212  if (file_exists($file)) {
2213  $filefound = 1;
2214  $classname = $modele;
2215  break;
2216  }
2217  }
2218 
2219  if ($filefound) {
2220  $result = dol_include_once($reldir."core/modules/ticket/".$modele.'.php');
2221  $modTicket = new $classname;
2222 
2223  $defaultref = $modTicket->getNextValue($thirdparty, $this);
2224  }
2225 
2226  if (is_numeric($defaultref) && $defaultref <= 0) {
2227  $defaultref = '';
2228  }
2229 
2230  return $defaultref;
2231  }
2232 
2233 
2234  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2241  public function is_photo_available($sdir)
2242  {
2243  // phpcs:enable
2244  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2245 
2246  global $conf;
2247 
2248  $dir = $sdir.'/';
2249  $nbphoto = 0;
2250 
2251  $dir_osencoded = dol_osencode($dir);
2252  if (file_exists($dir_osencoded)) {
2253  $handle = opendir($dir_osencoded);
2254  if (is_resource($handle)) {
2255  while (($file = readdir($handle)) !== false) {
2256  if (!utf8_check($file)) {
2257  $file = utf8_encode($file); // To be sure data is stored in UTF8 in memory
2258  }
2259  if (dol_is_file($dir.$file)) {
2260  return true;
2261  }
2262  }
2263  }
2264  }
2265  return false;
2266  }
2267 
2268 
2277  public function copyFilesForTicket($forcetrackid = null)
2278  {
2279  global $conf;
2280 
2281  // Create form object
2282  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2283  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2284  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2285 
2286  $maxwidthsmall = 270;
2287  $maxheightsmall = 150;
2288  $maxwidthmini = 128;
2289  $maxheightmini = 72;
2290 
2291  $formmail = new FormMail($this->db);
2292  $formmail->trackid = (is_null($forcetrackid) ? 'tic'.$this->id : '');
2293  $attachedfiles = $formmail->get_attached_files();
2294 
2295  $filepath = $attachedfiles['paths']; // path is for example user->dir_temp.'/'.$user->id.'/'...
2296  $filename = $attachedfiles['names'];
2297  $mimetype = $attachedfiles['mimes'];
2298 
2299  // Copy files into ticket directory
2300  $destdir = $conf->ticket->dir_output.'/'.$this->ref;
2301 
2302  if (!dol_is_dir($destdir)) {
2303  dol_mkdir($destdir);
2304  }
2305 
2306  $listofpaths = array();
2307  $listofnames = array();
2308  foreach ($filename as $i => $val) {
2309  $destfile = $destdir.'/'.$filename[$i];
2310  // If destination file already exists, we add a suffix to avoid to overwrite
2311  if (is_file($destfile)) {
2312  $pathinfo = pathinfo($filename[$i]);
2313  $now = dol_now();
2314  $destfile = $destdir.'/'.$pathinfo['filename'].' - '.dol_print_date($now, 'dayhourlog').'.'.$pathinfo['extension'];
2315  }
2316 
2317  $res = dol_move($filepath[$i], $destfile, 0, 1, 0, 1);
2318  if (!$res) {
2319  // Move has failed
2320  $this->error = "Failed to move file ".dirbasename($filepath[$i])." into ".dirbasename($destfile);
2321  return -1;
2322  } else {
2323  // If file is an image, we create thumbs
2324  if (image_format_supported($destfile) == 1) {
2325  // Create small thumbs for image (Ratio is near 16/9)
2326  // Used on logon for example
2327  $imgThumbSmall = vignette($destfile, $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
2328  // Create mini thumbs for image (Ratio is near 16/9)
2329  // Used on menu or for setup page for example
2330  $imgThumbMini = vignette($destfile, $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
2331  }
2332  }
2333 
2334  // Clear variables into session
2335  $formmail->remove_attached_files($i);
2336 
2337  // Fill array with new names
2338  $listofpaths[$i] = $destfile;
2339  $listofnames[$i] = basename($destfile);
2340  }
2341 
2342  return array('listofpaths'=>$listofpaths, 'listofnames'=>$listofnames, 'listofmimes'=>$mimetype);
2343  }
2344 
2355  public function setCategories($categories)
2356  {
2357  // Handle single category
2358  if (!is_array($categories)) {
2359  $categories = array($categories);
2360  }
2361 
2362  // Get current categories
2363  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2364  $c = new Categorie($this->db);
2365  $existing = $c->containing($this->id, Categorie::TYPE_TICKET, 'id');
2366 
2367  // Diff
2368  if (is_array($existing)) {
2369  $to_del = array_diff($existing, $categories);
2370  $to_add = array_diff($categories, $existing);
2371  } else {
2372  $to_del = array(); // Nothing to delete
2373  $to_add = $categories;
2374  }
2375 
2376  // Process
2377  foreach ($to_del as $del) {
2378  if ($c->fetch($del) > 0) {
2379  $c->del_type($this, Categorie::TYPE_TICKET);
2380  }
2381  }
2382  foreach ($to_add as $add) {
2383  if ($c->fetch($add) > 0) {
2384  $c->add_type($this, Categorie::TYPE_TICKET);
2385  }
2386  }
2387 
2388  return;
2389  }
2390 
2401  public function newMessage($user, &$action, $private = 1, $public_area = 0)
2402  {
2403  global $mysoc, $conf, $langs;
2404 
2405  $error = 0;
2406 
2407  $object = new Ticket($this->db);
2408 
2409  $ret = $object->fetch('', '', GETPOST('track_id', 'alpha'));
2410 
2411  $object->socid = $object->fk_soc;
2412  $object->fetch_thirdparty();
2413  $object->fetch_project();
2414 
2415  if ($ret < 0) {
2416  $error++;
2417  array_push($this->errors, $langs->trans("ErrorTicketIsNotValid"));
2418  $action = '';
2419  }
2420 
2421  if (!GETPOST("message")) {
2422  $error++;
2423  array_push($this->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("message")));
2424  $action = 'add_message';
2425  }
2426 
2427  if (!$error) {
2428  $object->subject = GETPOST('subject', 'alphanohtml');
2429  $object->message = GETPOST("message", "restricthtml");
2430  $object->private = GETPOST("private_message", "alpha");
2431 
2432  $send_email = GETPOST('send_email', 'int');
2433 
2434  // Copy attached files (saved into $_SESSION) as linked files to ticket. Return array with final name used.
2435  $resarray = $object->copyFilesForTicket();
2436  if (is_numeric($resarray) && $resarray == -1) {
2437  setEventMessages($object->error, $object->errors, 'errors');
2438  return -1;
2439  }
2440 
2441  $listofpaths = $resarray['listofpaths'];
2442  $listofnames = $resarray['listofnames'];
2443  $listofmimes = $resarray['listofmimes'];
2444 
2445  $id = $object->createTicketMessage($user, 0, $listofpaths, $listofmimes, $listofnames, $send_email);
2446  if ($id <= 0) {
2447  $error++;
2448  $this->error = $object->error;
2449  $this->errors = $object->errors;
2450  $action = 'add_message';
2451  }
2452 
2453  if (!$error && $id > 0) {
2454  setEventMessages($langs->trans('TicketMessageSuccessfullyAdded'), null, 'mesgs');
2455 
2456  //var_dump($_SESSION);
2457  //var_dump($listofpaths);exit;
2458 
2459  if (!empty($public_area)) {
2460  /*
2461  * Message created from the Public interface
2462  *
2463  * Send emails to assigned users (public area notification)
2464  */
2465  if (!empty($conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_ENABLED)) {
2466  $assigned_user_dont_have_email = '';
2467  $sendto = array();
2468  if ($this->fk_user_assign > 0) {
2469  $assigned_user = new User($this->db);
2470  $assigned_user->fetch($this->fk_user_assign);
2471  if (!empty($assigned_user->email)) {
2472  $sendto[$assigned_user->email] = $assigned_user->getFullName($langs)." <".$assigned_user->email.">";
2473  } else {
2474  $assigned_user_dont_have_email = $assigned_user->getFullName($langs);
2475  }
2476  }
2477  if (empty($sendto)) {
2478  if (!empty($conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL)) {
2479  $sendto[$conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL] = $conf->global->TICKET_PUBLIC_NOTIFICATION_NEW_MESSAGE_DEFAULT_EMAIL;
2480  } elseif (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) {
2481  $sendto[$conf->global->TICKET_NOTIFICATION_EMAIL_TO] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
2482  }
2483  }
2484 
2485  // Add global email address recipient
2486  if (!empty($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS) &&
2487  !empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) && !array_key_exists($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)
2488  ) {
2489  $sendto[$conf->global->TICKET_NOTIFICATION_EMAIL_TO] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
2490  }
2491 
2492  if (!empty($sendto)) {
2493  $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE;
2494  $subject = '['.$label_title.'- ticket #'.$object->track_id.'] '.$langs->trans('TicketNewMessage');
2495 
2496  // Message send
2497  $message = $langs->trans('TicketMessageMailIntroText');
2498  $message .= '<br><br>';
2499  $messagePost = GETPOST('message', 'restricthtml');
2500  if (!dol_textishtml($messagePost)) {
2501  $messagePost = dol_nl2br($messagePost);
2502  }
2503  $message .= $messagePost;
2504 
2505  // Customer company infos
2506  $message .= '<br><br>';
2507  $message .= "==============================================";
2508  $message .= !empty($object->thirdparty->name) ? '<br>'.$langs->trans('Thirdparty')." : ".$object->thirdparty->name : '';
2509  $message .= !empty($object->thirdparty->town) ? '<br>'.$langs->trans('Town')." : ".$object->thirdparty->town : '';
2510  $message .= !empty($object->thirdparty->phone) ? '<br>'.$langs->trans('Phone')." : ".$object->thirdparty->phone : '';
2511 
2512  // Email send to
2513  $message .= '<br><br>';
2514  if (!empty($assigned_user_dont_have_email)) {
2515  $message .= '<br>'.$langs->trans('NoEMail').' : '.$assigned_user_dont_have_email;
2516  }
2517  foreach ($sendto as $val) {
2518  $message .= '<br>'.$langs->trans('TicketNotificationRecipient').' : '.$val;
2519  }
2520 
2521  // URL ticket
2522  $url_internal_ticket = dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id;
2523  $message .= '<br><br>';
2524  $message .= $langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal').' : <a href="'.$url_internal_ticket.'">'.$object->track_id.'</a>';
2525 
2526  $this->sendTicketMessageByEmail($subject, $message, '', $sendto, $listofpaths, $listofmimes, $listofnames);
2527  }
2528  }
2529  } else {
2530  /*
2531  * Message send from the Backoffice / Private area
2532  *
2533  * Send emails to internal users (linked contacts) then, if private is not set, to external users (linked contacts or thirdparty email if no contact set)
2534  */
2535  if ($send_email > 0) {
2536  // Retrieve internal contact datas
2537  $internal_contacts = $object->getInfosTicketInternalContact();
2538 
2539  $sendto = array();
2540  if (is_array($internal_contacts) && count($internal_contacts) > 0) {
2541  // Set default subject
2542  $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE;
2543  $appli = $label_title;
2544  $subject = GETPOST('subject', 'alphanohtml') ? GETPOST('subject', 'alphanohtml') : '['.$appli.' - '.$langs->trans("Ticket").' #'.$object->track_id.'] '.$langs->trans('TicketNewMessage');
2545 
2546  $message_intro = $langs->trans('TicketNotificationEmailBody', "#".$object->id);
2547  $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE');
2548 
2549  $message = $langs->trans('TicketMessageMailIntroText');
2550  $message .= '<br><br>';
2551  $messagePost = GETPOST('message', 'restricthtml');
2552  if (!dol_textishtml($messagePost)) {
2553  $messagePost = dol_nl2br($messagePost);
2554  }
2555  $message .= $messagePost;
2556 
2557  // Data about customer
2558  $message .= '<br><br>';
2559  $message .= "==============================================<br>";
2560  $message .= !empty($object->thirdparty->name) ? $langs->trans('Thirdparty')." : ".$object->thirdparty->name : '';
2561  $message .= !empty($object->thirdparty->town) ? '<br>'.$langs->trans('Town')." : ".$object->thirdparty->town : '';
2562  $message .= !empty($object->thirdparty->phone) ? '<br>'.$langs->trans('Phone')." : ".$object->thirdparty->phone : '';
2563 
2564  // Build array to display recipient list
2565  foreach ($internal_contacts as $key => $info_sendto) {
2566  // Avoid duplicate notifications
2567  if ($info_sendto['id'] == $user->id) {
2568  continue;
2569  }
2570 
2571  if ($info_sendto['email'] != '') {
2572  if (!empty($info_sendto['email'])) {
2573  $sendto[$info_sendto['email']] = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'])." <".$info_sendto['email'].">";
2574  }
2575 
2576  // Contact type
2577  $recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1').' ('.strtolower($info_sendto['libelle']).')';
2578  $message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient').' : '.$recipient.'<br>' : '');
2579  }
2580  }
2581  $message .= '<br>';
2582  // URL ticket
2583  $url_internal_ticket = dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id;
2584 
2585  // Add html link on url
2586  $message .= '<br>'.$langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal').' : <a href="'.$url_internal_ticket.'">'.$object->track_id.'</a><br>';
2587 
2588  // Add global email address recipient
2589  if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !array_key_exists($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)) {
2590  if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) {
2591  $sendto[$conf->global->TICKET_NOTIFICATION_EMAIL_TO] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
2592  }
2593  }
2594 
2595  // dont try to send email if no recipient
2596  if (!empty($sendto)) {
2597  $this->sendTicketMessageByEmail($subject, $message, '', $sendto, $listofpaths, $listofmimes, $listofnames);
2598  }
2599  }
2600 
2601  /*
2602  * Send emails for externals users if not private (linked contacts)
2603  */
2604  if (empty($object->private)) {
2605  // Retrieve email of all contacts (external)
2606  $external_contacts = $object->getInfosTicketExternalContact();
2607 
2608  // If no contact, get email from thirdparty
2609  if (is_array($external_contacts) && count($external_contacts) === 0) {
2610  if (!empty($object->fk_soc)) {
2611  $object->fetch_thirdparty($object->fk_soc);
2612  $array_company = array(array('firstname' => '', 'lastname' => $object->thirdparty->name, 'email' => $object->thirdparty->email, 'libelle' => $langs->transnoentities('Customer'), 'socid' => $object->thirdparty->id));
2613  $external_contacts = array_merge($external_contacts, $array_company);
2614  } elseif (empty($object->fk_soc) && !empty($object->origin_email)) {
2615  $array_external = array(array('firstname' => '', 'lastname' => $object->origin_email, 'email' => $object->thirdparty->email, 'libelle' => $langs->transnoentities('Customer'), 'socid' => $object->thirdparty->id));
2616  $external_contacts = array_merge($external_contacts, $array_external);
2617  }
2618  }
2619 
2620  $sendto = array();
2621  if (is_array($external_contacts) && count($external_contacts) > 0) {
2622  // Get default subject for email to external contacts
2623  $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE;
2624  $appli = $mysoc->name;
2625  $subject = GETPOST('subject') ? GETPOST('subject') : '['.$appli.' - '.$langs->trans("Ticket").' #'.$object->track_id.'] '.$langs->trans('TicketNewMessage');
2626 
2627  $message_intro = GETPOST('mail_intro') ? GETPOST('mail_intro', 'restricthtml') : getDolGlobalString('TICKET_MESSAGE_MAIL_INTRO');
2628  $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature', 'restricthtml') : getDolGlobalString('TICKET_MESSAGE_MAIL_SIGNATURE');
2629  if (!dol_textishtml($message_intro)) {
2630  $message_intro = dol_nl2br($message_intro);
2631  }
2632  if (!dol_textishtml($message_signature)) {
2633  $message_signature = dol_nl2br($message_signature);
2634  }
2635 
2636  // We put intro after
2637  $messagePost = GETPOST('message', 'restricthtml');
2638  if (!dol_textishtml($messagePost)) {
2639  $messagePost = dol_nl2br($messagePost);
2640  }
2641  $message = $messagePost;
2642  $message .= '<br><br>';
2643 
2644  foreach ($external_contacts as $key => $info_sendto) {
2645  // altairis: avoid duplicate emails to external contacts
2646  if ($info_sendto['id'] == $user->contact_id) {
2647  continue;
2648  }
2649 
2650  if ($info_sendto['email'] != '' && $info_sendto['email'] != $object->origin_email) {
2651  if (!empty($info_sendto['email'])) {
2652  $sendto[$info_sendto['email']] = trim($info_sendto['firstname']." ".$info_sendto['lastname'])." <".$info_sendto['email'].">";
2653  }
2654 
2655  $recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1').' ('.strtolower($info_sendto['libelle']).')';
2656  $message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient').' : '.$recipient.'<br>' : '');
2657  }
2658  }
2659 
2660  // If public interface is not enable, use link to internal page into mail
2661  $url_public_ticket = (!empty($conf->global->TICKET_ENABLE_PUBLIC_INTERFACE) ?
2662  (!empty($conf->global->TICKET_URL_PUBLIC_INTERFACE) ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/view.php' : dol_buildpath('/public/ticket/view.php', 2)) : dol_buildpath('/ticket/card.php', 2)).'?track_id='.$object->track_id;
2663  $message .= '<br>'.$langs->trans('TicketNewEmailBodyInfosTrackUrlCustomer').' : <a href="'.$url_public_ticket.'">'.$object->track_id.'</a><br>';
2664 
2665  // Build final message
2666  $message = $message_intro.'<br><br>'.$message;
2667 
2668  // Add signature
2669  $message .= '<br>'.$message_signature;
2670 
2671  if (!empty($object->origin_email)) {
2672  $sendto[$object->origin_email] = $object->origin_email;
2673  }
2674 
2675  if ($object->fk_soc > 0 && !array_key_exists($object->origin_email, $sendto)) {
2676  $object->socid = $object->fk_soc;
2677  $object->fetch_thirdparty();
2678  if (!empty($object->thirdparty->email)) {
2679  $sendto[$object->thirdparty->email] = $object->thirdparty->email;
2680  }
2681  }
2682 
2683  // Add global email address recipient
2684  if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !array_key_exists($conf->global->TICKET_NOTIFICATION_EMAIL_TO, $sendto)) {
2685  if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO)) {
2686  $sendto[$conf->global->TICKET_NOTIFICATION_EMAIL_TO] = $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
2687  }
2688  }
2689 
2690  // Dont try to send email when no recipient
2691  if (!empty($sendto)) {
2692  $result = $this->sendTicketMessageByEmail($subject, $message, '', $sendto, $listofpaths, $listofmimes, $listofnames);
2693  if ($result) {
2694  // update last_msg_sent date (for last message sent to external users)
2695  $this->date_last_msg_sent = dol_now();
2696  $this->update($user, 1); // disable trigger when updating date_last_msg_sent. sendTicketMessageByEmail already create an event in actioncomm table.
2697  }
2698  }
2699  }
2700  }
2701  }
2702  }
2703 
2704  // Set status to "answered" if not set yet, but only if internal user and not private message
2705  // Or set status to "answered" if the client has answered and if the ticket has started
2706  if (($object->status < self::STATUS_IN_PROGRESS && !$user->socid && !$private) ||
2707  ($object->status > self::STATUS_IN_PROGRESS && $public_area)
2708  ) {
2709  $object->setStatut(3);
2710  }
2711  return 1;
2712  } else {
2713  setEventMessages($object->error, $object->errors, 'errors');
2714  return -1;
2715  }
2716  } else {
2717  setEventMessages($this->error, $this->errors, 'errors');
2718  return -1;
2719  }
2720  }
2721 
2722 
2735  public function sendTicketMessageByEmail($subject, $message, $send_internal_cc = 0, $array_receiver = array(), $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array())
2736  {
2737  global $conf, $langs;
2738 
2739  if ($conf->global->TICKET_DISABLE_ALL_MAILS) {
2740  dol_syslog(get_class($this).'::sendTicketMessageByEmail: Emails are disable into ticket setup by option TICKET_DISABLE_ALL_MAILS', LOG_WARNING);
2741  return false;
2742  }
2743 
2744  $langs->load("mails");
2745 
2746  include_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
2747  //$contactstatic = new Contact($this->db);
2748 
2749  // If no receiver defined, load all ticket linked contacts
2750  if (!is_array($array_receiver) || !count($array_receiver) > 0) {
2751  $array_receiver = $this->getInfosTicketInternalContact();
2752  $array_receiver = array_merge($array_receiver, $this->getInfosTicketExternalContact());
2753  }
2754 
2755  if ($send_internal_cc) {
2756  $sendtocc = $conf->global->TICKET_NOTIFICATION_EMAIL_FROM;
2757  }
2758 
2759  $from = $conf->global->TICKET_NOTIFICATION_EMAIL_FROM;
2760  $is_sent = false;
2761  if (is_array($array_receiver) && count($array_receiver) > 0) {
2762  foreach ($array_receiver as $key => $receiver) {
2763  $deliveryreceipt = 0;
2764  $filepath = $filename_list;
2765  $filename = $mimefilename_list;
2766  $mimetype = $mimetype_list;
2767 
2768  // Send email
2769 
2770  $old_MAIN_MAIL_AUTOCOPY_TO = getDolGlobalString('MAIN_MAIL_AUTOCOPY_TO');
2771 
2772  if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
2773  $conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
2774  }
2775 
2776  $upload_dir_tmp = $conf->user->dir_output."/".$user->id.'/temp';
2777 
2778  include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
2779  $trackid = "tic".$this->id;
2780 
2781  $moreinheader = 'X-Dolibarr-Info: sendTicketMessageByEmail'."\r\n";
2782  if (!empty($this->email_msgid)) {
2783  $moreinheader .= 'References <'.$this->email_msgid.'>'."\r\n";
2784  }
2785 
2786  $mailfile = new CMailFile($subject, $receiver, $from, $message, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, -1, '', '', $trackid, $moreinheader, 'ticket', '', $upload_dir_tmp);
2787  if ($mailfile->error) {
2788  setEventMessages($mailfile->error, null, 'errors');
2789  } else {
2790  $result = $mailfile->sendfile();
2791  if ($result) {
2792  setEventMessages($langs->trans('MailSuccessfulySent', $mailfile->getValidAddress($from, 2), $mailfile->getValidAddress($receiver, 2)), null, 'mesgs');
2793  $is_sent = true;
2794  } else {
2795  $langs->load("other");
2796  if ($mailfile->error) {
2797  setEventMessages($langs->trans('ErrorFailedToSendMail', $from, $receiver), null, 'errors');
2798  dol_syslog($langs->trans('ErrorFailedToSendMail', $from, $receiver).' : '.$mailfile->error);
2799  } else {
2800  setEventMessages('No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS', null, 'errors');
2801  }
2802  }
2803  }
2804 
2805  if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
2806  $conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
2807  }
2808  }
2809  } else {
2810  $langs->load("other");
2811  setEventMessages($langs->trans('ErrorMailRecipientIsEmptyForSendTicketMessage'), null, 'warnings');
2812  }
2813 
2814  return $is_sent;
2815  }
2816 
2817  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2825  public function load_board($user, $mode)
2826  {
2827  // phpcs:enable
2828  global $conf, $user, $langs;
2829 
2830  $now = dol_now();
2831  $delay_warning = 0;
2832 
2833  $this->nbtodo = $this->nbtodolate = 0;
2834  $clause = " WHERE";
2835 
2836  $sql = "SELECT p.rowid, p.ref, p.datec as datec";
2837  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as p";
2838  if (isModEnabled('societe') && empty($user->rights->societe->client->voir) && !$user->socid) {
2839  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON p.fk_soc = sc.fk_soc";
2840  $sql .= " WHERE sc.fk_user = ".((int) $user->id);
2841  $clause = " AND";
2842  }
2843  $sql .= $clause." p.entity IN (".getEntity('ticket').")";
2844  if ($mode == 'opened') {
2845  $sql .= " AND p.fk_statut NOT IN (".Ticket::STATUS_CLOSED.", ".Ticket::STATUS_CANCELED.")";
2846  }
2847  if ($user->socid) {
2848  $sql .= " AND p.fk_soc = ".((int) $user->socid);
2849  }
2850 
2851  $resql = $this->db->query($sql);
2852  if ($resql) {
2853  $label = $labelShort = '';
2854  $status = '';
2855  if ($mode == 'opened') {
2856  $status = 'openall';
2857  //$delay_warning = $conf->ticket->warning_delay;
2858  $delay_warning = 0;
2859  $label = $langs->trans("MenuListNonClosed");
2860  $labelShort = $langs->trans("MenuListNonClosed");
2861  }
2862 
2863  $response = new WorkboardResponse();
2864  //$response->warning_delay = $delay_warning / 60 / 60 / 24;
2865  $response->label = $label;
2866  $response->labelShort = $labelShort;
2867  $response->url = DOL_URL_ROOT.'/ticket/list.php?search_fk_statut[]='.$status;
2868  $response->img = img_object('', "ticket");
2869 
2870  // This assignment in condition is not a bug. It allows walking the results.
2871  while ($obj = $this->db->fetch_object($resql)) {
2872  $response->nbtodo++;
2873  if ($mode == 'opened') {
2874  $datelimit = $this->db->jdate($obj->datec) + $delay_warning;
2875  if ($datelimit < $now) {
2876  //$response->nbtodolate++;
2877  }
2878  }
2879  }
2880  return $response;
2881  } else {
2882  $this->error = $this->db->lasterror();
2883  return -1;
2884  }
2885  }
2886 
2887  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2893  public function load_state_board()
2894  {
2895  // phpcs:enable
2896  global $conf, $user;
2897 
2898  $this->nb = array();
2899  $clause = "WHERE";
2900 
2901  $sql = "SELECT count(p.rowid) as nb";
2902  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as p";
2903  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
2904  if (empty($user->rights->societe->client->voir) && !$user->socid) {
2905  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2906  $sql .= " WHERE sc.fk_user = ".((int) $user->id);
2907  $clause = "AND";
2908  }
2909  $sql .= " ".$clause." p.entity IN (".getEntity('ticket').")";
2910 
2911  $resql = $this->db->query($sql);
2912  if ($resql) {
2913  // This assignment in condition is not a bug. It allows walking the results.
2914  while ($obj = $this->db->fetch_object($resql)) {
2915  $this->nb["ticket"] = $obj->nb;
2916  }
2917  $this->db->free($resql);
2918  return 1;
2919  } else {
2920  dol_print_error($this->db);
2921  $this->error = $this->db->lasterror();
2922  return -1;
2923  }
2924  }
2925 
2934  public static function replaceThirdparty($db, $origin_id, $dest_id)
2935  {
2936  $tables = array('ticket');
2937 
2938  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2939  }
2940 }
2941 
2942 
2947 {
2952  public $rowid;
2953 
2957  public $id;
2958 
2962  public $ref;
2963 
2967  public $track_id;
2968 
2972  public $fk_soc;
2973 
2977  public $fk_project;
2978 
2983 
2988 
2993 
2997  public $subject;
2998 
3002  public $message;
3003 
3007  public $fk_statut;
3008 
3012  public $resolution;
3013 
3017  public $progress;
3018 
3022  public $timing;
3023 
3027  public $type_code;
3028 
3033 
3038 
3042  public $type_label;
3043 
3048 
3053 
3057  public $datec = '';
3058 
3062  public $date_read = '';
3063 
3067  public $date_last_msg_sent = '';
3068 
3072  public $date_close = '';
3073 }
Ticket\getIdTicketInternalContact
getIdTicketInternalContact()
Return id des contacts interne de suivi.
Definition: ticket.class.php:1991
Ticket\sendTicketMessageByEmail
sendTicketMessageByEmail($subject, $message, $send_internal_cc=0, $array_receiver=array(), $filename_list=array(), $mimetype_list=array(), $mimefilename_list=array())
Send ticket by email to linked contacts.
Definition: ticket.class.php:2735
Societe
Class to manage third parties objects (customers, suppliers, prospects...)
Definition: societe.class.php:49
db
$conf db
API class for accounts.
Definition: inc.php:41
TicketsLine\$date_read
$date_read
Read date.
Definition: ticket.class.php:3062
TicketsLine\$timing
$timing
Duration for ticket.
Definition: ticket.class.php:3022
TicketsLine\$progress
$progress
Progress in percent.
Definition: ticket.class.php:3017
Ticket\replaceThirdparty
static replaceThirdparty($db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
Definition: ticket.class.php:2934
ActionComm
Class to manage agenda events (actions)
Definition: actioncomm.class.php:38
TicketsLine\$type_label
$type_label
Type label.
Definition: ticket.class.php:3042
Ticket\fetchAll
fetchAll($user, $sortorder='ASC', $sortfield='t.datec', $limit='', $offset=0, $arch='', $filter='')
Load all objects in memory from database.
Definition: ticket.class.php:713
dol_osencode
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
Definition: functions.lib.php:8843
TicketsLine\$origin_email
$origin_email
Person email who have create ticket.
Definition: ticket.class.php:2982
Ticket\listeContact
listeContact($status=-1, $source='external', $list=0, $code='')
Get array of all contacts for a ticket Override method of file commonobject.class....
Definition: ticket.class.php:2093
Ticket\is_photo_available
is_photo_available($sdir)
Return if at least one photo is available.
Definition: ticket.class.php:2241
Ticket\$category_label
$category_label
Category label.
Definition: ticket.class.php:159
GETPOST
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:520
dol_nl2br
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
Definition: functions.lib.php:7160
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:4993
dol_include_once
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
Definition: functions.lib.php:1032
ref
$object ref
Definition: info.php:78
dol_buildpath
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
Definition: functions.lib.php:1061
Ticket\update
update($user=0, $notrigger=0)
Update object into database.
Definition: ticket.class.php:880
CMailFile
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
Definition: CMailFile.class.php:41
TicketsLine\$datec
$datec
Creation date.
Definition: ticket.class.php:3057
TicketsLine\$message
$message
Ticket message.
Definition: ticket.class.php:3002
Ticket\LibStatut
LibStatut($status, $mode=0, $notooltip=0, $progress=0)
Return status label of object.
Definition: ticket.class.php:1359
image_format_supported
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
Definition: images.lib.php:80
Categorie
Class to manage categories.
Definition: categorie.class.php:47
dol_clone
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
Definition: functions.lib.php:1157
CommonObject
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Definition: commonobject.class.php:44
Ticket\setCategories
setCategories($categories)
Sets object to supplied categories.
Definition: ticket.class.php:2355
Ticket\loadCacheCategoriesTickets
loadCacheCategoriesTickets($publicgroup=-1)
Load into a cache array, the list of ticket categories (setup done into dictionary)
Definition: ticket.class.php:1248
TicketsLine\$date_close
$date_close
Close ticket date.
Definition: ticket.class.php:3072
dol_is_file
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:481
Ticket\searchContactByEmail
searchContactByEmail($email, $socid='', $case='')
Search and fetch contacts by email.
Definition: ticket.class.php:1877
Ticket\assignUser
assignUser($user, $id_assign_user, $notrigger=0)
Mark a message as read.
Definition: ticket.class.php:1559
dol_print_date
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Definition: functions.lib.php:2550
WorkboardResponse
Definition: workboardresponse.class.php:24
dol_concatdesc
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
Definition: functions.lib.php:7542
img_picto
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
Definition: functions.lib.php:4024
Ticket\getLibStatut
getLibStatut($mode=0)
Return status label of object.
Definition: ticket.class.php:1343
TicketsLine\$fk_project
$fk_project
Project ID.
Definition: ticket.class.php:2977
utf8_check
utf8_check($str)
Check if a string is in UTF8.
Definition: functions.lib.php:8766
Ticket\getTicketAllCustomerContacts
getTicketAllCustomerContacts()
Return id of all contacts for ticket.
Definition: ticket.class.php:2071
Ticket\markAsRead
markAsRead($user, $notrigger=0)
Mark a message as read.
Definition: ticket.class.php:1503
TicketsLine\$type_code
$type_code
Type code.
Definition: ticket.class.php:3027
Ticket\setContract
setContract($contractid)
Link element with a contract.
Definition: ticket.class.php:1967
Ticket\load_state_board
load_state_board()
Load indicator this->nb of global stats widget.
Definition: ticket.class.php:2893
getEntity
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
Definition: functions.lib.php:180
TicketsLine\$severity_label
$severity_label
Severity label.
Definition: ticket.class.php:3052
Ticket\getNomUrl
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionaly the picto)
Definition: ticket.class.php:1429
CommonObject\insertExtraFields
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
Definition: commonobject.class.php:6173
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:745
Ticket\$fields
$fields
'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]',...
Definition: ticket.class.php:277
Ticket\printSelectStatus
printSelectStatus($selected="")
Print selected status.
Definition: ticket.class.php:1196
Ticket\loadCacheSeveritiesTickets
loadCacheSeveritiesTickets()
Charge dans cache la liste des sévérité de tickets (paramétrable dans dictionnaire)
Definition: ticket.class.php:1300
Ticket\searchSocidByEmail
searchSocidByEmail($email, $type='0', $filters=array(), $clause='AND')
Search and fetch thirparties by email.
Definition: ticket.class.php:1813
Ticket\loadCacheMsgsTicket
loadCacheMsgsTicket()
Load the list of event on ticket into ->cache_msgs_ticket.
Definition: ticket.class.php:1693
TicketsLine\$severity_code
$severity_code
Severity code.
Definition: ticket.class.php:3037
CommonObject\add_contact
add_contact($fk_socpeople, $type_contact, $source='external', $notrigger=0)
Add a link between element $this->element and a contact.
Definition: commonobject.class.php:1128
CommonObject\commonReplaceThirdparty
static commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
Definition: commonobject.class.php:8479
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1628
Ticket\close
close(User $user, $mode=0)
Close a ticket.
Definition: ticket.class.php:1737
Contact
Class to manage contact/addresses.
Definition: contact.class.php:40
Form\selectarray
static selectarray($htmlname, $array, $id='', $show_empty=0, $key_in_label=0, $value_as_key=0, $moreparam='', $translate=0, $maxlen=0, $disabled=0, $sort='', $morecss='minwidth75', $addjscombo=1, $moreparamonempty='', $disablebademail=0, $nohtmlescape=0)
Return a HTML select string, built from an array of key+value.
Definition: html.form.class.php:8004
Ticket\$email_from
$email_from
Email from user.
Definition: ticket.class.php:169
generate_random_id
generate_random_id($car=16)
Generate a random id.
Definition: ticket.lib.php:194
Ticket\create
create($user, $notrigger=0)
Create object into database.
Definition: ticket.class.php:435
Ticket\initAsSpecimen
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
Definition: ticket.class.php:1163
Ticket\__construct
__construct($db)
Constructor.
Definition: ticket.class.php:314
CommonObject\fetch_optionals
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
Definition: commonobject.class.php:6022
Ticket\getTicketAllContacts
getTicketAllContacts()
Return id of all contacts for ticket.
Definition: ticket.class.php:2051
Ticket\$severity_label
$severity_label
Severity label.
Definition: ticket.class.php:164
Ticket\setProgression
setProgression($percent)
Define progression of current ticket.
Definition: ticket.class.php:1943
getDolGlobalString
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
Definition: functions.lib.php:82
Ticket\newMessage
newMessage($user, &$action, $private=1, $public_area=0)
Add new message on a ticket (private/public area).
Definition: ticket.class.php:2401
dol_strlen
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
Definition: functions.lib.php:3887
Fichinter
Class to manage interventions.
Definition: fichinter.class.php:37
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:137
dolGetFirstLastname
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
Definition: functions.lib.php:8390
Ticket\STATUS_NOT_READ
const STATUS_NOT_READ
Status.
Definition: ticket.class.php:240
User
Class to manage Dolibarr users.
Definition: user.class.php:46
Ticket\getInfosTicketInternalContact
getInfosTicketInternalContact()
Retrieve informations about internal contacts.
Definition: ticket.class.php:2001
ExtraFields
Class to manage standard extra fields.
Definition: extrafields.class.php:39
dolGetStatus
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
Definition: functions.lib.php:10740
Ticket\loadCacheTypesTickets
loadCacheTypesTickets()
Load into a cache the types of tickets (setup done into dictionaries)
Definition: ticket.class.php:1207
Ticket\load_board
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
Definition: ticket.class.php:2825
TicketsLine\$subject
$subject
Ticket subject.
Definition: ticket.class.php:2997
Ticket\copyFilesForTicket
copyFilesForTicket($forcetrackid=null)
Copy files defined into $_SESSION array into the ticket directory of attached files.
Definition: ticket.class.php:2277
img_object
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
Definition: functions.lib.php:4360
Ticket\getDefaultRef
getDefaultRef($thirdparty='')
Get a default reference.
Definition: ticket.class.php:2198
Ticket\setCustomer
setCustomer($id)
Define parent commany of current ticket.
Definition: ticket.class.php:1919
TicketsLine\$resolution
$resolution
State resolution.
Definition: ticket.class.php:3012
Ticket\getIdTicketCustomerInvolvedContact
getIdTicketCustomerInvolvedContact()
Return id des contacts clients des intervenants.
Definition: ticket.class.php:2041
Ticket\createTicketMessage
createTicketMessage($user, $notrigger=0, $filename_list=array(), $mimetype_list=array(), $mimefilename_list=array(), $send_email=false)
Add message into database.
Definition: ticket.class.php:1619
TicketsLine\$track_id
$track_id
Hash to identify ticket.
Definition: ticket.class.php:2967
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:2951
TicketsLine\$category_label
$category_label
Category label.
Definition: ticket.class.php:3047
TicketsLine\$fk_statut
$fk_statut
Ticket statut.
Definition: ticket.class.php:3007
Ticket\verify
verify()
Check properties of ticket are ok (like ref, track_id, ...).
Definition: ticket.class.php:348
Ticket
Class to generate the form for creating a new ticket.
Definition: html.formticket.class.php:32
TicketsLine\$fk_user_assign
$fk_user_assign
User id who have ticket assigned.
Definition: ticket.class.php:2992
CommonObject\call_trigger
call_trigger($triggerName, $user)
Call trigger based on this instance.
Definition: commonobject.class.php:5806
setEventMessages
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
Definition: functions.lib.php:8465
TicketsLine\$category_code
$category_code
Category code.
Definition: ticket.class.php:3032
dol_textishtml
dol_textishtml($msg, $option=0)
Return if a text is a html content.
Definition: functions.lib.php:7475
dol_is_dir
dol_is_dir($folder)
Test if filename is a directory.
Definition: files.lib.php:451
Ticket\getIdTicketCustomerContact
getIdTicketCustomerContact()
Return id des contacts clients pour le suivi ticket.
Definition: ticket.class.php:2011
dirbasename
dirbasename($pathfile)
Return the relative dirname (relative to DOL_DATA_ROOT) of a full path string.
Definition: files.lib.php:3238
Ticket\createFromClone
createFromClone(User $user, $fromid)
Load an object from its id and create a new one in database.
Definition: ticket.class.php:1117
FormMail
Classe permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new For...
Definition: html.formmail.class.php:38
dol_mkdir
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Definition: functions.lib.php:6789
vignette
vignette($file, $maxWidth=160, $maxHeight=120, $extName='_small', $quality=50, $outdir='thumbs', $targetformat=0)
Create a thumbnail from an image file (Supported extensions are gif, jpg, png and bmp).
Definition: images.lib.php:511
Ticket\getInfosTicketExternalContact
getInfosTicketExternalContact()
Retrieve informations about external contacts.
Definition: ticket.class.php:2021
TicketsLine\$fk_user_create
$fk_user_create
User id who have create ticket.
Definition: ticket.class.php:2987
Ticket\$type_label
$type_label
Type label.
Definition: ticket.class.php:154
TicketsLine
Ticket line Class.
Definition: ticket.class.php:2946
Ticket\getIdTicketInternalInvolvedContact
getIdTicketInternalInvolvedContact()
Return id des contacts clients des intervenants.
Definition: ticket.class.php:2031
Ticket\$subject
$subject
var string Ticket subject
Definition: ticket.class.php:102
dol_move
dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=1)
Move a file into another name.
Definition: files.lib.php:875
Ticket\fetch
fetch($id='', $ref='', $track_id='', $email_msgid='')
Load object in memory from the database.
Definition: ticket.class.php:576