dolibarr  16.0.1
api_tickets.class.php
1 <?php
2 /* Copyright (C) 2016 Jean-François Ferry <hello@librethic.io>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18  use Luracast\Restler\RestException;
19 
20 require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
21 require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php';
22 
23 
30 class Tickets extends DolibarrApi
31 {
35  public static $FIELDS = array(
36  'subject',
37  'message'
38  );
39 
43  public static $FIELDS_MESSAGES = array(
44  'track_id',
45  'message'
46  );
47 
51  public $ticket;
52 
56  public function __construct()
57  {
58  global $db;
59  $this->db = $db;
60  $this->ticket = new Ticket($this->db);
61  }
62 
75  public function get($id)
76  {
77  return $this->getCommon($id, '', '');
78  }
79 
94  public function getByTrackId($track_id)
95  {
96  return $this->getCommon(0, $track_id, '');
97  }
98 
113  public function getByRef($ref)
114  {
115  try {
116  return $this->getCommon(0, '', $ref);
117  } catch (Exception $e) {
118  throw $e;
119  }
120  }
121 
131  private function getCommon($id = 0, $track_id = '', $ref = '')
132  {
133  if (!DolibarrApiAccess::$user->rights->ticket->read) {
134  throw new RestException(403);
135  }
136 
137  // Check parameters
138  if (($id < 0) && !$track_id && !$ref) {
139  throw new RestException(401, 'Wrong parameters');
140  }
141  if ($id == 0) {
142  $result = $this->ticket->initAsSpecimen();
143  } else {
144  $result = $this->ticket->fetch($id, $ref, $track_id);
145  }
146  if (!$result) {
147  throw new RestException(404, 'Ticket not found');
148  }
149 
150  // String for user assigned
151  if ($this->ticket->fk_user_assign > 0) {
152  $userStatic = new User($this->db);
153  $userStatic->fetch($this->ticket->fk_user_assign);
154  $this->ticket->fk_user_assign_string = $userStatic->firstname.' '.$userStatic->lastname;
155  }
156 
157  // Messages of ticket
158  $messages = array();
159  $this->ticket->loadCacheMsgsTicket();
160  if (is_array($this->ticket->cache_msgs_ticket) && count($this->ticket->cache_msgs_ticket) > 0) {
161  $num = count($this->ticket->cache_msgs_ticket);
162  $i = 0;
163  while ($i < $num) {
164  if ($this->ticket->cache_msgs_ticket[$i]['fk_user_author'] > 0) {
165  $user_action = new User($this->db);
166  $user_action->fetch($this->ticket->cache_msgs_ticket[$i]['fk_user_author']);
167  }
168 
169  // Now define messages
170  $messages[] = array(
171  'id' => $this->ticket->cache_msgs_ticket[$i]['id'],
172  'fk_user_action' => $this->ticket->cache_msgs_ticket[$i]['fk_user_author'],
173  'fk_user_action_socid' => $user_action->socid,
174  'fk_user_action_string' => dolGetFirstLastname($user_action->firstname, $user_action->lastname),
175  'message' => $this->ticket->cache_msgs_ticket[$i]['message'],
176  'datec' => $this->ticket->cache_msgs_ticket[$i]['datec'],
177  'private' => $this->ticket->cache_msgs_ticket[$i]['private']
178  );
179  $i++;
180  }
181  $this->ticket->messages = $messages;
182  }
183 
184  // History
185  $history = array();
186  $this->ticket->loadCacheLogsTicket();
187  if (is_array($this->ticket->cache_logs_ticket) && count($this->ticket->cache_logs_ticket) > 0) {
188  $num = count($this->ticket->cache_logs_ticket);
189  $i = 0;
190  while ($i < $num) {
191  if ($this->ticket->cache_logs_ticket[$i]['fk_user_create'] > 0) {
192  $user_action = new User($this->db);
193  $user_action->fetch($this->ticket->cache_logs_ticket[$i]['fk_user_create']);
194  }
195 
196  // Now define messages
197  $history[] = array(
198  'id' => $this->ticket->cache_logs_ticket[$i]['id'],
199  'fk_user_author' => $this->ticket->cache_msgs_ticket[$i]['fk_user_author'],
200  'fk_user_action' => $this->ticket->cache_logs_ticket[$i]['fk_user_create'],
201  'fk_user_action_string' => dolGetFirstLastname($user_action->firstname, $user_action->lastname),
202  'message' => $this->ticket->cache_logs_ticket[$i]['message'],
203  'datec' => $this->ticket->cache_logs_ticket[$i]['datec'],
204  );
205  $i++;
206  }
207  $this->ticket->history = $history;
208  }
209 
210  if (!DolibarrApi::_checkAccessToResource('ticket', $this->ticket->id)) {
211  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
212  }
213  return $this->_cleanObjectDatas($this->ticket);
214  }
215 
231  public function index($socid = 0, $sortfield = "t.rowid", $sortorder = "ASC", $limit = 100, $page = 0, $sqlfilters = '')
232  {
233  global $db, $conf;
234 
235  if (!DolibarrApiAccess::$user->rights->ticket->read) {
236  throw new RestException(403);
237  }
238 
239  $obj_ret = array();
240 
241  if (!$socid && DolibarrApiAccess::$user->socid) {
242  $socid = DolibarrApiAccess::$user->socid;
243  }
244 
245  // If the internal user must only see his customers, force searching by him
246  if (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) {
247  $search_sale = DolibarrApiAccess::$user->id;
248  }
249 
250  $sql = "SELECT t.rowid";
251  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
252  $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
253  }
254  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
255 
256  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
257  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
258  }
259 
260  $sql .= ' WHERE t.entity IN ('.getEntity('ticket', 1).')';
261  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
262  $sql .= " AND t.fk_soc = sc.fk_soc";
263  }
264  if ($socid > 0) {
265  $sql .= " AND t.fk_soc = ".((int) $socid);
266  }
267  if ($search_sale > 0) {
268  $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
269  }
270 
271  // Insert sale filter
272  if ($search_sale > 0) {
273  $sql .= " AND sc.fk_user = ".((int) $search_sale);
274  }
275  // Add sql filters
276  if ($sqlfilters) {
277  $errormessage = '';
278  if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
279  throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
280  }
281  $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
282  $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
283  }
284 
285  $sql .= $this->db->order($sortfield, $sortorder);
286 
287  if ($limit) {
288  if ($page < 0) {
289  $page = 0;
290  }
291  $offset = $limit * $page;
292 
293  $sql .= $this->db->plimit($limit, $offset);
294  }
295 
296  $result = $this->db->query($sql);
297  if ($result) {
298  $num = $this->db->num_rows($result);
299  $i = 0;
300  while ($i < $num) {
301  $obj = $this->db->fetch_object($result);
302  $ticket_static = new Ticket($this->db);
303  if ($ticket_static->fetch($obj->rowid)) {
304  if ($ticket_static->fk_user_assign > 0) {
305  $userStatic = new User($this->db);
306  $userStatic->fetch($ticket_static->fk_user_assign);
307  $ticket_static->fk_user_assign_string = $userStatic->firstname.' '.$userStatic->lastname;
308  }
309  $obj_ret[] = $this->_cleanObjectDatas($ticket_static);
310  }
311  $i++;
312  }
313  } else {
314  throw new RestException(503, 'Error when retrieve ticket list');
315  }
316  if (!count($obj_ret)) {
317  throw new RestException(404, 'No ticket found');
318  }
319  return $obj_ret;
320  }
321 
328  public function post($request_data = null)
329  {
330  $ticketstatic = new Ticket($this->db);
331  if (!DolibarrApiAccess::$user->rights->ticket->write) {
332  throw new RestException(401);
333  }
334  // Check mandatory fields
335  $result = $this->_validate($request_data);
336 
337  foreach ($request_data as $field => $value) {
338  $this->ticket->$field = $value;
339  }
340  if (empty($this->ticket->ref)) {
341  $this->ticket->ref = $ticketstatic->getDefaultRef();
342  }
343  if (empty($this->ticket->track_id)) {
344  $this->ticket->track_id = generate_random_id(16);
345  }
346 
347  if ($this->ticket->create(DolibarrApiAccess::$user) < 0) {
348  throw new RestException(500, "Error creating ticket", array_merge(array($this->ticket->error), $this->ticket->errors));
349  }
350 
351  return $this->ticket->id;
352  }
353 
361  public function postNewMessage($request_data = null)
362  {
363  $ticketstatic = new Ticket($this->db);
364  if (!DolibarrApiAccess::$user->rights->ticket->write) {
365  throw new RestException(401);
366  }
367  // Check mandatory fields
368  $result = $this->_validateMessage($request_data);
369 
370  foreach ($request_data as $field => $value) {
371  $this->ticket->$field = $value;
372  }
373  $ticketMessageText = $this->ticket->message;
374  $result = $this->ticket->fetch('', '', $this->ticket->track_id);
375  if (!$result) {
376  throw new RestException(404, 'Ticket not found');
377  }
378  $this->ticket->message = $ticketMessageText;
379  if (!$this->ticket->createTicketMessage(DolibarrApiAccess::$user)) {
380  throw new RestException(500, 'Error when creating ticket');
381  }
382  return $this->ticket->id;
383  }
384 
393  public function put($id, $request_data = null)
394  {
395  if (!DolibarrApiAccess::$user->rights->ticket->write) {
396  throw new RestException(401);
397  }
398 
399  $result = $this->ticket->fetch($id);
400  if (!$result) {
401  throw new RestException(404, 'Ticket not found');
402  }
403 
404  if (!DolibarrApi::_checkAccessToResource('ticket', $this->ticket->id)) {
405  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
406  }
407 
408  foreach ($request_data as $field => $value) {
409  $this->ticket->$field = $value;
410  }
411 
412  if ($this->ticket->update($id, DolibarrApiAccess::$user)) {
413  return $this->get($id);
414  }
415 
416  return false;
417  }
418 
426  public function delete($id)
427  {
428  if (!DolibarrApiAccess::$user->rights->ticket->delete) {
429  throw new RestException(401);
430  }
431  $result = $this->ticket->fetch($id);
432  if (!$result) {
433  throw new RestException(404, 'Ticket not found');
434  }
435 
436  if (!DolibarrApi::_checkAccessToResource('ticket', $this->ticket->id)) {
437  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
438  }
439 
440  if (!$this->ticket->delete($id)) {
441  throw new RestException(500, 'Error when deleting ticket');
442  }
443 
444  return array(
445  'success' => array(
446  'code' => 200,
447  'message' => 'Ticket deleted'
448  )
449  );
450  }
451 
460  private function _validate($data)
461  {
462  $ticket = array();
463  foreach (Tickets::$FIELDS as $field) {
464  if (!isset($data[$field])) {
465  throw new RestException(400, "$field field missing");
466  }
467  $ticket[$field] = $data[$field];
468  }
469  return $ticket;
470  }
471 
480  private function _validateMessage($data)
481  {
482  $ticket = array();
483  foreach (Tickets::$FIELDS_MESSAGES as $field) {
484  if (!isset($data[$field])) {
485  throw new RestException(400, "$field field missing");
486  }
487  $ticket[$field] = $data[$field];
488  }
489  return $ticket;
490  }
491 
492  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
502  protected function _cleanObjectDatas($object)
503  {
504  // phpcs:enable
505  $object = parent::_cleanObjectDatas($object);
506 
507  // Other attributes to clean
508  $attr2clean = array(
509  "contact",
510  "contact_id",
511  "ref_previous",
512  "ref_next",
513  "ref_ext",
514  "table_element_line",
515  "statut",
516  "country",
517  "country_id",
518  "country_code",
519  "barcode_type",
520  "barcode_type_code",
521  "barcode_type_label",
522  "barcode_type_coder",
523  "mode_reglement_id",
524  "cond_reglement_id",
525  "cond_reglement",
526  "fk_delivery_address",
527  "shipping_method_id",
528  "modelpdf",
529  "fk_account",
530  "note_public",
531  "note_private",
532  "note",
533  "total_ht",
534  "total_tva",
535  "total_localtax1",
536  "total_localtax2",
537  "total_ttc",
538  "fk_incoterms",
539  "label_incoterms",
540  "location_incoterms",
541  "name",
542  "lastname",
543  "firstname",
544  "civility_id",
545  "canvas",
546  "cache_msgs_ticket",
547  "cache_logs_ticket",
548  "cache_types_tickets",
549  "cache_category_tickets",
550  "regeximgext",
551  "statuts_short",
552  "statuts"
553  );
554  foreach ($attr2clean as $toclean) {
555  unset($object->$toclean);
556  }
557 
558  // If object has lines, remove $db property
559  if (isset($object->lines) && count($object->lines) > 0) {
560  $nboflines = count($object->lines);
561  for ($i = 0; $i < $nboflines; $i++) {
562  $this->_cleanObjectDatas($object->lines[$i]);
563  }
564  }
565 
566  // If object has linked objects, remove $db property
567  if (isset($object->linkedObjects) && count($object->linkedObjects) > 0) {
568  foreach ($object->linkedObjects as $type_object => $linked_object) {
569  foreach ($linked_object as $object2clean) {
570  $this->_cleanObjectDatas($object2clean);
571  }
572  }
573  }
574  return $object;
575  }
576 }
getCommon($id=0, $track_id= '', $ref= '')
Get properties of a Ticket object Return an array with ticket informations.
_validateMessage($data)
Validate fields before create or update object message.
index($socid=0, $sortfield="t.rowid", $sortorder="ASC", $limit=100, $page=0, $sqlfilters= '')
List tickets.
getByTrackId($track_id)
Get properties of a Ticket object from track id.
$conf db
API class for accounts.
Definition: inc.php:41
postNewMessage($request_data=null)
Create ticket object.
Class to manage Dolibarr users.
Definition: user.class.php:44
Class to manage ticket.
_checkFilters($sqlfilters, &$error= '')
Return if a $sqlfilters parameter is valid.
Definition: api.class.php:310
Class for API REST v1.
Definition: api.class.php:30
_cleanObjectDatas($object)
Clean sensible object datas.
generate_random_id($car=16)
Generate a random id.
Definition: ticket.lib.php:184
__construct()
Constructor.
getByRef($ref)
Get properties of a Ticket object from ref.
static _checkAccessToResource($resource, $resource_id=0, $dbtablename= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid')
Check access by user to a given resource.
Definition: api.class.php:283
put($id, $request_data=null)
Update ticket.
_validate($data)
Validate fields before create or update object.
post($request_data=null)
Create ticket object.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.