20use Luracast\Restler\RestException;
22require_once DOL_DOCUMENT_ROOT.
'/ticket/class/ticket.class.php';
23require_once DOL_DOCUMENT_ROOT.
'/core/lib/ticket.lib.php';
37 public static $FIELDS = array(
45 public static $FIELDS_MESSAGES = array(
62 $this->ticket =
new Ticket($this->db);
78 public function get(
$id, $contact_list = 1)
100 return $this->
getCommon(0, $track_id,
'', $contact_list);
120 return $this->
getCommon(0,
'', $ref, $contact_list);
133 private function getCommon(
$id = 0, $track_id =
'', $ref =
'', $contact_list = 1)
137 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'read')) {
138 throw new RestException(403);
142 if ((
$id < 0) && !$track_id && !$ref) {
143 throw new RestException(400,
'Wrong parameters');
145 if (empty(
$id) && empty($ref) && empty($track_id)) {
146 $result = $this->ticket->initAsSpecimen();
148 $result = $this->ticket->fetch(
$id, $ref, $track_id);
151 throw new RestException(404,
'Ticket not found');
157 $this->ticket->loadCacheMsgsTicket();
159 if (is_array($this->ticket->cache_msgs_ticket) && count($this->ticket->cache_msgs_ticket) > 0) {
160 $num = count($this->ticket->cache_msgs_ticket);
163 $iduseraction = $this->ticket->cache_msgs_ticket[$i][
'fk_user_action'];
164 if ($iduseraction > 0) {
165 if (empty(
$conf->cache[
'user'][$iduseraction])) {
166 $user_action =
new User($this->db);
167 $user_action->fetch($iduseraction);
169 $conf->cache[
'user'][$iduseraction] = $user_action;
171 $user_action =
$conf->cache[
'user'][$iduseraction];
179 'id' => $this->ticket->cache_msgs_ticket[$i][
'id'],
180 'fk_user_action' => $this->ticket->cache_msgs_ticket[$i][
'fk_user_action'],
181 'fk_user_action_socid' => $user_action ===
null ?
'' : $user_action->socid,
182 'fk_user_action_string' => $user_action ===
null ?
'' :
dolGetFirstLastname($user_action->firstname, $user_action->lastname),
183 'datec' => $this->ticket->cache_msgs_ticket[$i][
'datec'],
184 'datep' => $this->ticket->cache_msgs_ticket[$i][
'datep'],
185 'subject' => $this->ticket->cache_msgs_ticket[$i][
'subject'],
186 'message' => $this->ticket->cache_msgs_ticket[$i][
'message'],
187 'private' => $this->ticket->cache_msgs_ticket[$i][
'private']
191 $this->ticket->messages = $messages;
195 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
198 if ($contact_list > -1) {
200 $tmparray = $this->ticket->liste_contact(-1,
'external', $contact_list);
201 if (is_array($tmparray)) {
202 $this->ticket->contacts_ids = $tmparray;
204 $tmparray = $this->ticket->liste_contact(-1,
'internal', $contact_list);
205 if (is_array($tmparray)) {
206 $this->ticket->contacts_ids_internal = $tmparray;
232 public function index($socid = 0, $sortfield =
"t.rowid", $sortorder =
"ASC", $limit = 100, $page = 0, $sqlfilters =
'', $properties =
'', $loadcontacts = 0, $pagination_data =
false)
234 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'read')) {
235 throw new RestException(403);
240 $socid = DolibarrApiAccess::$user->socid ?: $socid;
245 if (!DolibarrApiAccess::$user->hasRight(
'societe',
'client',
'voir') && !$socid) {
246 $search_sale = DolibarrApiAccess::$user->id;
249 $sql =
"SELECT t.rowid";
250 $sql .=
" FROM ".MAIN_DB_PREFIX.
"ticket AS t";
251 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe AS s ON (s.rowid = t.fk_soc)";
252 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"ticket_extrafields AS ef ON (ef.fk_object = t.rowid)";
253 $sql .=
' WHERE t.entity IN ('.getEntity(
'ticket', 1).
')';
255 $sql .=
" AND t.fk_soc = ".((int) $socid);
258 if ($search_sale && $search_sale !=
'-1') {
259 if ($search_sale == -2) {
260 $sql .=
" AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc)";
261 } elseif ($search_sale > 0) {
262 $sql .=
" AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX.
"societe_commerciaux as sc WHERE sc.fk_soc = t.fk_soc AND sc.fk_user = ".((int) $search_sale).
")";
268 $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
270 throw new RestException(400,
'Error when validating parameter sqlfilters -> '.$errormessage);
275 $sqlTotals = str_replace(
'SELECT t.rowid',
'SELECT count(t.rowid) as total', $sql);
277 $sql .= $this->db->order($sortfield, $sortorder);
283 $offset = $limit * $page;
285 $sql .= $this->db->plimit($limit, $offset);
288 $result = $this->db->query($sql);
291 $num = $this->db->num_rows($result);
292 $min = min($num, ($limit <= 0 ? $num : $limit));
294 $obj = $this->db->fetch_object($result);
295 $ticket_static =
new Ticket($this->db);
296 if ($ticket_static->fetch($obj->rowid)) {
297 if ($ticket_static->fk_user_assign > 0) {
298 $userStatic =
new User($this->db);
299 $userStatic->fetch($ticket_static->fk_user_assign);
305 $tmparray = $ticket_static->liste_contact(-1,
'external', 1);
306 if (is_array($tmparray)) {
307 $ticket_static->contacts_ids = $tmparray;
309 $tmparray = $ticket_static->liste_contact(-1,
'internal', 1);
310 if (is_array($tmparray)) {
311 $ticket_static->contacts_ids_internal = $tmparray;
320 throw new RestException(503,
'Error when retrieve ticket list');
324 if ($pagination_data) {
325 $totalsResult = $this->db->query($sqlTotals);
326 $total = $this->db->fetch_object($totalsResult)->total;
331 $obj_ret[
'data'] = $tmp;
332 $obj_ret[
'pagination'] = [
333 'total' => (int) $total,
335 'page_count' => ceil((
int) $total / $limit),
351 public function post($request_data =
null)
353 $ticketstatic =
new Ticket($this->db);
354 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
355 throw new RestException(403);
362 $socid = (int) $request_data[
'socid'];
364 $thirdpartytmp =
new Societe($this->db);
365 $thirdparty_result = $thirdpartytmp->fetch($socid);
366 if ($thirdparty_result < 1) {
367 throw new RestException(404,
'Thirdparty with id='.$socid.
' not found or not allowed');
370 throw new RestException(404,
'Thirdparty with id='.$thirdpartytmp->id.
' not found or not allowed');
374 foreach ($request_data as $field => $value) {
375 if ($field ===
'caller') {
377 $this->ticket->context[
'caller'] =
sanitizeVal($request_data[
'caller'],
'aZ09');
381 $this->ticket->$field = $this->
_checkValForAPI($field, $value, $this->ticket);
383 if (empty($this->ticket->ref)) {
384 $this->ticket->ref = $ticketstatic->getDefaultRef();
386 if (empty($this->ticket->track_id)) {
390 if ($this->ticket->create(DolibarrApiAccess::$user) < 0) {
391 throw new RestException(500,
"Error creating ticket", array_merge(array($this->ticket->error), $this->ticket->errors));
394 return $this->ticket->id;
409 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
410 throw new RestException(403);
416 $return_action_id =
false;
417 if (isset($request_data[
'return_action_id'])) {
418 $return_action_id = !empty($request_data[
'return_action_id']);
419 unset($request_data[
'return_action_id']);
422 $attachments = array();
423 if (isset($request_data[
'attachments']) && is_array($request_data[
'attachments'])) {
424 $attachments = $request_data[
'attachments'];
425 unset($request_data[
'attachments']);
428 foreach ($request_data as $field => $value) {
429 if ($field ===
'caller') {
431 $this->ticket->context[
'caller'] =
sanitizeVal($request_data[
'caller'],
'aZ09');
435 $this->ticket->$field = $this->
_checkValForAPI($field, $value, $this->ticket);
437 $ticketMessageText = $this->ticket->message;
438 $result = $this->ticket->fetch(0,
'', $this->ticket->track_id);
440 throw new RestException(404,
'Ticket not found');
444 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
447 $this->ticket->message = $ticketMessageText;
449 $filename_list = array();
450 $mimetype_list = array();
451 $mimefilename_list = array();
452 if (!empty($attachments)) {
454 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
456 $destdir =
$conf->ticket->dir_output.
'/'.$this->ticket->ref;
458 throw new RestException(500,
'Error while trying to create directory '.$destdir);
461 foreach ($attachments as $attachment) {
462 if (!is_array($attachment) || empty($attachment[
'filename'])) {
467 if (empty($filename)) {
471 $filecontent = isset($attachment[
'filecontent']) ? $attachment[
'filecontent'] :
'';
472 $fileencoding = isset($attachment[
'fileencoding']) ? $attachment[
'fileencoding'] :
'';
473 $content = ($fileencoding ===
'base64') ? base64_decode($filecontent) : $filecontent;
474 if ($content ===
false) {
475 throw new RestException(400,
'Failed to decode attachment '.$filename);
478 $destfile = $destdir.
'/'.$filename;
479 if (is_file($destfile)) {
480 $pathinfo = pathinfo($filename);
481 $suffix =
' - '.dol_print_date(
dol_now(),
'dayhourlog');
482 $extension = !empty($pathinfo[
'extension']) ?
'.'.$pathinfo[
'extension'] :
'';
483 $basename = !empty($pathinfo[
'filename']) ? $pathinfo[
'filename'] : preg_replace(
'/\.[^.]+$/',
'', $filename);
484 $destfile = $destdir.
'/'.$basename.$suffix.$extension;
487 $destfiletmp = DOL_DATA_ROOT.
'/admin/temp/'.basename($destfile);
492 $fhandle = @fopen($destfiletmp,
'w');
494 throw new RestException(500,
"Failed to open file '".$destfiletmp.
"' for write");
496 $nbofbyteswrote = fwrite($fhandle, $content);
498 if ($nbofbyteswrote ===
false) {
499 throw new RestException(500,
"Failed to write file '".$destfiletmp.
"'");
503 'description' =>
'File uploaded using ticket API',
504 'src_object_type' => $this->ticket->element,
505 'src_object_id' => $this->ticket->id,
506 'gen_or_uploaded' =>
'uploaded'
508 $resultmove =
dol_move($destfiletmp, $destfile,
'0', 1, 0, 1, $moreinfo);
510 throw new RestException(500,
"Failed to move file into '".$destfile.
"'");
513 $filename_list[] = $destfile;
514 $mimefilename_list[] = basename($destfile);
515 $mimetype_list[] = !empty($attachment[
'mimetype']) ? $attachment[
'mimetype'] :
'';
519 $actionid = $this->ticket->createTicketMessage(DolibarrApiAccess::$user, 0, $filename_list, $mimetype_list, $mimefilename_list);
520 if ($actionid <= 0) {
521 throw new RestException(500,
'Error when creating ticket');
523 if ($return_action_id) {
524 return array(
'ticket_id' => $this->ticket->id,
'action_id' => $actionid);
526 return $this->ticket->id;
538 public function put(
$id, $request_data =
null)
540 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
541 throw new RestException(403);
544 $result = $this->ticket->fetch(
$id);
546 throw new RestException(404,
'Ticket not found');
550 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
554 $socid = (int) $request_data[
'socid'];
556 $thirdpartytmp =
new Societe($this->db);
557 $thirdparty_result = $thirdpartytmp->fetch($socid);
558 if ($thirdparty_result < 1) {
559 throw new RestException(404,
'Thirdparty with id='.$socid.
' not found or not allowed');
562 throw new RestException(404,
'Thirdparty with id='.$thirdpartytmp->id.
' not found or not allowed');
566 foreach ($request_data as $field => $value) {
567 if ($field ===
'caller') {
569 $this->ticket->context[
'caller'] =
sanitizeVal($request_data[
'caller'],
'aZ09');
573 if ($field ==
'id') {
576 if ($field ==
'array_options' && is_array($value)) {
577 foreach ($value as $index => $val) {
583 $this->ticket->$field = $this->
_checkValForAPI($field, $value, $this->ticket);
586 if ($this->ticket->update(DolibarrApiAccess::$user) > 0) {
587 return $this->
get(
$id);
589 throw new RestException(500, $this->ticket->error);
601 public function delete(
$id)
603 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'delete')) {
604 throw new RestException(403);
606 $result = $this->ticket->fetch(
$id);
608 throw new RestException(404,
'Ticket not found');
612 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
615 if (!$this->ticket->delete(DolibarrApiAccess::$user)) {
616 throw new RestException(500,
'Error when deleting ticket');
622 'message' =>
'Ticket deleted'
637 if ($data ===
null) {
641 foreach (Tickets::$FIELDS as $field) {
642 if (!isset($data[$field])) {
643 throw new RestException(400,
"$field field missing");
645 $ticket[$field] = $data[$field];
660 if ($data ===
null) {
664 foreach (Tickets::$FIELDS_MESSAGES as $field) {
665 if (!isset($data[$field])) {
666 throw new RestException(400,
"$field field missing");
668 $ticket[$field] = $data[$field];
697 "table_element_line",
704 "barcode_type_label",
705 "barcode_type_coder",
709 "fk_delivery_address",
710 "shipping_method_id",
723 "location_incoterms",
731 "cache_types_tickets",
735 "multicurrency_code",
737 "multicurrency_total_ht",
738 "multicurrency_total_ttc",
739 "multicurrency_total_tva",
740 "multicurrency_total_localtax1",
741 "multicurrency_total_localtax2"
743 foreach ($attr2clean as $toclean) {
749 $nboflines = count(
$object->lines);
750 for ($i = 0; $i < $nboflines; $i++) {
756 if (isset(
$object->linkedObjects) && count(
$object->linkedObjects) > 0) {
757 foreach (
$object->linkedObjects as $type_object => $linked_object) {
758 foreach ($linked_object as $object2clean) {
786 public function postContact(
int $id,
int $contactid,
string $type,
string $source =
"external",
int $notrigger = 0): array
789 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
790 throw new RestException(403);
794 if (empty($source)) {
795 throw new RestException(400,
'Source can not be empty');
799 throw new RestException(400,
'type can not be empty');
803 $sqlCheckTypeSource =
"SELECT tc.rowid";
804 $sqlCheckTypeSource .=
" FROM ".$this->db->prefix().
"c_type_contact as tc";
805 $sqlCheckTypeSource .=
" WHERE tc.element LIKE 'ticket'";
806 $sqlCheckTypeSource .=
" AND tc.source = '".$this->db->escape($source).
"'";
807 $sqlCheckTypeSource .=
" AND tc.code = '".$this->db->escape($type).
"'";
808 $sqlCheckTypeSource .=
" AND tc.active = 1";
809 $result = $this->db->query($sqlCheckTypeSource);
811 if ($result && $this->db->num_rows($result) == 0) {
812 throw new RestException(400,
'Contact type not found');
816 if ($source ==
"external") {
818 $sqlCheckExternalContact =
"SELECT 1 as exist";
819 $sqlCheckExternalContact .=
" FROM llx_socpeople";
820 $sqlCheckExternalContact .=
" WHERE rowid = " . intval($contactid);
821 $result = $this->db->query($sqlCheckExternalContact);
823 if ($result && $this->db->num_rows($result) == 0) {
824 throw new RestException(404,
'External contact not found');
828 $sqlCheckInternalContact =
"SELECT 1 as exist";
829 $sqlCheckInternalContact .=
" FROM llx_user";
830 $sqlCheckInternalContact .=
" WHERE rowid = " . intval($contactid);
831 $result = $this->db->query($sqlCheckInternalContact);
833 if ($result && $this->db->num_rows($result) == 0) {
834 throw new RestException(404,
'Internal contact not found');
839 $result = $this->ticket->fetch(
$id);
841 throw new RestException(404,
'Ticket not found');
844 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
847 $result = $this->ticket->add_contact($contactid, $type, $source, $notrigger);
850 throw new RestException(400,
'Already exists: Contact='.$contactid.
' is already linked to the ticket='.
$id.
' as source='.$source.
' and type='.$type);
851 } elseif ($result == -1) {
852 throw new RestException(400,
'Wrong contact='.$contactid);
853 } elseif ($result == -2) {
854 throw new RestException(400,
'Wrong type='.$type);
855 } elseif ($result == -3) {
856 throw new RestException(400,
'Not allowed contacts');
857 } elseif ($result == -4) {
858 throw new RestException(400,
'ErrorCommercialNotAllowedForThirdparty');
859 } elseif ($result == -5) {
860 throw new RestException(400,
'Trigger failed');
861 } elseif ($result == -6) {
862 throw new RestException(400,
'DB_ERROR_RECORD_ALREADY_EXISTS');
863 } elseif ($result == -7) {
864 throw new RestException(400,
'Some other error');
865 } elseif ($result <= -8) {
866 throw new RestException(400,
'Unknown error occurred');
872 'message' =>
'Contact='.$contactid.
' linked to the ticket='.
$id.
' as '.$source.
' '.$type
896 public function deleteContact(
int $id,
int $contactid,
string $type,
string $source =
"external"): array
899 if (!DolibarrApiAccess::$user->hasRight(
'ticket',
'write')) {
900 throw new RestException(403);
904 if (empty($source)) {
905 throw new RestException(400,
'Source can not be empty');
909 throw new RestException(400,
'type can not be empty');
912 $result = $this->ticket->fetch(
$id);
914 throw new RestException(404,
'Ticket not found');
918 throw new RestException(403,
'Access not allowed for login '.DolibarrApiAccess::$user->login);
921 $contacts = $this->ticket->liste_contact(-1, $source);
922 foreach ($contacts as $contact) {
923 if ($contact[
'id'] == $contactid && $contact[
'code'] == $type) {
924 $result = $this->ticket->delete_contact($contact[
'rowid']);
927 throw new RestException(500,
'Error when deleting the contact '.$contact[
'rowid']);
935 'message' =>
'Contact unlinked from ticket'
$id
Support class for third parties, contacts, members, users or resources.
if(! $sortfield) if(! $sortorder) $object
_checkValExtrafieldsForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
_filterObjectProperties($object, $properties)
Filter properties that will be returned on object.
static _checkAccessToResource($resource, $resource_id=0, $dbtablename='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid')
Check access by user to a given resource.
_checkValForAPI($field, $value, $object)
Check and convert a string depending on its type/name.
Class to manage third parties objects (customers, suppliers, prospects...)
getByTrackId($track_id, $contact_list=1)
Get properties of a Ticket object from track id.
deleteContact(int $id, int $contactid, string $type, string $source="external")
Unlink a contact type of given ticket.
getCommon($id=0, $track_id='', $ref='', $contact_list=1)
Get properties of a Ticket object Return an array with ticket information.
__construct()
Constructor.
index($socid=0, $sortfield="t.rowid", $sortorder="ASC", $limit=100, $page=0, $sqlfilters='', $properties='', $loadcontacts=0, $pagination_data=false)
List tickets.
_cleanObjectDatas($object)
Clean sensible object datas @phpstan-template T.
postNewMessage($request_data=null)
Add a new message to an existing ticket identified by property ->track_id into request.
post($request_data=null)
Create ticket object.
put($id, $request_data=null)
Update ticket.
_validateMessage($data)
Validate fields before create or update object message.
postContact(int $id, int $contactid, string $type, string $source="external", int $notrigger=0)
Add a contact type of given ticket.
getByRef($ref, $contact_list=1)
Get properties of a Ticket object from ref.
_validate($data)
Validate fields before create or update object.
Class to manage Dolibarr users.
dol_move($srcfile, $destfile, $newmask='0', $overwriteifexists=1, $testvirus=0, $indexdatabase=1, $moreinfo=array(), $entity=null)
Move a file into another name.
dol_is_dir($folder)
Test if filename is a directory.
dol_now($mode='gmt')
Return date for now.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
sanitizeVal($out='', $check='alphanohtml', $filter=null, $options=null)
Return a sanitized or empty value after checking value against a rule.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Class to generate the form for creating a new ticket.
generate_random_id($car=16)
Generate a random id.