dolibarr  16.0.5
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  $search_sale = null;
246  // If the internal user must only see his customers, force searching by him
247  if (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) {
248  $search_sale = DolibarrApiAccess::$user->id;
249  }
250 
251  $sql = "SELECT t.rowid";
252  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
253  $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)
254  }
255  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
256 
257  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
258  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
259  }
260 
261  $sql .= ' WHERE t.entity IN ('.getEntity('ticket', 1).')';
262  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
263  $sql .= " AND t.fk_soc = sc.fk_soc";
264  }
265  if ($socid > 0) {
266  $sql .= " AND t.fk_soc = ".((int) $socid);
267  }
268  if ($search_sale > 0) {
269  $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
270  }
271 
272  // Insert sale filter
273  if ($search_sale > 0) {
274  $sql .= " AND sc.fk_user = ".((int) $search_sale);
275  }
276  // Add sql filters
277  if ($sqlfilters) {
278  $errormessage = '';
279  if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
280  throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
281  }
282  $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
283  $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
284  }
285 
286  $sql .= $this->db->order($sortfield, $sortorder);
287 
288  if ($limit) {
289  if ($page < 0) {
290  $page = 0;
291  }
292  $offset = $limit * $page;
293 
294  $sql .= $this->db->plimit($limit, $offset);
295  }
296 
297  $result = $this->db->query($sql);
298  if ($result) {
299  $num = $this->db->num_rows($result);
300  $i = 0;
301  while ($i < $num) {
302  $obj = $this->db->fetch_object($result);
303  $ticket_static = new Ticket($this->db);
304  if ($ticket_static->fetch($obj->rowid)) {
305  if ($ticket_static->fk_user_assign > 0) {
306  $userStatic = new User($this->db);
307  $userStatic->fetch($ticket_static->fk_user_assign);
308  $ticket_static->fk_user_assign_string = $userStatic->firstname.' '.$userStatic->lastname;
309  }
310  $obj_ret[] = $this->_cleanObjectDatas($ticket_static);
311  }
312  $i++;
313  }
314  } else {
315  throw new RestException(503, 'Error when retrieve ticket list');
316  }
317  if (!count($obj_ret)) {
318  throw new RestException(404, 'No ticket found');
319  }
320  return $obj_ret;
321  }
322 
329  public function post($request_data = null)
330  {
331  $ticketstatic = new Ticket($this->db);
332  if (!DolibarrApiAccess::$user->rights->ticket->write) {
333  throw new RestException(401);
334  }
335  // Check mandatory fields
336  $result = $this->_validate($request_data);
337 
338  foreach ($request_data as $field => $value) {
339  $this->ticket->$field = $value;
340  }
341  if (empty($this->ticket->ref)) {
342  $this->ticket->ref = $ticketstatic->getDefaultRef();
343  }
344  if (empty($this->ticket->track_id)) {
345  $this->ticket->track_id = generate_random_id(16);
346  }
347 
348  if ($this->ticket->create(DolibarrApiAccess::$user) < 0) {
349  throw new RestException(500, "Error creating ticket", array_merge(array($this->ticket->error), $this->ticket->errors));
350  }
351 
352  return $this->ticket->id;
353  }
354 
362  public function postNewMessage($request_data = null)
363  {
364  $ticketstatic = new Ticket($this->db);
365  if (!DolibarrApiAccess::$user->rights->ticket->write) {
366  throw new RestException(401);
367  }
368  // Check mandatory fields
369  $result = $this->_validateMessage($request_data);
370 
371  foreach ($request_data as $field => $value) {
372  $this->ticket->$field = $value;
373  }
374  $ticketMessageText = $this->ticket->message;
375  $result = $this->ticket->fetch('', '', $this->ticket->track_id);
376  if (!$result) {
377  throw new RestException(404, 'Ticket not found');
378  }
379  $this->ticket->message = $ticketMessageText;
380  if (!$this->ticket->createTicketMessage(DolibarrApiAccess::$user)) {
381  throw new RestException(500, 'Error when creating ticket');
382  }
383  return $this->ticket->id;
384  }
385 
394  public function put($id, $request_data = null)
395  {
396  if (!DolibarrApiAccess::$user->rights->ticket->write) {
397  throw new RestException(401);
398  }
399 
400  $result = $this->ticket->fetch($id);
401  if (!$result) {
402  throw new RestException(404, 'Ticket not found');
403  }
404 
405  if (!DolibarrApi::_checkAccessToResource('ticket', $this->ticket->id)) {
406  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
407  }
408 
409  foreach ($request_data as $field => $value) {
410  $this->ticket->$field = $value;
411  }
412 
413  if ($this->ticket->update($id, DolibarrApiAccess::$user)) {
414  return $this->get($id);
415  }
416 
417  return false;
418  }
419 
427  public function delete($id)
428  {
429  if (!DolibarrApiAccess::$user->rights->ticket->delete) {
430  throw new RestException(401);
431  }
432  $result = $this->ticket->fetch($id);
433  if (!$result) {
434  throw new RestException(404, 'Ticket not found');
435  }
436 
437  if (!DolibarrApi::_checkAccessToResource('ticket', $this->ticket->id)) {
438  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
439  }
440 
441  if (!$this->ticket->delete($id)) {
442  throw new RestException(500, 'Error when deleting ticket');
443  }
444 
445  return array(
446  'success' => array(
447  'code' => 200,
448  'message' => 'Ticket deleted'
449  )
450  );
451  }
452 
461  private function _validate($data)
462  {
463  $ticket = array();
464  foreach (Tickets::$FIELDS as $field) {
465  if (!isset($data[$field])) {
466  throw new RestException(400, "$field field missing");
467  }
468  $ticket[$field] = $data[$field];
469  }
470  return $ticket;
471  }
472 
481  private function _validateMessage($data)
482  {
483  $ticket = array();
484  foreach (Tickets::$FIELDS_MESSAGES as $field) {
485  if (!isset($data[$field])) {
486  throw new RestException(400, "$field field missing");
487  }
488  $ticket[$field] = $data[$field];
489  }
490  return $ticket;
491  }
492 
493  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
503  protected function _cleanObjectDatas($object)
504  {
505  // phpcs:enable
506  $object = parent::_cleanObjectDatas($object);
507 
508  // Other attributes to clean
509  $attr2clean = array(
510  "contact",
511  "contact_id",
512  "ref_previous",
513  "ref_next",
514  "ref_ext",
515  "table_element_line",
516  "statut",
517  "country",
518  "country_id",
519  "country_code",
520  "barcode_type",
521  "barcode_type_code",
522  "barcode_type_label",
523  "barcode_type_coder",
524  "mode_reglement_id",
525  "cond_reglement_id",
526  "cond_reglement",
527  "fk_delivery_address",
528  "shipping_method_id",
529  "modelpdf",
530  "fk_account",
531  "note_public",
532  "note_private",
533  "note",
534  "total_ht",
535  "total_tva",
536  "total_localtax1",
537  "total_localtax2",
538  "total_ttc",
539  "fk_incoterms",
540  "label_incoterms",
541  "location_incoterms",
542  "name",
543  "lastname",
544  "firstname",
545  "civility_id",
546  "canvas",
547  "cache_msgs_ticket",
548  "cache_logs_ticket",
549  "cache_types_tickets",
550  "cache_category_tickets",
551  "regeximgext",
552  "statuts_short",
553  "statuts"
554  );
555  foreach ($attr2clean as $toclean) {
556  unset($object->$toclean);
557  }
558 
559  // If object has lines, remove $db property
560  if (isset($object->lines) && count($object->lines) > 0) {
561  $nboflines = count($object->lines);
562  for ($i = 0; $i < $nboflines; $i++) {
563  $this->_cleanObjectDatas($object->lines[$i]);
564  }
565  }
566 
567  // If object has linked objects, remove $db property
568  if (isset($object->linkedObjects) && count($object->linkedObjects) > 0) {
569  foreach ($object->linkedObjects as $type_object => $linked_object) {
570  foreach ($linked_object as $object2clean) {
571  $this->_cleanObjectDatas($object2clean);
572  }
573  }
574  }
575  return $object;
576  }
577 }
db
$conf db
API class for accounts.
Definition: inc.php:41
Tickets\index
index($socid=0, $sortfield="t.rowid", $sortorder="ASC", $limit=100, $page=0, $sqlfilters='')
List tickets.
Definition: api_tickets.class.php:231
Tickets\postNewMessage
postNewMessage($request_data=null)
Create ticket object.
Definition: api_tickets.class.php:362
Tickets\_cleanObjectDatas
_cleanObjectDatas($object)
Clean sensible object datas.
Definition: api_tickets.class.php:503
DolibarrApi\_checkAccessToResource
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
Tickets
Definition: api_tickets.class.php:30
Tickets\put
put($id, $request_data=null)
Update ticket.
Definition: api_tickets.class.php:394
Tickets\getByTrackId
getByTrackId($track_id)
Get properties of a Ticket object from track id.
Definition: api_tickets.class.php:94
DolibarrApi
Class for API REST v1.
Definition: api.class.php:30
Tickets\__construct
__construct()
Constructor.
Definition: api_tickets.class.php:56
Exception
DolibarrApi\_checkFilters
_checkFilters($sqlfilters, &$error='')
Return if a $sqlfilters parameter is valid.
Definition: api.class.php:310
generate_random_id
generate_random_id($car=16)
Generate a random id.
Definition: ticket.lib.php:184
dolGetFirstLastname
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
Definition: functions.lib.php:8062
Tickets\_validate
_validate($data)
Validate fields before create or update object.
Definition: api_tickets.class.php:461
User
Class to manage Dolibarr users.
Definition: user.class.php:44
Tickets\getByRef
getByRef($ref)
Get properties of a Ticket object from ref.
Definition: api_tickets.class.php:113
Ticket
Class to generate the form for creating a new ticket.
Definition: html.formticket.class.php:31
Tickets\post
post($request_data=null)
Create ticket object.
Definition: api_tickets.class.php:329
Tickets\_validateMessage
_validateMessage($data)
Validate fields before create or update object message.
Definition: api_tickets.class.php:481
Tickets\getCommon
getCommon($id=0, $track_id='', $ref='')
Get properties of a Ticket object Return an array with ticket informations.
Definition: api_tickets.class.php:131