dolibarr 24.0.0-beta
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2016 Jean-François FERRY <hello@librethic.io>
3 * Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
4 * Copyright (C) 2018 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2021-2026 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
7 * Copyright (C) 2022-2023 Charlene Benke <charlene@patas-monkey.com>
8 * Copyright (C) 2023 Benjamin Falière <benjamin.faliere@altairis.fr>
9 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
10 * Copyright (C) 2024 Irvine FLEITH <irvine.fleith@atm-consulting.fr>
11 * Copyright (C) 2026 Jon Bendtsen <jon.bendtsen.github@jonb.dk>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 */
26
33// Load Dolibarr environment
34require '../main.inc.php';
43require_once DOL_DOCUMENT_ROOT.'/ticket/class/actions_ticket.class.php';
44require_once DOL_DOCUMENT_ROOT.'/core/class/html.formticket.class.php';
45require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
46require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
48require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
49require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
50require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
51
52if (isModEnabled('project')) {
53 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
54 include_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
55 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
56}
57if (isModEnabled('contract')) {
58 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formcontract.class.php';
59 include_once DOL_DOCUMENT_ROOT.'/core/lib/contract.lib.php';
60 include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
61}
62
63// Load translation files required by the page
64$langs->loadLangs(array("companies", "other", "ticket"));
65
66// Get parameters
67$id = GETPOSTINT('id');
68$ref = GETPOST('ref', 'alpha');
69$track_id = GETPOST('track_id', 'alpha', 3);
70$socid = GETPOSTINT('socid');
71$contactid = GETPOSTINT('contactid');
72$projectid = GETPOSTINT('projectid');
73$notifyTiers = GETPOST("notify_tiers_at_create", 'alpha');
74$mine = GETPOSTINT('mine');
75
76$action = GETPOST('action', 'aZ09');
77$cancel = GETPOST('cancel', 'alpha');
78$backtopage = GETPOST('backtopage', 'alpha');
79$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
80$contextpage = GETPOST('contextpage', 'aZ');
81
82$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
83$sortfield = GETPOST('sortfield', 'aZ09comma') ? GETPOST('sortfield', 'aZ09comma') : "a.datep";
84$sortorder = GETPOST('sortorder', 'aZ09comma') ? GETPOST('sortorder', 'aZ09comma') : "desc";
85$search_rowid = GETPOST('search_rowid');
86$search_agenda_label = GETPOST('search_agenda_label');
87
88if (GETPOST('actioncode', 'array')) {
89 $actioncode = GETPOST('actioncode', 'array', 3);
90 if (!count($actioncode)) {
91 $actioncode = '0';
92 }
93} else {
94 $actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : getDolGlobalString('AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT'));
95}
96
97
98// Initialize a technical object to manage hooks of ticket. Note that conf->hooks_modules contains array array
99$hookmanager->initHooks(array('ticketcard', 'globalcard'));
100
101$object = new Ticket($db);
102
103// Fetch optionals attributes and labels
104$extrafields->fetch_name_optionals_label($object->table_element);
105
106$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
107
108// Initialize array of search criteria
109$search_all = GETPOST("search_all", 'alpha');
110$search = array();
111foreach ($object->fields as $key => $val) {
112 if (GETPOST('search_'.$key, 'alpha')) {
113 $search[$key] = GETPOST('search_'.$key, 'alpha');
114 }
115}
116
117if (empty($action) && empty($id) && empty($ref)) {
118 $action = 'view';
119}
120
121// Select mail models is same action as add_message
122if (GETPOST('modelselected', 'alpha')) {
123 $action = 'presend';
124}
125
126// Load object
127//include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'. Include fetch and fetch_thirdparty but not fetch_optionals
128$res = 0;
129if ($id || $track_id || $ref) {
130 $res = $object->fetch($id, $ref, $track_id);
131 if ($res >= 0) {
132 $id = $object->id;
133 $track_id = $object->track_id;
134 }
135}
136
137$now = dol_now();
138
139$actionobject = new ActionsTicket($db);
140
141// Store current page url
142$url_page_current = DOL_URL_ROOT.'/ticket/card.php';
143
144// Security check - Protection if external user
145if ($user->socid > 0) {
146 $socid = $user->socid;
147}
148$result = restrictedArea($user, 'ticket', $object->id);
149
150$triggermodname = 'TICKET_MODIFY';
151
152// Permissions
153$permissiontoread = $user->hasRight('ticket', 'read');
154$permissiontoadd = $user->hasRight('ticket', 'write');
155$permissiontodelete = $user->hasRight('ticket', 'delete');
156// Permission allowing the management of all ticket status modifications (status change buttons, Close/Resolve, Cancel, the assignee selection menu, and re-open)
157$permissiontomanage = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('ticket', 'write')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('ticket', 'manage_advance')));
158$permissiontoeditextra = $permissiontoadd;
159if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
160 // For action 'update_extras', is there a specific permission set for the attribute to update
161 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
162}
163
164$upload_dir = $conf->ticket->dir_output;
165
166
167/*
168 * Actions
169 */
170
171$parameters = array();
172$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
173if ($reshook < 0) {
174 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
175}
176
177$error = 0;
178if (empty($reshook)) {
179 // Purge search criteria
180 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers{
181 $actioncode = '';
182 $search_agenda_label = '';
183 }
184
185 $backurlforlist = DOL_URL_ROOT . '/ticket/list.php';
186
187 if (empty($backtopage) || ($cancel && empty($id))) {
188 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
189 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
190 $backtopage = $backurlforlist;
191 } else {
192 $backtopage = DOL_URL_ROOT . '/ticket/card.php?id=' . ((!empty($id) && $id > 0) ? $id : '__ID__');
193 }
194 }
195 }
196
197 if ($cancel) {
198 if (!empty($backtopageforcancel)) {
199 header("Location: " . $backtopageforcancel);
200 exit;
201 } elseif (!empty($backtopage)) {
202 header("Location: " . $backtopage);
203 exit;
204 }
205 $action = 'view';
206 }
207
208 if ((($action == 'add' && GETPOST('save', 'alpha')) || ($action == 'update' && $object->status < Ticket::STATUS_CLOSED)) && $permissiontoadd) {
209 $ifErrorAction = ($action == 'add' ? 'create' : 'edit'); // Test on permission not required here
210 if ($action == 'add') { // Test on permission already done
211 $object->track_id = null;
212 }
213 $error = 0;
214
215 $fieldsToCheck = [
216 'ref' => ['check' => 'alpha', 'langs' => 'Ref'],
217 'type_code' => ['check' => 'alpha', 'langs' => 'TicketTypeRequest'],
218 'category_code' => ['check' => 'alpha', 'langs' => 'TicketCategory'],
219 'severity_code' => ['check' => 'alpha', 'langs' => 'TicketSeverity'],
220 'subject' => ['check' => 'alphanohtml', 'langs' => 'Subject'],
221 'message' => ['check' => 'restricthtml', 'langs' => 'Message']
222 ];
223
224 FormTicket::checkRequiredFields($fieldsToCheck, $error);
225
226 if (!empty($error)) {
227 $action = $ifErrorAction;
228 }
229
230 $ret = $extrafields->setOptionalsFromPost(null, $object);
231 if ($ret < 0) {
232 $error++;
233 }
234 $getRef = GETPOST('ref', 'alpha');
235
236 if (!empty($getRef)) {
237 $isExistingRef = $object->checkExistingRef($action, $getRef);
238 } else {
239 $isExistingRef = true;
240 }
241
242 $style = '';
243
244 if ($isExistingRef) {
245 if ($action == 'update') { // Test on permission already done
246 $error++;
247 $action = 'edit';
248 $style = 'errors';
249 } elseif ($action == 'add') { // Test on permission already done
250 $object->ref = $object->getDefaultRef();
251 $object->track_id = null;
252 $style = 'warnings';
253 }
254 if (!empty($getRef)) {
255 setEventMessage($langs->trans('TicketRefAlreadyUsed', $getRef, $object->ref), $style);
256 }
257 }
258 if (!$error) {
259 $db->begin();
260
261 $object->type_code = GETPOST('type_code', 'alpha');
262 $object->category_code = GETPOST('category_code', 'alpha');
263 $object->severity_code = GETPOST('severity_code', 'alpha');
264 $object->subject = GETPOST('subject', 'alpha');
265 $object->message = GETPOST('message', 'restricthtml');
266 $object->fk_soc = GETPOSTINT('socid');
267 $fk_user_assign = GETPOSTINT('fk_user_assign');
268 $object->fk_project = GETPOSTINT('projectid');
269 $object->fk_contract = GETPOSTISSET('contractid') ? GETPOSTINT('contractid') : GETPOSTINT('contratid');
270
271 if ($fk_user_assign > 0) {
272 $object->fk_user_assign = $fk_user_assign;
273 $object->status = $object::STATUS_ASSIGNED;
274 }
275
276 if ($action == 'add') { // Test on permission already done
277 $object->type_code = GETPOST("type_code", 'alpha');
278 $object->type_label = $langs->trans($langs->getLabelFromKey($db, $object->type_code, 'c_ticket_type', 'code', 'label'));
279 $object->category_label = $langs->trans($langs->getLabelFromKey($db, $object->category_code, 'c_ticket_category', 'code', 'label'));
280 $object->severity_label = $langs->trans($langs->getLabelFromKey($db, $object->severity_code, 'c_ticket_severity', 'code', 'label'));
281 $object->fk_user_create = $user->id;
282 $object->email_from = $user->email;
283 $object->origin_email = null;
284 $notifyTiers = GETPOST("notify_tiers_at_create", 'alpha');
285 $object->notify_tiers_at_create = empty($notifyTiers) ? 0 : 1;
286 $object->context['contact_id'] = GETPOSTINT('contactid');
287 $id = $object->create($user);
288 } else {
289 $id = $object->update($user);
290 }
291
292 if ($id <= 0) {
293 $error++;
294 setEventMessages($object->error, $object->errors, 'errors');
295 $action = $ifErrorAction;
296 }
297
298 if (!$error) {
299 // Category association
300 $categories = GETPOST('categories', 'array:int');
301 $object->setCategories($categories);
302 }
303
304 if ($action == 'add') { // Test on permission already done
305 if (!$error) {
306 // Add contact
307 $contactid = GETPOSTINT('contactid');
308 $type_contact = GETPOST("type", 'alpha');
309
310 if ($contactid > 0 && $type_contact) {
311 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
312 $result = $object->add_contact($contactid, $typeid, 'external');
313 }
314
315 // Link ticket to project
316 if (GETPOST('origin', 'alpha') == 'projet') {
317 $projectid = GETPOSTINT('originid');
318 } else {
319 $projectid = GETPOSTINT('projectid');
320 }
321
322 if ($projectid > 0) {
323 $object->setProject($projectid);
324 }
325
326 // Auto mark as read if created from backend
327 if (getDolGlobalString('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND') && $permissiontomanage) {
328 if (!$object->markAsRead($user) > 0) {
329 setEventMessages($object->error, $object->errors, 'errors');
330 }
331 }
332
333 // Auto assign user
334 if ((empty($fk_user_assign) && getDolGlobalInt('TICKET_AUTO_ASSIGN_USER_CREATE') == 1) || (getDolGlobalInt('TICKET_AUTO_ASSIGN_USER_CREATE') == 2)) {
335 $result = $object->assignUser($user, $user->id, 1);
336 $object->add_contact($user->id, "SUPPORTTEC", 'internal');
337 }
338 }
339
340 if (!$error) {
341 // File transfer
342 $object->copyFilesForTicket(''); // trackid is forced to '' because files were uploaded when no id for ticket exists yet and trackid was ''
343 }
344 }
345 if (!$error) {
346 $db->commit();
347
348 if (!empty($backtopage)) {
349 if (empty($id)) {
350 $url = $backtopage;
351 } else {
352 $url = 'card.php?track_id=' . urlencode($object->track_id);
353 }
354 } else {
355 $url = 'card.php?track_id=' . urlencode($object->track_id);
356 }
357
358 header("Location: " . $url);
359 exit;
360 } else {
361 $db->rollback();
362 setEventMessages($object->error, $object->errors, 'errors');
363 }
364 } else {
365 $action = $ifErrorAction;
366 }
367 }
368
369 // Mark as Read
370 if ($action == "set_read" && $permissiontomanage) {
371 $object->fetch(0, '', GETPOST("track_id", 'alpha'));
372
373 if ($object->markAsRead($user) > 0) {
374 setEventMessages($langs->trans('TicketMarkedAsRead'), null, 'mesgs');
375
376 header("Location: card.php?track_id=" . $object->track_id);
377 exit;
378 } else {
379 setEventMessages($object->error, $object->errors, 'errors');
380 }
381 $action = 'view';
382 }
383
384 // Assign to someone
385 if ($action == "assign_user" && GETPOST('btn_assign_user', 'alpha') && $permissiontomanage) {
386 $object->fetch(0, '', GETPOST("track_id", 'alpha'));
387 $useroriginassign = $object->fk_user_assign;
388 $usertoassign = GETPOSTINT('fk_user_assign');
389
390 /*if (! ($usertoassign > 0)) {
391 $error++;
392 array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("AssignedTo")));
393 $action = 'view';
394 }*/
395
396 if (!$error) {
397 $ret = $object->assignUser($user, $usertoassign);
398 if ($ret < 0) {
399 $error++;
400 }
401 }
402
403 if (!$error) { // Update list of contacts
404 // If a user has already been assigned, we delete him from the contacts.
405 if ($useroriginassign > 0) {
406 $internal_contacts = $object->listeContact(-1, 'internal', 0, 'SUPPORTTEC');
407 foreach ($internal_contacts as $key => $contact) {
408 if ($contact['id'] !== $usertoassign) {
409 $result = $object->delete_contact($contact['rowid']);
410 if ($result < 0) {
411 $error++;
412 setEventMessages($object->error, $object->errors, 'errors');
413 }
414 }
415 }
416 }
417
418 if ($usertoassign > 0 && $usertoassign !== $useroriginassign) {
419 $result = $object->add_contact($usertoassign, "SUPPORTTEC", 'internal', $notrigger = 0);
420 if ($result < 0) {
421 $error++;
422 setEventMessages($object->error, $object->errors, 'errors');
423 }
424 }
425 }
426
427 if (!$error) {
428 // Log action in ticket logs table
429 $object->fetch_user($usertoassign);
430
431 setEventMessages($langs->trans('TicketAssigned'), null, 'mesgs');
432 header("Location: card.php?track_id=" . $object->track_id);
433 exit;
434 } else {
435 array_push($object->errors, $object->error);
436 }
437 $action = 'view';
438 }
439
440 // Action to add a message (private or not, with email or not).
441 // This may also send an email (concatenated with email_intro and email footer if checkbox was selected)
442 if ($action == 'add_message' && GETPOSTISSET('btn_add_message') && $permissiontoread) {
443 $ret = $object->newMessage($user, $action, GETPOSTINT('private_message'), 0);
444
445 if ($ret > 0) {
446 if (!empty($backtopage)) {
447 $url = $backtopage;
448 } else {
449 $url = 'card.php?track_id=' . urlencode($object->track_id);
450 }
451
452 header("Location: " . $url);
453 exit;
454 } else {
455 setEventMessages($object->error, $object->errors, 'errors');
456 $action = 'presend';
457 }
458 }
459
460 if (($action == "confirm_close" || $action == "confirm_abandon") && GETPOST('confirm', 'alpha') == 'yes' && $permissiontomanage) {
461 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
462 if (GETPOSTISSET('contactid')) {
463 $object->context['contact_id'] = GETPOSTINT('contactid');
464 }
465
466 if ($object->close($user, ($action == "confirm_abandon" ? 1 : 0)) > 0) { // Test on pemrission already done
467 setEventMessages($langs->trans('TicketMarkedAsClosed'), null, 'mesgs');
468
469 $url = 'card.php?track_id=' . GETPOST('track_id', 'alpha');
470 header("Location: " . $url);
471 exit;
472 } else {
473 $action = '';
474 setEventMessages($object->error, $object->errors, 'errors');
475 }
476 }
477
478 if ($action == "confirm_public_close" && GETPOST('confirm', 'alpha') == 'yes' && $permissiontoadd) {
479 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
480 if ($_SESSION['email_customer'] == $object->origin_email || $_SESSION['email_customer'] == $object->thirdparty->email) {
481 $object->context['contact_id'] = GETPOSTINT('contactid');
482
483 if ($object->close($user) > 0) {
484 setEventMessages('<div class="confirm">' . $langs->trans('TicketMarkedAsClosed') . '</div>', null, 'mesgs');
485
486 $url = 'card.php?track_id=' . GETPOST('track_id', 'alpha');
487 header("Location: " . $url);
488 exit;
489 }
490 setEventMessages($object->error, $object->errors, 'errors');
491 $action = '';
492 } else {
493 setEventMessages($object->error, $object->errors, 'errors');
494 $action = '';
495 }
496 }
497
498 if ($action == 'confirm_clone' && GETPOST('confirm', 'alpha') == "yes" && $permissiontomanage) {
499 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
500 $newid = $object->createFromClone($user, $object->id);
501 if ($newid > 0) {
502 header("Location: " . DOL_URL_ROOT . "/ticket/card.php?id=".$newid);
503 exit;
504 } else {
505 setEventMessages($object->error, $object->errors, 'errors');
506 $action = '';
507 }
508 }
509 }
510
511 if ($action == 'confirm_delete_ticket' && GETPOST('confirm', 'alpha') == "yes" && $permissiontodelete) {
512 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
513 if ($object->delete($user) > 0) {
514 setEventMessages('<div class="confirm">' . $langs->trans('TicketDeletedSuccess') . '</div>', null, 'mesgs');
515 header("Location: " . DOL_URL_ROOT . "/ticket/list.php");
516 exit;
517 } else {
518 $langs->load("errors");
519 $mesg = '<div class="error">' . $langs->trans($object->error) . '</div>';
520 $action = '';
521 }
522 }
523 }
524
525 // Set parent company
526 if ($action == 'set_thirdparty' && $permissiontoadd) {
527 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
528 $result = $object->setCustomer(GETPOSTINT('editcustomer'));
529 $url = $_SERVER["PHP_SELF"] . '?track_id=' . GETPOST('track_id', 'alpha');
530 header("Location: " . $url);
531 exit();
532 }
533 }
534
535 // Set progress status
536 if ($action == 'set_progression' && $permissiontoadd) {
537 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
538 $result = $object->setProgression(GETPOSTINT('progress'));
539
540 $url = 'card.php?track_id=' . $object->track_id;
541 header("Location: " . $url);
542 exit();
543 }
544 }
545
546 // Set categories
547 if ($action == 'set_categories' && $permissiontoadd) {
548 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
549 $result = $object->setCategories(GETPOST('categories', 'array'));
550
551 $url = 'card.php?track_id=' . $object->track_id;
552 header("Location: " . $url);
553 exit();
554 }
555 }
556
557 // Set Subject
558 if ($action == 'setsubject' && $permissiontoadd) {
559 if ($object->fetch(GETPOSTINT('id'))) {
560 if ($action == 'setsubject') { // Test on permission already done
561 $object->subject = GETPOST('subject', 'alphanohtml');
562 }
563
564 if ($action == 'setsubject' && empty($object->subject)) { // Test on permission already done
565 $error++;
566 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")), null, 'errors');
567 }
568
569 if (!$error) {
570 if (!$object->update($user) >= 0) {
571 $error++;
572 setEventMessages($object->error, $object->errors, 'errors');
573 }
574 }
575
576 header("Location: " . $_SERVER['PHP_SELF'] . "?track_id=" . $object->track_id);
577 exit;
578 }
579 }
580
581 if ($action == 'confirm_reopen' && $permissiontomanage && !GETPOST('cancel')) {
582 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
583 // prevent browser refresh from reopening ticket several times
584 if ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED) {
585 if ($object->fk_user_assign != null) {
586 $res = $object->setStatut(Ticket::STATUS_ASSIGNED, null, '', $triggermodname);
587 } else {
588 $res = $object->setStatut(Ticket::STATUS_NOT_READ, null, '', $triggermodname);
589 }
590 if ($res) {
591 $url = 'card.php?track_id=' . $object->track_id;
592 header("Location: " . $url);
593 exit();
594 } else {
595 $error++;
596 setEventMessages($object->error, $object->errors, 'errors');
597 }
598 }
599 }
600 } elseif ($action == 'classin' && $permissiontoadd) {
601 // Categorisation dans projet
602 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
603 $object->setProject($projectid);
604 $url = 'card.php?track_id=' . $object->track_id;
605 header("Location: " . $url);
606 exit();
607 }
608 } elseif ($action == 'setcontract' && $permissiontoadd) {
609 // Categorisation dans contrat
610 if ($object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha')) >= 0) {
611 $object->setContract(GETPOSTINT('contractid'));
612 $url = 'card.php?track_id=' . $object->track_id;
613 header("Location: " . $url);
614 exit();
615 }
616 } elseif ($action == "set_message" && $permissiontoadd) {
617 if (!GETPOST('cancel')) {
618 $object->fetch(0, '', GETPOST('track_id', 'alpha'));
619 //$oldvalue_message = $object->message;
620 $fieldtomodify = GETPOST('message_initial', 'restricthtml');
621
622 $object->message = $fieldtomodify;
623 $ret = $object->update($user);
624 if ($ret > 0) {
625 //include_once DOL_DOCUMENT_ROOT.'/core/class/utils_diff.class.php';
626 // output the result of comparing two files as plain text
627 //$log_action .= Diff::toString(Diff::compare(strip_tags($oldvalue_message), strip_tags($object->message)));
628
629 setEventMessages($langs->trans('TicketMessageSuccesfullyUpdated'), null, 'mesgs');
630 } else {
631 $error++;
632 setEventMessages($object->error, $object->errors, 'errors');
633 }
634 }
635
636 $action = 'view';
637 } elseif ($action == 'confirm_set_status' && $permissiontomanage && !GETPOST('cancel')) {
638 // Reopen ticket
639 if ($object->fetch(GETPOSTINT('id'), GETPOST('track_id', 'alpha')) >= 0) {
640 $new_status = GETPOSTINT('new_status');
641
642 $res = $object->setStatut($new_status, null, '', $triggermodname);
643 if ($res) {
644 if ($new_status != Ticket::STATUS_NOT_READ) {
645 $res = $object->setReadDate($user, 1); // Update date read if necessary, without trigger because we already run trigger in setStatut()
646 if ($res < 0) {
647 $error++;
648 setEventMessages($object->error, $object->errors, 'errors');
649 }
650 } else {
651 $sql = "UPDATE ".MAIN_DB_PREFIX."ticket SET date_read = null WHERE rowid = ".((int) $object->id);
652 $resql = $db->query($sql);
653 if (!$resql) {
655 }
656 }
657 $url = 'card.php?track_id=' . $object->track_id;
658 header("Location: " . $url);
659 exit();
660 } else {
661 $error++;
662 setEventMessages($object->error, $object->errors, 'errors');
663 }
664 }
665 }
666
667 // Action to update an extrafield
668 if ($action == "update_extras" && $permissiontoeditextra) {
669 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
670
671 $attribute_name = GETPOST('attribute', 'aZ09');
672
673 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
674 if ($ret < 0) {
675 $error++;
676 }
677
678 if (!$error) {
679 $result = $object->updateExtraField($attribute_name, $triggermodname);
680 if ($result < 0) {
681 setEventMessages($object->error, $object->errors, 'errors');
682 $error++;
683 }
684 }
685
686 if ($error) {
687 $action = 'edit_extras';
688 }
689 }
690
691 if ($action == "change_property" && GETPOST('btn_update_ticket_prop', 'alpha') && $permissiontoadd) {
692 $object->fetch(GETPOSTINT('id'), '', GETPOST('track_id', 'alpha'));
693
694 $object->type_code = GETPOST('update_value_type', 'aZ09');
695 $object->severity_code = GETPOST('update_value_severity', 'aZ09');
696 $object->category_code = GETPOST('update_value_category', 'aZ09');
697
698 $ret = $object->update($user);
699 if ($ret > 0) {
700 setEventMessages($langs->trans('TicketUpdated'), null, 'mesgs');
701 } else {
702 $error++;
703 setEventMessages($object->error, $object->errors, 'errors');
704 }
705 $action = 'view';
706 }
707
708 // Actions when printing a doc from card
709 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
710
711 $permissiondellink = $permissiontoadd;
712 include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
713
714 // Actions when printing a doc from card
715 include DOL_DOCUMENT_ROOT . '/core/actions_printing.inc.php';
716
717 // Actions to build doc
718 include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
719
720 // Actions to send emails
721 $triggersendname = 'TICKET_SENTBYMAIL';
722 $paramname = 'id';
723 $autocopy = 'MAIN_MAIL_AUTOCOPY_TICKET_TO'; // used to know the automatic BCC to add
724 $trackid = 'tic' . $object->id;
725 include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
726
727 // Set $action to correct value for the case we used presend action to add a message
728 if (GETPOSTISSET('actionbis') && $action == 'presend') { // Test on permission not required here
729 $action = 'presend_addmessage';
730 }
731}
732
733
734/*
735 * View
736 */
737
738$userstat = new User($db);
739$form = new Form($db);
740$formfile = new FormFile($db);
741$formticket = new FormTicket($db);
742
743$help_url = 'EN:Module_Ticket|FR:DocumentationModuleTicket';
744
745$title = $actionobject->getTitle($action, $object);
746
747llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-ticket page-card');
748
749if ($action == 'create' || $action == 'presend') {
750 if (empty($permissiontoadd)) {
751 accessforbidden('NotEnoughPermissions', 0, 1);
752 }
753
754 $formticket = new FormTicket($db);
755
756 print load_fiche_titre($langs->trans('NewTicket'), '', 'ticket');
757
758 $formticket->trackid = ''; // TODO Use a unique key 'tic' to avoid conflict in upload file feature
759
760 if (GETPOST("mode", "aZ09") == 'init' && empty($_POST)) {
761 $formticket->clear_attached_files();
762 }
763
764 $formticket->withfromsocid = $socid ? $socid : $user->socid;
765 $formticket->withfromcontactid = $contactid ? $contactid : '';
766 $formticket->withtitletopic = 1;
767 $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0));
768 $formticket->withusercreate = 0;
769 $formticket->withref = 1;
770 $formticket->fk_user_create = $user->id;
771 $formticket->withfile = 2;
772 $formticket->withextrafields = 1;
773 $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid'));
774
775 $formticket->withcancel = 1;
776
777 // Init list of files
778 if (GETPOST("mode", "aZ09") == 'init') {
779 $formticket->clear_attached_files();
780 }
781
782 $formticket->showForm(1, 'create', 0, null, $action, $object);
783
784 print dol_get_fiche_end();
785} elseif ($action == 'edit' && $permissiontoadd && $object->status < Ticket::STATUS_CLOSED) {
786 if (empty($permissiontoadd)) {
787 accessforbidden('NotEnoughPermissions', 0, 1);
788 }
789
790 $formticket = new FormTicket($db);
791
792 $head = ticket_prepare_head($object);
793
794 print dol_get_fiche_head($head, 'tabTicket', $langs->trans('Ticket'), -1, 'ticket');
795
796 $formticket->trackid = 'tic'.$object->id;
797 $formticket->withfromsocid = $object->socid;
798 $formticket->withtitletopic = 1;
799 // $formticket->withnotifytiersatcreate = ($notifyTiers ? 1 : (getDolGlobalString('TICKET_CHECK_NOTIFY_THIRDPARTY_AT_CREATION') ? 1 : 0));
800 $formticket->withnotifytiersatcreate = 0;
801 $formticket->withusercreate = 0;
802 $formticket->withref = 1;
803 $formticket->fk_user_create = $user->id;
804 $formticket->withfile = 0;
805 $formticket->action = 'update';
806 $formticket->withextrafields = 1;
807 $formticket->param = array('origin' => GETPOST('origin'), 'originid' => GETPOST('originid'));
808
809 $formticket->withcancel = 1;
810
811 $formticket->showForm(0, 'edit', 0, null, $action, $object);
812
813 print dol_get_fiche_end();
814} elseif ($object->id) {
815 if (!empty($res) && $res > 0) {
816 // or for unauthorized internals users
817 if (!$user->socid && (getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY') && $object->fk_user_assign != $user->id) && !$permissiontomanage) {
818 accessforbidden('', 0, 1);
819 }
820
821 $trackid = 'tic'.$object->id;
822
823 $formconfirm = '';
824
825 // Confirmation close
826 if ($action == 'close' && $permissiontomanage) {
827 $thirdparty_contacts = $object->getInfosTicketExternalContact(1);
828 $contacts_select = array(
829 '-2' => $langs->trans('TicketNotifyAllTiersAtClose'),
830 '-3' => $langs->trans('TicketNotNotifyTiersAtClose')
831 );
832 foreach ($thirdparty_contacts as $thirdparty_contact) {
833 $contacts_select[$thirdparty_contact['id']] = $thirdparty_contact['civility'] . ' ' . $thirdparty_contact['lastname'] . ' ' . $thirdparty_contact['firstname'];
834 }
835
836 // Default select all or no contact
837 $default = (getDolGlobalString('TICKET_NOTIFY_AT_CLOSING') ? '-2' : '-3');
838 $formquestion = array(
839 array(
840 'name' => 'contactid',
841 'type' => 'select',
842 'label' => $langs->trans('NotifyThirdpartyOnTicketClosing'),
843 'values' => $contacts_select,
844 'default' => $default
845 ),
846 );
847
848 $formconfirm = $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("CloseATicket"), $langs->trans("ConfirmCloseAticket"), "confirm_close", $formquestion, '', 1);
849 }
850 // Confirmation abandon
851 if ($action == 'abandon' && $permissiontomanage) {
852 $formconfirm = $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("AbandonTicket"), $langs->trans("ConfirmAbandonTicket"), "confirm_abandon", '', '', 1);
853 }
854 // Confirmation delete
855 if ($action == 'delete' && $permissiontodelete) {
856 $formconfirm = $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("Delete"), $langs->trans("ConfirmDeleteTicket"), "confirm_delete_ticket", '', '', 1);
857 }
858 // Confirm reopen
859 if ($action == 'reopen' && $permissiontomanage) {
860 $formconfirm = $form->formconfirm($url_page_current.'?track_id='.$object->track_id, $langs->trans('ReOpen'), $langs->trans('ConfirmReOpenTicket'), 'confirm_reopen', '', '', 1);
861 }
862 // Confirmation status change
863 if ($action == 'set_status' && $permissiontomanage) {
864 $new_status = GETPOSTINT('new_status');
865 //var_dump($url_page_current . "?track_id=" . $object->track_id);
866 $formconfirm = $form->formconfirm($url_page_current."?track_id=".$object->track_id."&new_status=".$new_status, $langs->trans("TicketChangeStatus"), $langs->trans("TicketConfirmChangeStatus", $langs->transnoentities($object->labelStatusShort[$new_status])), "confirm_set_status", '', '', 1);
867 }
868 // Clone confirmation
869 if ($action == 'clone') {
870 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', '', 'yes', 1);
871 }
872
873 // Call Hook formConfirm
874 $parameters = array('formConfirm' => $formconfirm);
875 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
876 if (empty($reshook)) {
877 $formconfirm .= $hookmanager->resPrint;
878 } elseif ($reshook > 0) {
879 $formconfirm = $hookmanager->resPrint;
880 }
881
882 // Print form confirm
883 print $formconfirm;
884
885 // project info
886 if ($projectid > 0) {
887 $projectstat = new Project($db);
888 if ($projectstat->fetch($projectid) > 0) {
889 $projectstat->fetch_thirdparty();
890
891 // To verify role of users
892 //$userAccess = $object->restrictedProjectArea($user,'read');
893 $userWrite = $projectstat->restrictedProjectArea($user, 'write');
894 //$userDelete = $object->restrictedProjectArea($user,'delete');
895 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
896
897 $head = project_prepare_head($projectstat);
898
899 print dol_get_fiche_head($head, 'ticket', $langs->trans("Project"), 0, ($projectstat->public ? 'projectpub' : 'project'));
900
901 print '<table class="border centpercent">';
902
903 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
904
905 // Ref
906 print '<tr><td>'.$langs->trans('Ref').'</td><td colspan="3">';
907 // Define a complementary filter for search of next/prev ref.
908 if (!$user->hasRight('projet', 'all', 'lire')) {
909 $objectsListId = $projectstat->getProjectsAuthorizedForUser($user, $mine, 0);
910 $projectstat->next_prev_filter = "rowid:IN:".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0');
911 }
912 print $form->showrefnav($projectstat, 'ref', $linkback, 1, 'ref', 'ref', '');
913 print '</td></tr>';
914
915 // Label
916 print '<tr><td>'.$langs->trans("Label").'</td><td>'.$projectstat->title.'</td></tr>';
917
918 // Customer
919 print "<tr><td>".$langs->trans("ThirdParty")."</td>";
920 print '<td colspan="3">';
921 if ($projectstat->thirdparty->id > 0) {
922 print $projectstat->thirdparty->getNomUrl(1);
923 } else {
924 print '&nbsp;';
925 }
926
927 print '</td></tr>';
928
929 // Visibility
930 print '<tr><td>'.$langs->trans("Visibility").'</td><td>';
931 if ($projectstat->public) {
932 print $langs->trans('SharedProject');
933 } else {
934 print $langs->trans('PrivateProject');
935 }
936
937 print '</td></tr>';
938
939 // Status
940 print '<tr><td>'.$langs->trans("Status").'</td><td>'.$projectstat->getLibStatut(4).'</td></tr>';
941
942 print "</table>";
943
944 print dol_get_fiche_end();
945 } else {
946 print "ErrorRecordNotFound";
947 }
948 } elseif ($socid > 0) {
949 $object->fetch_thirdparty();
950 $head = societe_prepare_head($object->thirdparty);
951
952 print dol_get_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company');
953
954 dol_banner_tab($object->thirdparty, 'socid', '', ($user->socid ? 0 : 1), 'rowid', 'nom');
955
956 print dol_get_fiche_end();
957 }
958
959 if (!$user->socid && getDolGlobalString('TICKET_LIMIT_VIEW_ASSIGNED_ONLY')) {
960 $object->next_prev_filter = "te.fk_user_assign:=:".((int) $user->id);
961 } elseif ($user->socid > 0) {
962 $object->next_prev_filter = "te.fk_soc:=:".((int) $user->socid);
963 }
964
965 $head = ticket_prepare_head($object);
966
967 print dol_get_fiche_head($head, 'tabTicket', $langs->trans("Ticket"), -1, 'ticket', 0, '', '', 0, '', 1);
968
969 $morehtmlref = '<div class="refidno">';
970
971 if ($permissiontoadd && !$user->socid) {
972 $morehtmlref .= '<a class="editfielda" href="'.$url_page_current.'?action=editsubject&token='.newToken().'&track_id='.urlencode($object->track_id).'">'.img_edit($langs->transnoentitiesnoconv('SetTitle'), 0).'</a> ';
973 }
974 if ($action != 'editsubject') {
975 $morehtmlref .= '<span class="smallonsmartphone">'.dolPrintLabel($object->subject).'</span>';
976 } else {
977 $morehtmlref .= '<form method="post" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
978 $morehtmlref .= '<input type="hidden" name="action" value="setsubject">';
979 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
980 $morehtmlref .= '<input type="hidden" name="id" value="'.$object->id.'">';
981 $morehtmlref .= '<input type="text" class="minwidth300" id="subject" name="subject" value="'.$object->subject.'" autofocus="" spellcheck="false">';
982 $morehtmlref .= '<input type="submit" class="smallpaddingimp button valignmiddle" name="modify" value="'.$langs->trans("Modify").'">';
983 $morehtmlref .= '<input type="submit" class="smallpaddingimp button button-cancel valignmiddle" name="cancel" value="'.$langs->trans("Cancel").'">';
984 $morehtmlref .= '</form>';
985 }
986
987 // Author
988 $createdbyshown = 0;
989 if ($object->fk_user_create > 0) {
990 $morehtmlref .= '<br>';
991 //$morehtmlref .= '<span class="opacitymedium">'.$langs->trans("CreatedBy").'</span> ';
992
993 $fuser = new User($db);
994 $fuser->fetch($object->fk_user_create);
995 $morehtmlref .= $fuser->getNomUrl(-4);
996 $createdbyshown++;
997 }
998
999 $createdfrompublicticket = 0;
1000 $createdfromemailcollector = 0;
1001 if (!empty($object->origin_email) && (empty($object->email_msgid) || preg_match('/dolibarr\-tic\d+/', $object->email_msgid))) {
1002 // If ticket create from public interface - TODO Add a more robust test to know if created by public interface
1003 $createdfrompublicticket = 1;
1004 } elseif (!empty($object->email_msgid)) {
1005 // If ticket create by emailcollector - TODO Add a more robust test to know if created by email collector (using import key ?)
1006 $createdfromemailcollector = 1;
1007 }
1008
1009 //var_dump($object);
1010 $htmltooltip = '';
1011 if ($createdfrompublicticket) {
1012 $htmltooltip .= $langs->trans("OriginEmail").': '.$object->origin_email;
1013 $htmltooltip .= '<br>'.$langs->trans("IP").': '.dol_print_ip($object->ip);
1014 $morehtmlref .= ($createdbyshown ? ' - ' : '<br>');
1015 //$morehtmlref .= ($createdbyshown ? '' : '<span class="opacitymedium">'.$langs->trans("CreatedBy").' </span> ');
1016 $morehtmlref .= img_picto('', 'email', 'class="paddingrightonly"');
1017 $morehtmlref .= dol_escape_htmltag($object->origin_email).' <small class="hideonsmartphone opacitymedium">- '.$form->textwithpicto($langs->trans("CreatedByPublicPortal"), $htmltooltip, 1, 'help', '', 0, 3, 'tooltipcreatedbyportal').'</small>';
1018 } elseif ($createdfromemailcollector) {
1019 $langs->load("mails");
1020
1021 $htmltooltip .= '<b>'.$langs->trans("EmailMsgID").':</b> '.$object->email_msgid;
1022 $htmltooltip .= '<br><b>'.$langs->trans("EmailDate").':</b> '.dol_print_date($object->email_date, 'dayhour');
1023 $htmltooltip .= '<br><b>'.$langs->trans("MailFrom").':</b> '.$object->origin_email;
1024 $htmltooltip .= '<br><b>'.$langs->trans("MailReply").':</b> '.$object->origin_replyto;
1025 $htmltooltip .= '<br><b>'.$langs->trans("MailReferences").':</b> '.$object->origin_references;
1026 $morehtmlref .= ($createdbyshown ? ' - ' : '<br>');
1027 //$morehtmlref .= ($createdbyshown ? '' : '<span class="opacitymedium">'.$langs->trans("CreatedBy").'</span> ');
1028 $morehtmlref .= img_picto('From', 'email', 'class="paddingrightonly"');
1029 $morehtmlref .= dol_escape_htmltag($object->origin_email);
1030 if ($object->origin_replyto) {
1031 $morehtmlref .= ' - '.img_picto('ReplyTo', 'email', 'class="paddingrightonly"');
1032 $morehtmlref .= dol_escape_htmltag($object->origin_replyto);
1033 }
1034 $morehtmlref .= ' <small class="hideonsmartphone opacitymedium">- '.$form->textwithpicto($langs->trans("CreatedByEmailCollector"), $htmltooltip, 1, 'help', '', 0, 3, 'tooltipcreatedbyemailcollector').'</small>';
1035 }
1036
1037 $permissiontoedit = $object->status < 8 && !$user->socid && $permissiontoadd;
1038 //$permissiontoedit = 0;
1039
1040 // Thirdparty
1041 if (isModEnabled("societe")) {
1042 $morehtmlref .= '<br>';
1043 if ($action != 'editcustomer' && $permissiontoedit) {
1044 $morehtmlref .= img_picto($langs->trans("ThirdParty"), 'company', 'class="pictofixedwidth"');
1045 $morehtmlref .= '<a class="editfielda" href="'.$url_page_current.'?action=editcustomer&token='.newToken().'&track_id='.$object->track_id.'">'.img_edit($langs->transnoentitiesnoconv('SetThirdParty'), 0).'</a> ';
1046 }
1047 $morehtmlref .= $form->form_thirdparty($url_page_current.'?track_id='.$object->track_id, (string) $object->socid, $action == 'editcustomer' ? 'editcustomer' : 'none', '', 1, 0, 0, array(), 1);
1048 if (!empty($object->socid)) {
1049 $morehtmlref .= ' - <a href="'.DOL_URL_ROOT.'/ticket/list.php?socid='.$object->socid.'&sortfield=t.datec&sortorder=desc'.(getDolGlobalBool('TICKET_CLIENT_OTHER_TICKET_ONLY_OPEN') ? '&search_fk_statut[]=openall' : '').'">'.img_picto($langs->trans("Tickets"), 'ticket', 'class="pictofixedwidth paddingright"').$langs->trans("TicketHistory").'</a>';
1050 }
1051 }
1052
1053 // Project
1054 if (isModEnabled('project')) {
1055 $langs->load("projects");
1056 $morehtmlref .= '<br>';
1057 if ($permissiontoedit) {
1058 $object->fetchProject();
1059 $morehtmlref .= img_picto($langs->trans("Project"), 'project'.((is_object($object->project) && $object->project->public) ? 'pub' : ''), 'class="pictofixedwidth"');
1060 if ($action != 'classify') {
1061 $morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1062 }
1063 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
1064 } else {
1065 if (!empty($object->fk_project)) {
1066 $object->fetchProject();
1067 $morehtmlref .= $object->project->getNomUrl(1);
1068 if ($object->project->title) {
1069 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($object->project->title).'</span>';
1070 }
1071 }
1072 }
1073 }
1074
1075 // Contract
1076 if (getDolGlobalString('TICKET_LINK_TO_CONTRACT_WITH_HARDLINK')) {
1077 // Deprecated. Duplicate feature. Ticket can already be linked to contract with the generic "Link to" feature.
1078 if (isModEnabled('contract')) {
1079 // This feature hang the application on large list of contracts, because the select component is not complete: it does not work like select of thirdparty or product to support large lists
1080 // So we add a hidden option to avoid to have it used and the application locked, until the select_contract is fixed.
1081 if (getDolGlobalString("CONTRACT_CAN_USE_THE_BUGGED_SELECT_COMPONENT")) {
1082 $langs->load('contracts');
1083 $morehtmlref .= '<br>';
1084 if ($permissiontoedit) {
1085 $morehtmlref .= img_picto($langs->trans("Contract"), 'contract', 'class="pictofixedwidth"');
1086 if ($action == 'edit_contrat') {
1087 $formcontract = new FormContract($db);
1088 $morehtmlref .= $formcontract->formSelectContract($_SERVER["PHP_SELF"].'?id='.$object->id, $object->socid, $object->fk_contract, 'contratid', 0, 1, 1, 1);
1089 } else {
1090 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edit_contrat&token='.newToken().'&id='.$object->id.'">';
1091 $morehtmlref .= img_edit($langs->trans('SetContract'));
1092 $morehtmlref .= '</a>';
1093 }
1094 } else {
1095 if (!empty($object->fk_contract)) {
1096 $contratstatic = new Contrat($db);
1097 $contratstatic->fetch($object->fk_contract);
1098 //print '<a href="'.DOL_URL_ROOT.'/projet/card.php?id='.$selected.'">'.$projet->title.'</a>';
1099 $morehtmlref .= $contratstatic->getNomUrl(0, 0, 1);
1100 }
1101 }
1102 }
1103 }
1104 }
1105
1106 $morehtmlref .= '</div>';
1107
1108 $linkback = '<a href="'.DOL_URL_ROOT.'/ticket/list.php?restore_lastsearch_values=1"><strong>'.$langs->trans("BackToList").'</strong></a> ';
1109
1110 dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', 'ref', $morehtmlref);
1111
1112 print '<div class="fichecenter">';
1113 print '<div class="fichehalfleft">';
1114 print '<div class="underbanner clearboth"></div>';
1115
1116 print '<table class="border tableforfield centpercent">';
1117
1118 // Subject
1119 /*
1120 print '<tr><td>';
1121 print $form->editfieldkey("Subject", 'subject', $object->subject, $object, $permissiontoadd && !$user->socid, 'string');
1122 print '</td><td>';
1123 print $form->editfieldval("Subject", 'subject', $object->subject, $object, $permissiontoadd && !$user->socid, 'string');
1124 print '</td></tr>';
1125 */
1126
1127 // Creation date
1128 print '<tr><td>'.$langs->trans("DateCreation").'</td><td>';
1129 print dol_print_date($object->datec, 'dayhour', 'tzuser');
1130 print '<span class="opacitymedium"><span class="small"> - '.$langs->trans("TimeElapsedSince").': <b><i>'.convertSecondToTime(roundUpToNextMultiple($now - $object->datec, 60)).'</i></b></span></span>';
1131 print '</td></tr>';
1132
1133 // Read date
1134 print '<tr><td>'.$langs->trans("TicketReadOn").'</td><td>';
1135 if (!empty($object->date_read)) {
1136 print dol_print_date($object->date_read, 'dayhour', 'tzuser');
1137 print '<span class="opacitymedium"><span class="small"> - '.$langs->trans("TimeElapsedSince").': ';
1138 //print '<b><i>'.convertSecondToTime(roundUpToNextMultiple($object->date_read - $object->datec, 60)).'</i></b>';
1139 //print ' / ';
1140 print '<b><i>'.convertSecondToTime(roundUpToNextMultiple($now - $object->date_read, 60)).'</i></b></span></span>';
1141 }
1142 print '</td></tr>';
1143
1144 // Close date
1145 print '<tr><td>'.$langs->trans("TicketCloseOn").'</td><td>';
1146 if (!empty($object->date_close)) {
1147 print dol_print_date($object->date_close, 'dayhour', 'tzuser');
1148 }
1149 print '</td></tr>';
1150
1151 // User assigned
1152 print '<tr><td>';
1153 print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">';
1154 print $langs->trans("AssignedTo");
1155 if (isset($object->status) && $object->status < $object::STATUS_CLOSED && GETPOST('set', 'alpha') != "assign_ticket" && $permissiontomanage) {
1156 print '</td><td class="right"><a class="editfielda" href="'.$url_page_current.'?track_id='.urlencode($object->track_id).'&set=assign_ticket">'.img_edit($langs->trans('Modify')).'</a>';
1157 }
1158 print '</td></tr></table>';
1159 print '</td><td>';
1160 if (GETPOST('set', 'alpha') != "assign_ticket" && $object->fk_user_assign > 0) {
1161 $userstat->fetch($object->fk_user_assign);
1162 print $userstat->getNomUrl(-1);
1163 }
1164
1165 // Show user list to assignate one if status is "read"
1166 if (GETPOST('set', 'alpha') == "assign_ticket" && $object->status < 8 && !$user->socid && $permissiontomanage) {
1167 print '<form method="post" name="ticket" enctype="multipart/form-data" action="'.$url_page_current.'">';
1168 print '<input type="hidden" name="token" value="'.newToken().'">';
1169 print '<input type="hidden" name="action" value="assign_user">';
1170 print '<input type="hidden" name="track_id" value="'.$object->track_id.'">';
1171 print $form->select_dolusers(empty($object->fk_user_assign) ? $user->id : $object->fk_user_assign, 'fk_user_assign', 1, null, 0, '', '', '', 0, 0, '', 0, '', '', 1);
1172 print ' <input type="submit" class="button smallpaddingimp" name="btn_assign_user" value="'.$langs->trans("Validate").'" />';
1173 print ' <input type="submit" class="button smallpaddingimp" name="btn_cancel" value="'.$langs->trans("Cancel").'" />';
1174 print '</form>';
1175 }
1176 print '</td></tr>';
1177
1178 // Progression
1179 print '<tr><td>';
1180 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
1181 print $langs->trans('Progression').'</td><td class="left">';
1182 print '</td>';
1183 if ($permissiontoadd && $action != 'progression' && isset($object->status) && $object->status < $object::STATUS_CLOSED && !$user->socid) {
1184 print '<td class="right"><a class="editfielda" href="'.$url_page_current.'?action=progression&token='.newToken().'&track_id='.urlencode($object->track_id).'">'.img_edit($langs->trans('Modify')).'</a></td>';
1185 }
1186 print '</tr></table>';
1187 print '</td><td>';
1188 if ($permissiontoadd && $action == 'progression') {
1189 print '<form action="'.$url_page_current.'" method="post">';
1190 print '<input type="hidden" name="token" value="'.newToken().'">';
1191 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1192 print '<input type="hidden" name="action" value="set_progression">';
1193 print '<input type="text" class="flat width75" name="progress" value="'.$object->progress.'">';
1194 print ' <input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Modify').'">';
1195 print '</form>';
1196 } else {
1197 print($object->progress > 0 ? $object->progress : '0').'%';
1198 }
1199 print '</td>';
1200 print '</tr>';
1201
1202 // Timing (Duration sum of linked fichinter)
1203 if (isModEnabled('intervention')) {
1204 $object->fetchObjectLinked();
1205 $num = count($object->linkedObjects);
1206 $timing = 0;
1207 $foundinter = 0;
1208 if ($num) {
1209 foreach ($object->linkedObjects as $objecttype => $objects) {
1210 if ($objecttype == "fichinter") {
1211 '@phan-var-force Fichinter[] $objects';
1212 foreach ($objects as $fichinter) {
1213 $foundinter++;
1215 $timing += $fichinter->duration;
1216 }
1217 }
1218 }
1219 }
1220 print '<tr><td>';
1221 print $form->textwithpicto($langs->trans("TicketDurationAuto"), $langs->trans("TicketDurationAutoInfos"), 1);
1222 print '</td><td>';
1223 print $foundinter ? convertSecondToTime($timing, 'all', getDolGlobalInt('MAIN_DURATION_OF_WORKDAY')) : '';
1224 print '</td></tr>';
1225 }
1226
1227 // Other attributes
1228 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1229
1230 print '</table>';
1231
1232
1233 // End of left column and beginning of right column
1234 print '</div><div class="fichehalfright">';
1235
1236
1237 print '<form method="post" name="formticketproperties" action="'.$url_page_current.'">';
1238 print '<input type="hidden" name="token" value="'.newToken().'">';
1239 print '<input type="hidden" name="action" value="change_property">';
1240 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1241 print '<input type="hidden" name="trackid" value="'.$trackid.'">';
1242
1243 // Classification of ticket
1244 print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
1245 print '<table class="border tableforfield centpercent margintable bordertopimp">';
1246 print '<tr class="liste_titre">';
1247 print '<td class="valignmiddle titlefield">';
1248 print '<table class="nobordernopadding centpercent"><tr><td class="none" style="border-bottom: none !important;">';
1249 print $langs->trans('TicketProperties');
1250 if (GETPOST('set', 'alpha') != 'properties' && isset($object->status) && ($object->status < $object::STATUS_NEED_MORE_INFO || !getDolGlobalInt('TICKET_DISALLOW_CLASSIFICATION_MODIFICATION_EVEN_IF_CLOSED')) && $permissiontoadd) {
1251 print '</td><td class="right" style="border-bottom: none !important;"><a class="editfielda" href="card.php?track_id='.$object->track_id.'&set=properties">'.img_edit($langs->trans('Modify')).'</a>';
1252 }
1253 print '</td></tr></table>';
1254 print '</td>';
1255 print '<td>';
1256 if (GETPOST('set', 'alpha') == 'properties' && $permissiontoadd) {
1257 print '<input type="submit" class="button smallpaddingimp" name="btn_update_ticket_prop" value="'.$langs->trans("Modify").'" />';
1258 }
1259 print '</td>';
1260 print '</tr>';
1261
1262 if (GETPOST('set', 'alpha') == 'properties' && $permissiontoadd) {
1263 print '<tr>';
1264 // Type
1265 print '<td class="titlefield">';
1266 print $langs->trans('Type');
1267 print '</td><td>';
1268 $formticket->selectTypesTickets($object->type_code, 'update_value_type', '', 2);
1269 print '</td>';
1270 print '</tr>';
1271 // Group
1272 print '<tr>';
1273 print '<td>';
1274 print $langs->trans('TicketCategory');
1275 print '</td><td>';
1276 $formticket->selectGroupTickets($object->category_code, 'update_value_category', '', 2, 0, 0, 0, 'maxwidth500 widthcentpercentminusxx');
1277 print '</td>';
1278 print '</tr>';
1279 // Severity
1280 print '<tr>';
1281 print '<td>';
1282 print $langs->trans('TicketSeverity');
1283 print '</td><td>';
1284 $formticket->selectSeveritiesTickets($object->severity_code, 'update_value_severity', '', 2);
1285 print '</td>';
1286 print '</tr>';
1287 } else {
1288 // Type
1289 print '<tr><td class="titlefield">'.$langs->trans("Type").'</td><td>';
1290 if (!empty($object->type_code)) {
1291 print $langs->getLabelFromKey($db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code);
1292 }
1293 print '</td></tr>';
1294 // Group
1295 $s = '';
1296 if (!empty($object->category_code)) {
1297 $s = $langs->getLabelFromKey($db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code);
1298 }
1299 print '<tr><td>'.$langs->trans("TicketCategory").'</td><td class="tdoverflowmax200" title="'.dol_escape_htmltag($s).'">';
1300 print dol_escape_htmltag($s);
1301 print '</td></tr>';
1302 // Severity
1303 print '<tr><td>'.$langs->trans("TicketSeverity").'</td><td>';
1304 if (!empty($object->severity_code)) {
1305 print $langs->getLabelFromKey($db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code);
1306 }
1307 print '</td></tr>';
1308 }
1309 print '</table>'; // End table actions
1310 print '</div>';
1311
1312 print '</form>';
1313
1314 // Tags/Categories
1315 if (isModEnabled('category')) {
1316 print '<!-- tag/categories -->'."\n";
1317 print '<table class="border centpercent tableforfield">';
1318 print '<tr>';
1319 print '<td class="valignmiddle titlefield">';
1320 print '<table class="nobordernopadding centpercent"><tr><td class="none">';
1321 print $langs->trans("Categories");
1322 if ($permissiontoadd && !in_array($object->status, [Ticket::STATUS_CLOSED, Ticket::STATUS_CANCELED]) && $action != 'categories' && !$user->socid) {
1323 print '</td><td class="right"><a class="editfielda" href="'.$url_page_current.'?action=categories&track_id='.urlencode($object->track_id).'">'.img_edit($langs->trans('Modify')).'</a>';
1324 }
1325 print '</td>';
1326 print '</table>';
1327 print '</td>';
1328
1329 if ($permissiontoadd && $action == 'categories') {
1330 print '<td colspan="3">';
1331 print '<form action="'.$url_page_current.'" method="POST">';
1332 print '<input type="hidden" name="token" value="'.newToken().'">';
1333 print '<input type="hidden" name="track_id" value="'.$track_id.'">';
1334 print '<input type="hidden" name="action" value="set_categories">';
1335 print $form->selectCategories(Categorie::TYPE_TICKET, 'categories', $object);
1336 print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Save').'">';
1337 print '</form>';
1338 print "</td>";
1339 } else {
1340 print '<td colspan="3">';
1341 print $form->showCategories($object->id, Categorie::TYPE_TICKET, 1);
1342 print "</td></tr>";
1343 }
1344
1345 print '</table>';
1346 }
1347
1348 // View Original message
1349 $actionobject->viewTicketOriginalMessage($user, $action, $object);
1350
1351
1352 // Display navbar with links to change ticket status
1353 print '<!-- navbar with status -->';
1354 if (!$user->socid && $permissiontomanage && isset($object->status) && $object->status < $object::STATUS_CLOSED) {
1355 $actionobject->viewStatusActions($object);
1356 }
1357
1358
1359 if (getDolGlobalString('MAIN_DISABLE_CONTACTS_TAB')) {
1360 print load_fiche_titre($langs->trans('Contacts'), '', 'title_companies.png');
1361
1362 print '<div class="div-table-responsive-no-min">';
1363 print '<div class="tagtable centpercent noborder allwidth">';
1364
1365 print '<div class="tagtr liste_titre">';
1366 print '<div class="tagtd">'.$langs->trans("Source").'</div>
1367 <div class="tagtd">' . $langs->trans("Company").'</div>
1368 <div class="tagtd">' . $langs->trans("Contacts").'</div>
1369 <div class="tagtd">' . $langs->trans("ContactType").'</div>
1370 <div class="tagtd">' . $langs->trans("Phone").'</div>
1371 <div class="tagtd center">' . $langs->trans("Status").'</div>';
1372 print '</div><!-- tagtr -->';
1373
1374 // Contact list
1375 $companystatic = new Societe($db);
1376 $contactstatic = new Contact($db);
1377 $userstatic = new User($db);
1378 $var = false;
1379 foreach (array('internal', 'external') as $source) {
1380 $tmpobject = $object;
1381 $tab = $tmpobject->listeContact(-1, $source);
1382 // '@phan-var-force array<array{source:string,id:int,rowid:int,email:string,civility:string,firstname:string,lastname:string,labeltype:string,libelle:string,socid:int,code:string,status:int,statuscontact:int,fk_c_typecontact:string,phone:string,phone_mobile:string,phone_perso?:string,nom:string}> $tab';
1383 $num = is_array($tab) ? count($tab) : 0;
1384 $i = 0;
1385 foreach (array_keys($tab) as $i) {
1386 $tab_i = &$tab[$i];
1387 $var = !$var;
1388 print '<div class="tagtr '.($var ? 'pair' : 'impair').'">';
1389
1390 print '<div class="tagtd left">';
1391 if ($tab_i['source'] == 'internal') {
1392 echo $langs->trans("User");
1393 }
1394
1395 if ($tab_i['source'] == 'external') {
1396 echo $langs->trans("ThirdPartyContact");
1397 }
1398
1399 print '</div>';
1400 print '<div class="tagtd left">';
1401
1402 if ($tab_i['socid'] > 0) {
1403 $companystatic->fetch($tab_i['socid']);
1404 echo $companystatic->getNomUrl(-1);
1405 }
1406 if ($tab_i['socid'] < 0) {
1407 echo getDolGlobalString('MAIN_INFO_SOCIETE_NOM');
1408 }
1409 if (!$tab_i['socid']) {
1410 echo '&nbsp;';
1411 }
1412 print '</div>';
1413
1414 print '<div class="tagtd">';
1415 if ($tab_i['source'] == 'internal') {
1416 if ($userstatic->fetch($tab_i['id'])) {
1417 print $userstatic->getNomUrl(-1);
1418 }
1419 }
1420 if ($tab_i['source'] == 'external') {
1421 if ($contactstatic->fetch($tab_i['id'])) {
1422 print $contactstatic->getNomUrl(-1);
1423 }
1424 }
1425 print ' </div>
1426 <div class="tagtd">' . $tab_i['libelle'].'</div>';
1427
1428 print '<div class="tagtd">';
1429
1430 print dol_print_phone($tab_i['phone'], '', 0, 0, 'AC_TEL').'<br>';
1431
1432 if (array_key_exists('phone_perso', $tab_i) && !empty($tab_i['phone_perso'])) {
1433 //print img_picto($langs->trans('PhonePerso'),'object_phoning.png','',0,0,0).' ';
1434 print '<br>'.dol_print_phone((string) $tab_i['phone_perso'], '', 0, 0, 'AC_TEL').'<br>';
1435 }
1436 if (!empty($tab_i['phone_mobile'])) {
1437 //print img_picto($langs->trans('PhoneMobile'),'object_phoning.png','',0,0,0).' ';
1438 print dol_print_phone($tab_i['phone_mobile'], '', 0, 0, 'AC_TEL').'<br>';
1439 }
1440 print '</div>';
1441
1442 print '<div class="tagtd center">';
1443 if ($object->status >= 0) {
1444 echo '<a href="contact.php?track_id='.$object->track_id.'&amp;action=swapstatut&amp;ligne='.$tab_i['rowid'].'">';
1445 }
1446
1447 if ($tab_i['source'] == 'internal') {
1448 $userstatic->id = $tab_i['id'];
1449 $userstatic->lastname = $tab_i['lastname'];
1450 $userstatic->firstname = $tab_i['firstname'];
1451 echo $userstatic->LibStatut($tab_i['statuscontact'], 3);
1452 }
1453 if ($tab_i['source'] == 'external') {
1454 $contactstatic->id = $tab_i['id'];
1455 $contactstatic->lastname = $tab_i['lastname'];
1456 $contactstatic->firstname = $tab_i['firstname'];
1457 echo $contactstatic->LibStatut($tab_i['statuscontact'], 3);
1458 }
1459 if ($object->status >= 0) {
1460 echo '</a>';
1461 }
1462
1463 print '</div>';
1464
1465 print '</div><!-- tagtr -->';
1466
1467 $i++;
1468 }
1469 }
1470
1471 print '</div><!-- contact list -->';
1472 print '</div>';
1473 }
1474
1475 print '</div></div>';
1476 print '<div class="clearboth"></div>';
1477
1478 print dol_get_fiche_end();
1479
1480
1481 // Buttons for actions
1482 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'editline') {
1483 print '<div class="tabsAction">'."\n";
1484 $parameters = array();
1485 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1486 if ($reshook < 0) {
1487 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1488 }
1489
1490 if (empty($reshook)) {
1491 // Email
1492 if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1493 print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER["PHP_SELF"].'?action=presend_addmessage&send_email=1&private_message=0&mode=init&token='.newToken().'&track_id='.$object->track_id.'#formmailbeforetitle', '');
1494 }
1495
1496 // Show link to add a message (if read and not closed)
1497 if (isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage") {
1498 print dolGetButtonAction('', $langs->trans('TicketAddPrivateMessage'), 'default', $_SERVER["PHP_SELF"].'?action=presend_addmessage&mode=init&token='.newToken().'&track_id='.$object->track_id.'#formmailbeforetitle', '');
1499 }
1500
1501 // Link to create an intervention
1502 // socid is needed otherwise fichinter ask it and forgot origin after form submit :\
1503 if (!$object->fk_soc && $user->hasRight("ficheinter", "creer")) {
1504 print dolGetButtonAction($langs->trans('UnableToCreateInterIfNoSocid'), $langs->trans('TicketAddIntervention'), 'default', $_SERVER['PHP_SELF']. '#', '', false);
1505 }
1506 if ($object->fk_soc > 0 && isset($object->status) && $object->status < Ticket::STATUS_CLOSED && $user->hasRight('ficheinter', 'creer')) {
1507 print dolGetButtonAction('', $langs->trans('TicketAddIntervention'), 'default', DOL_URL_ROOT.'/fichinter/card.php?action=create&token='.newToken().'&socid='. $object->fk_soc.'&origin=ticket_ticket&originid='. $object->id, '');
1508 }
1509
1510 // Close ticket if status is read
1511 if (isset($object->status) && $object->status >= 0 && $object->status < Ticket::STATUS_CLOSED && $permissiontomanage) {
1512 print dolGetButtonAction('', $langs->trans('CloseTicket'), 'default', $_SERVER["PHP_SELF"].'?action=close&token='.newToken().'&track_id='.$object->track_id, '');
1513 }
1514
1515 // Abandon ticket if status is read
1516 if (isset($object->status) && $object->status > 0 && $object->status < Ticket::STATUS_CLOSED && $permissiontomanage) {
1517 print dolGetButtonAction('', $langs->trans('AbandonTicket'), 'default', $_SERVER["PHP_SELF"].'?action=abandon&token='.newToken().'&track_id='.$object->track_id, '');
1518 }
1519
1520 // Re-open ticket
1521 if ($permissiontomanage && !$user->socid && (isset($object->status) && ($object->status == Ticket::STATUS_CLOSED || $object->status == Ticket::STATUS_CANCELED)) && !$user->socid) {
1522 print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&track_id='.$object->track_id, '');
1523 }
1524
1525 // Edit ticket
1526 if ($permissiontoedit) {
1527 print dolGetButtonAction('', $langs->trans('Modify'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken(), '', $permissiontoedit);
1528 }
1529
1530 // Clone
1531 if ($permissiontoadd) {
1532 print dolGetButtonAction('', $langs->trans('ToClone'), 'clone', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=clone&token='.newToken(), '', $permissiontoadd);
1533 }
1534
1535 // Delete ticket
1536 if ($permissiontodelete && !$user->socid) {
1537 print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&track_id='.$object->track_id, '');
1538 }
1539 }
1540 print '</div>'."\n";
1541 }
1542
1543 // Select mail models is same action as presend
1544 if (GETPOST('modelselected')) {
1545 $action = 'presend';
1546 }
1547 // Set $action to correct value for the case we used presend action to add a message
1548 if (GETPOSTISSET('actionbis') && $action == 'presend') {
1549 $action = 'presend_addmessage';
1550 }
1551
1552 // add a message
1553 if ($action == 'presend' || $action == 'presend_addmessage') {
1554 if ($object->fk_soc > 0) {
1555 $object->fetch_thirdparty();
1556 }
1557
1558 $outputlangs = $langs;
1559 $newlang = '';
1560 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
1561 $newlang = GETPOST('lang_id', 'aZ09');
1562 } elseif (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && is_object($object->thirdparty)) {
1563 $newlang = $object->thirdparty->default_lang;
1564 }
1565 if (!empty($newlang)) {
1566 $outputlangs = new Translate("", $conf);
1567 $outputlangs->setDefaultLang($newlang);
1568 }
1569
1570 $arrayoffamiliestoexclude = array('objectamount');
1571
1572 $action = 'add_message'; // action to use to post the message
1573 $modelmail = 'ticket_send';
1574
1575 // Substitution array
1576 $morehtmlright = '';
1577 //$help = "";
1578 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object);
1579 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1580 //$morehtmlright .= $form->textwithpicto('<span class="opacitymedium">'.$langs->trans("TicketMessageSubstitutionReplacedByGenericValues").'</span>', $help, 1, 'helpclickable', '', 0, 3, 'helpsubstitution');
1581
1582 print '<div>';
1583
1584 print '<div id="formmailbeforetitle" name="formmailbeforetitle"></div>';
1585
1586 print load_fiche_titre($langs->trans('TicketAddMessage'), $morehtmlright, 'fa-comment-dots');
1587
1588 print '<hr>';
1589
1590 $formticket = new FormTicket($db);
1591
1592 $formticket->action = $action;
1593 $formticket->track_id = $object->track_id;
1594 $formticket->ref = $object->ref;
1595 $formticket->id = $object->id;
1596 $formticket->trackid = 'tic'.$object->id;
1597
1598 $formticket->withfile = 2;
1599 $formticket->withcancel = 1;
1600 $formticket->param = array('fk_user_create' => $user->id);
1601 $formticket->param['langsmodels'] = (empty($newlang) ? $langs->defaultlang : $newlang);
1602
1603 // Table of additional post parameters
1604 $formticket->param['models'] = $modelmail;
1605 $formticket->param['models_id'] = GETPOSTINT('modelmailselected');
1606 //$formticket->param['socid']=$object->fk_soc;
1607 $formticket->param['returnurl'] = $_SERVER["PHP_SELF"].'?track_id='.urldecode($object->track_id);
1608
1609 $formticket->withsubstit = 1;
1610 $formticket->substit = $substitutionarray;
1611 $formticket->backtopage = $backtopage;
1612
1613 $formticket->withtitletopic = 1;
1614
1615 $formticket->showMessageForm('100%', 0);
1616
1617 print '</div>';
1618 }
1619
1620 // Show messages on card (Note: this is a duplicate of the view Events/Agenda but on the main tab)
1621 if (getDolGlobalString('TICKET_SHOW_MESSAGES_ON_CARD')) {
1622 $param = '&id='.$object->id;
1623 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
1624 $param .= '&contextpage='.$contextpage;
1625 }
1626 if ($limit > 0 && $limit != $conf->liste_limit) {
1627 $param .= '&limit='.$limit;
1628 }
1629 if ($actioncode) {
1630 $param .= '&actioncode='.urlencode($actioncode);
1631 }
1632 if ($search_agenda_label) {
1633 $param .= '&search_agenda_label='.urlencode($search_agenda_label);
1634 }
1635
1636 $morehtmlright = '';
1637
1638 $messagingUrl = DOL_URL_ROOT.'/ticket/agenda.php?track_id='.$object->track_id;
1639 $morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fa fa-bars imgforviewmode', $messagingUrl, '', 1);
1640
1641 // Show link to add a message (if read and not closed)
1642 $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1643 $url = 'card.php?track_id='.$object->track_id.'&action=presend_addmessage&mode=init';
1644 $morehtmlright .= dolGetButtonTitle($langs->trans('TicketAddMessage'), '', 'fa fa-comment-dots', $url, 'add-new-ticket-title-button', (int) $btnstatus);
1645
1646 // Show link to add event (if read and not closed)
1647 $btnstatus = $object->status < Ticket::STATUS_CLOSED && $action != "presend" && $action != "presend_addmessage" && $action != "add_message";
1648 $url = dol_buildpath('/comm/action/card.php', 1).'?action=create&datep='.date('YmdHi').'&origin=ticket&originid='.$object->id.'&projectid='.$object->fk_project.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?track_id='.$object->track_id);
1649 $morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', $url, 'add-new-ticket-even-button', (int) $btnstatus);
1650
1651 print_barre_liste($langs->trans("ActionsOnTicket"), 0, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 1);
1652
1653 // List of all actions
1654 $filters = array();
1655 $filters['search_agenda_label'] = $search_agenda_label;
1656 $filters['search_rowid'] = $search_rowid;
1657
1658 show_actions_messaging($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder);
1659 }
1660
1661 if ($action != 'presend' && $action != 'presend_addmessage' && $action != 'add_message') {
1662 print '<div class="fichecenter"><div class="fichehalfleft">';
1663 print '<a name="builddoc"></a>'; // ancre
1664 /*
1665 * Generated documents
1666 */
1667 $filename = dol_sanitizeFileName($object->ref);
1668 $filedir = $upload_dir."/".dol_sanitizeFileName($object->ref);
1669 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
1670 $genallowed = $permissiontoadd;
1671 $delallowed = $permissiontodelete;
1672 $codelang = '';
1673 if ($object->fk_soc > 0) {
1674 $object->fetch_thirdparty();
1675 $codelang = $object->thirdparty->default_lang;
1676 }
1677
1678 print $formfile->showdocuments('ticket', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $codelang);
1679
1680 // Show links to link elements
1681 $tmparray = $form->showLinkToObjectBlock($object, array(), array('ticket'), 1);
1682 $linktoelem = $tmparray['linktoelem'];
1683 $htmltoenteralink = $tmparray['htmltoenteralink'];
1684 print $htmltoenteralink;
1685
1686 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1687
1688 // Show direct link to public interface
1689 print '<br><!-- Link to public interface -->'."\n";
1690 print showDirectPublicLink($object).'<br>';
1691 print '</div>';
1692
1693 if (!getDolGlobalString('MAIN_HIDE_MESSAGES_ON_CARD')) {
1694 print '<div class="fichehalfright">';
1695
1696 $MAXEVENT = 10;
1697
1698 $morehtmlcenter = '<div class="nowraponall">';
1699 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT.'/ticket/messaging.php?id='.$object->id);
1700 $morehtmlcenter .= dolGetButtonTitle($langs->trans('FullList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/ticket/agenda.php?id='.$object->id);
1701 $morehtmlcenter .= '</div>';
1702
1703 // List of actions on element
1704 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1705 $formactions = new FormActions($db);
1706 $somethingshown = $formactions->showactions($object, 'ticket', $socid, 1, 'listactions', $MAXEVENT, '', $morehtmlcenter);
1707
1708 print '</div>';
1709 }
1710
1711 print '</div>';
1712 }
1713 }
1714}
1715
1716// End of page
1717llxFooter();
1718$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class Actions of the module ticket.
Class to manage contact/addresses.
Class to manage building of HTML components.
Class to manage generation of HTML components for contract module.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
static checkRequiredFields(array $fields, int &$errors)
Check required fields.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
societe_prepare_head(Societe $object, $subtabs='')
Return array of tabs to used on pages for third parties cards.
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:248
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
dol_print_ip($ip, $mode=0, $showname=0)
Return an IP formatted to be shown on screen.
dol_print_phone($phone, $countrycode='', $contactid=0, $socid=0, $addlink='', $separ="&nbsp;", $withpicto='', $titlealt='', $adddivfloat=0, $morecss='paddingright')
Format phone numbers according to country.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalBool($key, $default=false)
Return a Dolibarr global constant boolean value.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Class to generate the form for creating a new ticket.
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
Definition receipt.php:487
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
showDirectPublicLink($object)
Return string with full Url.
ticket_prepare_head($object)
Build tabs for a Ticket object.