dolibarr  x.y.z
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  return $this->getCommon(0, '', $ref);
116  }
117 
127  private function getCommon($id = 0, $track_id = '', $ref = '')
128  {
129  if (!DolibarrApiAccess::$user->rights->ticket->read) {
130  throw new RestException(403);
131  }
132 
133  // Check parameters
134  if (($id < 0) && !$track_id && !$ref) {
135  throw new RestException(401, 'Wrong parameters');
136  }
137  if ($id == 0) {
138  $result = $this->ticket->initAsSpecimen();
139  } else {
140  $result = $this->ticket->fetch($id, $ref, $track_id);
141  }
142  if (!$result) {
143  throw new RestException(404, 'Ticket not found');
144  }
145 
146  // String for user assigned
147  if ($this->ticket->fk_user_assign > 0) {
148  $userStatic = new User($this->db);
149  $userStatic->fetch($this->ticket->fk_user_assign);
150  $this->ticket->fk_user_assign_string = $userStatic->firstname.' '.$userStatic->lastname;
151  }
152 
153  // Messages of ticket
154  $messages = array();
155  $this->ticket->loadCacheMsgsTicket();
156  if (is_array($this->ticket->cache_msgs_ticket) && count($this->ticket->cache_msgs_ticket) > 0) {
157  $num = count($this->ticket->cache_msgs_ticket);
158  $i = 0;
159  while ($i < $num) {
160  if ($this->ticket->cache_msgs_ticket[$i]['fk_user_author'] > 0) {
161  $user_action = new User($this->db);
162  $user_action->fetch($this->ticket->cache_msgs_ticket[$i]['fk_user_author']);
163  }
164 
165  // Now define messages
166  $messages[] = array(
167  'id' => $this->ticket->cache_msgs_ticket[$i]['id'],
168  'fk_user_action' => $this->ticket->cache_msgs_ticket[$i]['fk_user_author'],
169  'fk_user_action_socid' => $user_action->socid,
170  'fk_user_action_string' => dolGetFirstLastname($user_action->firstname, $user_action->lastname),
171  'message' => $this->ticket->cache_msgs_ticket[$i]['message'],
172  'datec' => $this->ticket->cache_msgs_ticket[$i]['datec'],
173  'private' => $this->ticket->cache_msgs_ticket[$i]['private']
174  );
175  $i++;
176  }
177  $this->ticket->messages = $messages;
178  }
179 
180  if (!DolibarrApi::_checkAccessToResource('ticket', $this->ticket->id)) {
181  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
182  }
183  return $this->_cleanObjectDatas($this->ticket);
184  }
185 
201  public function index($socid = 0, $sortfield = "t.rowid", $sortorder = "ASC", $limit = 100, $page = 0, $sqlfilters = '')
202  {
203  global $db, $conf;
204 
205  if (!DolibarrApiAccess::$user->rights->ticket->read) {
206  throw new RestException(403);
207  }
208 
209  $obj_ret = array();
210 
211  if (!$socid && DolibarrApiAccess::$user->socid) {
212  $socid = DolibarrApiAccess::$user->socid;
213  }
214 
215  $search_sale = null;
216  // If the internal user must only see his customers, force searching by him
217  $search_sale = 0;
218  if (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) {
219  $search_sale = DolibarrApiAccess::$user->id;
220  }
221 
222  $sql = "SELECT t.rowid";
223  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
224  $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)
225  }
226  $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t";
227 
228  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
229  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
230  }
231 
232  $sql .= ' WHERE t.entity IN ('.getEntity('ticket', 1).')';
233  if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) {
234  $sql .= " AND t.fk_soc = sc.fk_soc";
235  }
236  if ($socid > 0) {
237  $sql .= " AND t.fk_soc = ".((int) $socid);
238  }
239  if ($search_sale > 0) {
240  $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
241  }
242 
243  // Insert sale filter
244  if ($search_sale > 0) {
245  $sql .= " AND sc.fk_user = ".((int) $search_sale);
246  }
247  // Add sql filters
248  if ($sqlfilters) {
249  $errormessage = '';
250  if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) {
251  throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage);
252  }
253  $regexstring = '\‍(([^:\'\‍(\‍)]+:[^:\'\‍(\‍)]+:[^\‍(\‍)]+)\‍)';
254  $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
255  }
256 
257  $sql .= $this->db->order($sortfield, $sortorder);
258 
259  if ($limit) {
260  if ($page < 0) {
261  $page = 0;
262  }
263  $offset = $limit * $page;
264 
265  $sql .= $this->db->plimit($limit, $offset);
266  }
267 
268  $result = $this->db->query($sql);
269  if ($result) {
270  $num = $this->db->num_rows($result);
271  $i = 0;
272  while ($i < $num) {
273  $obj = $this->db->fetch_object($result);
274  $ticket_static = new Ticket($this->db);
275  if ($ticket_static->fetch($obj->rowid)) {
276  if ($ticket_static->fk_user_assign > 0) {
277  $userStatic = new User($this->db);
278  $userStatic->fetch($ticket_static->fk_user_assign);
279  $ticket_static->fk_user_assign_string = $userStatic->firstname.' '.$userStatic->lastname;
280  }
281  $obj_ret[] = $this->_cleanObjectDatas($ticket_static);
282  }
283  $i++;
284  }
285  } else {
286  throw new RestException(503, 'Error when retrieve ticket list');
287  }
288  if (!count($obj_ret)) {
289  throw new RestException(404, 'No ticket found');
290  }
291  return $obj_ret;
292  }
293 
300  public function post($request_data = null)
301  {
302  $ticketstatic = new Ticket($this->db);
303  if (!DolibarrApiAccess::$user->rights->ticket->write) {
304  throw new RestException(401);
305  }
306  // Check mandatory fields
307  $result = $this->_validate($request_data);
308 
309  foreach ($request_data as $field => $value) {
310  $this->ticket->$field = $value;
311  }
312  if (empty($this->ticket->ref)) {
313  $this->ticket->ref = $ticketstatic->getDefaultRef();
314  }
315  if (empty($this->ticket->track_id)) {
316  $this->ticket->track_id = generate_random_id(16);
317  }
318 
319  if ($this->ticket->create(DolibarrApiAccess::$user) < 0) {
320  throw new RestException(500, "Error creating ticket", array_merge(array($this->ticket->error), $this->ticket->errors));
321  }
322 
323  return $this->ticket->id;
324  }
325 
333  public function postNewMessage($request_data = null)
334  {
335  $ticketstatic = new Ticket($this->db);
336  if (!DolibarrApiAccess::$user->rights->ticket->write) {
337  throw new RestException(401);
338  }
339  // Check mandatory fields
340  $result = $this->_validateMessage($request_data);
341 
342  foreach ($request_data as $field => $value) {
343  $this->ticket->$field = $value;
344  }
345  $ticketMessageText = $this->ticket->message;
346  $result = $this->ticket->fetch('', '', $this->ticket->track_id);
347  if (!$result) {
348  throw new RestException(404, 'Ticket not found');
349  }
350  $this->ticket->message = $ticketMessageText;
351  if (!$this->ticket->createTicketMessage(DolibarrApiAccess::$user)) {
352  throw new RestException(500, 'Error when creating ticket');
353  }
354  return $this->ticket->id;
355  }
356 
365  public function put($id, $request_data = null)
366  {
367  if (!DolibarrApiAccess::$user->rights->ticket->write) {
368  throw new RestException(401);
369  }
370 
371  $result = $this->ticket->fetch($id);
372  if (!$result) {
373  throw new RestException(404, 'Ticket not found');
374  }
375 
376  if (!DolibarrApi::_checkAccessToResource('ticket', $this->ticket->id)) {
377  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
378  }
379 
380  foreach ($request_data as $field => $value) {
381  $this->ticket->$field = $value;
382  }
383 
384  if ($this->ticket->update($id, DolibarrApiAccess::$user)) {
385  return $this->get($id);
386  }
387 
388  return false;
389  }
390 
398  public function delete($id)
399  {
400  if (!DolibarrApiAccess::$user->rights->ticket->delete) {
401  throw new RestException(401);
402  }
403  $result = $this->ticket->fetch($id);
404  if (!$result) {
405  throw new RestException(404, 'Ticket not found');
406  }
407 
408  if (!DolibarrApi::_checkAccessToResource('ticket', $this->ticket->id)) {
409  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
410  }
411 
412  if (!$this->ticket->delete($id)) {
413  throw new RestException(500, 'Error when deleting ticket');
414  }
415 
416  return array(
417  'success' => array(
418  'code' => 200,
419  'message' => 'Ticket deleted'
420  )
421  );
422  }
423 
432  private function _validate($data)
433  {
434  $ticket = array();
435  foreach (Tickets::$FIELDS as $field) {
436  if (!isset($data[$field])) {
437  throw new RestException(400, "$field field missing");
438  }
439  $ticket[$field] = $data[$field];
440  }
441  return $ticket;
442  }
443 
452  private function _validateMessage($data)
453  {
454  $ticket = array();
455  foreach (Tickets::$FIELDS_MESSAGES as $field) {
456  if (!isset($data[$field])) {
457  throw new RestException(400, "$field field missing");
458  }
459  $ticket[$field] = $data[$field];
460  }
461  return $ticket;
462  }
463 
464  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
474  protected function _cleanObjectDatas($object)
475  {
476  // phpcs:enable
477  $object = parent::_cleanObjectDatas($object);
478 
479  // Other attributes to clean
480  $attr2clean = array(
481  "contact",
482  "contact_id",
483  "ref_previous",
484  "ref_next",
485  "ref_ext",
486  "table_element_line",
487  "statut",
488  "country",
489  "country_id",
490  "country_code",
491  "barcode_type",
492  "barcode_type_code",
493  "barcode_type_label",
494  "barcode_type_coder",
495  "mode_reglement_id",
496  "cond_reglement_id",
497  "cond_reglement",
498  "fk_delivery_address",
499  "shipping_method_id",
500  "modelpdf",
501  "fk_account",
502  "note_public",
503  "note_private",
504  "note",
505  "total_ht",
506  "total_tva",
507  "total_localtax1",
508  "total_localtax2",
509  "total_ttc",
510  "fk_incoterms",
511  "label_incoterms",
512  "location_incoterms",
513  "name",
514  "lastname",
515  "firstname",
516  "civility_id",
517  "canvas",
518  "cache_msgs_ticket",
519  "cache_logs_ticket",
520  "cache_types_tickets",
521  "cache_category_tickets",
522  "regeximgext",
523  "statuts_short",
524  "statuts"
525  );
526  foreach ($attr2clean as $toclean) {
527  unset($object->$toclean);
528  }
529 
530  // If object has lines, remove $db property
531  if (isset($object->lines) && count($object->lines) > 0) {
532  $nboflines = count($object->lines);
533  for ($i = 0; $i < $nboflines; $i++) {
534  $this->_cleanObjectDatas($object->lines[$i]);
535  }
536  }
537 
538  // If object has linked objects, remove $db property
539  if (isset($object->linkedObjects) && count($object->linkedObjects) > 0) {
540  foreach ($object->linkedObjects as $type_object => $linked_object) {
541  foreach ($linked_object as $object2clean) {
542  $this->_cleanObjectDatas($object2clean);
543  }
544  }
545  }
546  return $object;
547  }
548 }
Class for API REST v1.
Definition: api.class.php:31
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
_checkFilters($sqlfilters, &$error='')
Return if a $sqlfilters parameter is valid.
Definition: api.class.php:310
getCommon($id=0, $track_id='', $ref='')
Get properties of a Ticket object Return an array with ticket informations.
getByRef($ref)
Get properties of a Ticket object from ref.
__construct()
Constructor.
_cleanObjectDatas($object)
Clean sensible object datas.
postNewMessage($request_data=null)
Create ticket object.
post($request_data=null)
Create ticket object.
put($id, $request_data=null)
Update ticket.
index($socid=0, $sortfield="t.rowid", $sortorder="ASC", $limit=100, $page=0, $sqlfilters='')
List tickets.
_validateMessage($data)
Validate fields before create or update object message.
getByTrackId($track_id)
Get properties of a Ticket object from track id.
_validate($data)
Validate fields before create or update object.
Class to manage Dolibarr users.
Definition: user.class.php:45
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
Class to generate the form for creating a new ticket.
$conf db
API class for accounts.
Definition: inc.php:41
generate_random_id($car=16)
Generate a random id.
Definition: ticket.lib.php:194