dolibarr 21.0.0-alpha
actioncomm.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2002-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
7 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
8 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
9 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
10 * Copyright (C) 2024 William Mead <william.mead@manchenumerique.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
31require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php';
32require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
34require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncommreminder.class.php';
35
36
41{
45 public $element = 'action';
46
50 public $table_element = 'actioncomm';
51
55 public $table_rowid = 'id';
56
60 public $picto = 'action';
61
67 public $restrictiononfksoc = 2;
68
72 public $id;
73
77 public $ref;
78
83 public $type_id;
84
89 public $type;
90
95 public $type_code;
96
100 public $type_label;
101
105 public $type_color;
106
110 public $type_picto;
111
116 public $code;
117
121 public $label;
122
126 public $datec;
127
131 public $duree;
132
136 public $datem;
137
143 public $author;
144
150 public $usermod;
151
155 public $authorid;
156
160 public $usermodid;
161
165 public $datep;
166
170 public $datef;
171
175 public $date_start_in_calendar;
176
180 public $date_end_in_calendar;
181
185 public $datep2;
186
191 public $durationp = -1;
192
196 public $fulldayevent = 0;
197
201 public $ponctuel;
202
206 public $percentage;
207
211 public $location;
212
216 public $transparency;
217
221 public $priority;
222
226 public $userassigned = array();
227
231 public $userownerid;
232
236 public $socpeopleassigned = array();
237
241 public $otherassigned = array();
242
246 public $reminders = array();
247
251 public $socid;
252
256 public $contact_id;
257
261 public $fk_task;
262
268 public $societe;
269
275 public $contact;
276
277 // Properties for links to other objects
282 public $fk_element; // Id of record
283
287 public $elementid;
288
292 public $elementtype;
293
297 public $fk_bookcal_calendar;
298
302 public $icalname;
303
307 public $icalcolor;
308
312 public $extraparams;
313
317 public $actions = array();
318
322 public $email_msgid;
323
327 public $email_from;
328
332 public $email_sender;
333
337 public $email_to;
338
342 public $email_tocc;
346 public $email_tobcc;
347
351 public $email_subject;
352
356 public $errors_to;
357
361 public $num_vote;
362
366 public $event_paid;
367
371 public $status;
372
376 public $ip;
377
378 /*
379 * Properties to manage the recurring events
380 */
382 public $recurid;
384 public $recurrule;
386 public $recurdateend;
387
389 public $calling_duration;
390
391
395 const EVENT_TODO = 0;
396
401
405 const EVENT_FINISHED = 100;
406
407
408 public $fields = array();
409
415 public function __construct(DoliDB $db)
416 {
417 $this->db = $db;
418
419 $this->ismultientitymanaged = 1;
420 }
421
430 public function create(User $user, $notrigger = 0)
431 {
432 global $langs, $conf;
433
434 $error = 0;
435 $now = dol_now();
436
437 // Check parameters
438 if (!isset($this->userownerid) || (string) $this->userownerid === '') { // $this->userownerid may be 0 (anonymous event) or > 0
439 dol_syslog("You tried to create an event but mandatory property userownerid was empty (you can define it to 0 for anonymous event)", LOG_WARNING);
440 $this->errors[] = 'ErrorActionCommPropertyUserowneridNotDefined';
441 return -1;
442 }
443
444 // Clean parameters
445 $this->label = dol_trunc(trim($this->label), 128);
446 $this->location = (!empty($this->location) ? dol_trunc(trim($this->location), 128) : "");
447 $this->note_private = dol_htmlcleanlastbr(trim(empty($this->note_private) ? $this->note : $this->note_private));
448 if (empty($this->percentage)) {
449 $this->percentage = 0;
450 }
451 if (empty($this->priority) || !is_numeric($this->priority)) {
452 $this->priority = 0;
453 }
454 if (empty($this->fulldayevent)) {
455 $this->fulldayevent = 0;
456 }
457 if (empty($this->transparency)) {
458 $this->transparency = 0;
459 }
460 if ($this->percentage > 100) {
461 $this->percentage = 100;
462 }
463 if (empty($this->datep) && $this->datep != '0') { // We should not insert event in calendar without a start date
464 $this->datep = $now;
465 }
466 if (!empty($this->datep) && !empty($this->datef)) {
467 $this->durationp = ($this->datef - $this->datep); // deprecated
468 }
469 if (!empty($this->datep) && !empty($this->datef) && $this->datep > $this->datef) {
470 $this->datef = $this->datep;
471 }
472 if (!isset($this->fk_project) || $this->fk_project < 0) {
473 $this->fk_project = 0;
474 }
475 if (!isset($this->fk_task) || $this->fk_task < 0) {
476 $this->fk_task = 0;
477 }
478 // For backward compatibility
479 if ($this->elementtype == 'facture') {
480 $this->elementtype = 'invoice';
481 }
482 if ($this->elementtype == 'commande') {
483 $this->elementtype = 'order';
484 }
485 if ($this->elementtype == 'contrat') {
486 $this->elementtype = 'contract';
487 }
488 if (empty($this->fk_element) && !empty($this->elementid)) {
489 $this->fk_element = $this->elementid;
490 }
491 if (empty($this->elementid) && !empty($this->fk_element)) {
492 $this->elementid = $this->fk_element;
493 }
494
495 if (!is_array($this->userassigned) && !empty($this->userassigned)) { // For backward compatibility when userassigned was an int instead of an array
496 $tmpid = (int) $this->userassigned;
497 $this->userassigned = array();
498 $this->userassigned[$tmpid] = array('id' => $tmpid, 'transparency' => $this->transparency);
499 }
500
501 $userownerid = $this->userownerid;
502
503 // Be sure assigned user is defined as an array of array('id'=>,'mandatory'=>,...).
504 if (empty($this->userassigned) || count($this->userassigned) == 0 || !is_array($this->userassigned)) {
505 $this->userassigned = array($userownerid => array('id' => $userownerid, 'transparency' => $this->transparency));
506 }
507
508 if (!$this->type_id || !$this->type_code) {
509 $key = empty($this->type_id) ? $this->type_code : $this->type_id;
510
511 // Get id from code
512 $cactioncomm = new CActionComm($this->db);
513 $result = $cactioncomm->fetch($key);
514
515 if ($result > 0) {
516 $this->type_id = $cactioncomm->id;
517 $this->type_code = $cactioncomm->code;
518 } elseif ($result == 0) {
519 $this->error = $langs->trans('ErrorActionCommBadType', $this->type_id, $this->type_code);
520 return -1;
521 } else {
522 $this->error = $cactioncomm->error;
523 return -1;
524 }
525 }
526 $code = empty($this->code) ? $this->type_code : $this->code;
527
528 // Check parameters
529 if (!$this->type_id) {
530 $this->error = "ErrorWrongParameters";
531 return -1;
532 }
533
534 $this->db->begin();
535
536 $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm";
537 $sql .= "(ref,";
538 $sql .= "datec,";
539 $sql .= "datep,";
540 $sql .= "datep2,";
541 $sql .= "durationp,"; // deprecated
542 $sql .= "fk_action,";
543 $sql .= "code,";
544 $sql .= "ref_ext,";
545 $sql .= "fk_soc,";
546 $sql .= "fk_project,";
547 $sql .= "note,";
548 $sql .= "fk_contact,";
549 $sql .= "fk_user_author,";
550 $sql .= "fk_user_action,";
551 $sql .= "label,percent,priority,fulldayevent,location,";
552 $sql .= "transparency,";
553 $sql .= "fk_element,";
554 $sql .= "elementtype,";
555 $sql .= "fk_bookcal_calendar,";
556 $sql .= "entity,";
557 $sql .= "extraparams,";
558 // Fields emails
559 $sql .= "email_msgid,";
560 $sql .= "email_from,";
561 $sql .= "email_sender,";
562 $sql .= "email_to,";
563 $sql .= "email_tocc,";
564 $sql .= "email_tobcc,";
565 $sql .= "email_subject,";
566 $sql .= "errors_to,";
567 $sql .= "recurid,";
568 $sql .= "recurrule,";
569 $sql .= "recurdateend,";
570 $sql .= "num_vote,";
571 $sql .= "event_paid,";
572 $sql .= "status,";
573 $sql .= "ip";
574 $sql .= ") VALUES (";
575 $sql .= "'(PROV)', ";
576 $sql .= "'".$this->db->idate($now)."', "; // date creation
577 $sql .= "'".$this->db->idate($this->datep)."', "; // date start event
578 $sql .= (strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : "null").", ";
579 $sql .= ((isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '') ? "'".$this->db->escape($this->durationp)."'" : "null").", "; // deprecated
580 $sql .= (isset($this->type_id) ? $this->type_id : "null").",";
581 $sql .= ($code ? ("'".$this->db->escape($code)."'") : "null").", ";
582 $sql .= (!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : "null").", ";
583 $sql .= ((isset($this->socid) && $this->socid > 0) ? ((int) $this->socid) : "null").", ";
584 $sql .= ((isset($this->fk_project) && $this->fk_project > 0) ? ((int) $this->fk_project) : "null").", ";
585 $sql .= " '".$this->db->escape($this->note_private)."', ";
586 $sql .= ((isset($this->contact_id) && $this->contact_id > 0) ? ((int) $this->contact_id) : "null").", "; // deprecated, use ->socpeopleassigned
587 $sql .= (isset($user->id) && $user->id > 0 ? $user->id : "null").", ";
588 $sql .= ($userownerid > 0 ? $userownerid : "null").", ";
589 $sql .= "'".$this->db->escape($this->label)."', ";
590 $sql .= "'".$this->db->escape($this->percentage)."', ";
591 $sql .= "'".$this->db->escape($this->priority)."', ";
592 $sql .= "'".$this->db->escape($this->fulldayevent)."', ";
593 $sql .= "'".$this->db->escape($this->location)."', ";
594 $sql .= "'".$this->db->escape($this->transparency)."', ";
595 $sql .= (!empty($this->fk_element) ? ((int) $this->fk_element) : "null").", ";
596 $sql .= (!empty($this->elementtype) ? "'".$this->db->escape($this->elementtype)."'" : "null").", ";
597 $sql .= (!empty($this->fk_bookcal_calendar) ? "'".$this->db->escape($this->fk_bookcal_calendar)."'" : "null").", ";
598 $sql .= ((int) $conf->entity).",";
599 $sql .= (!empty($this->extraparams) ? "'".$this->db->escape($this->extraparams)."'" : "null").", ";
600 // Fields emails
601 $sql .= (!empty($this->email_msgid) ? "'".$this->db->escape($this->email_msgid)."'" : "null").", ";
602 $sql .= (!empty($this->email_from) ? "'".$this->db->escape($this->email_from)."'" : "null").", ";
603 $sql .= (!empty($this->email_sender) ? "'".$this->db->escape($this->email_sender)."'" : "null").", ";
604 $sql .= (!empty($this->email_to) ? "'".$this->db->escape($this->email_to)."'" : "null").", ";
605 $sql .= (!empty($this->email_tocc) ? "'".$this->db->escape($this->email_tocc)."'" : "null").", ";
606 $sql .= (!empty($this->email_tobcc) ? "'".$this->db->escape($this->email_tobcc)."'" : "null").", ";
607 $sql .= (!empty($this->email_subject) ? "'".$this->db->escape($this->email_subject)."'" : "null").", ";
608 $sql .= (!empty($this->errors_to) ? "'".$this->db->escape($this->errors_to)."'" : "null").", ";
609 $sql .= (!empty($this->recurid) ? "'".$this->db->escape($this->recurid)."'" : "null").", ";
610 $sql .= (!empty($this->recurrule) ? "'".$this->db->escape($this->recurrule)."'" : "null").", ";
611 $sql .= (!empty($this->recurdateend) ? "'".$this->db->idate($this->recurdateend)."'" : "null").", ";
612 $sql .= (!empty($this->num_vote) ? (int) $this->num_vote : "null").", ";
613 $sql .= (!empty($this->event_paid) ? (int) $this->event_paid : 0).", ";
614 $sql .= (!empty($this->status) ? (int) $this->status : "0").", ";
615 $sql .= (!empty($this->ip) ? "'".$this->db->escape($this->ip)."'" : "null");
616 $sql .= ")";
617
618 dol_syslog(get_class($this)."::add", LOG_DEBUG);
619 $resql = $this->db->query($sql);
620 if ($resql) {
621 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."actioncomm", "id");
622 $this->ref = (string) $this->id;
623 $sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm SET ref='".$this->db->escape($this->ref)."' WHERE id=".$this->id;
624 $resql = $this->db->query($sql);
625 if (!$resql) {
626 $error++;
627 dol_syslog('Error to process ref: '.$this->db->lasterror(), LOG_ERR);
628 $this->errors[] = $this->db->lasterror();
629 }
630 // Now insert assigned users
631 if (!$error) {
632 //dol_syslog(var_export($this->userassigned, true));
633 $already_inserted = array();
634 foreach ($this->userassigned as $key => $val) {
635 // Common value with new behavior is to have $val = array('id'=>iduser, 'transparency'=>0|1) and $this->userassigned is an array of iduser => $val.
636 if (!is_array($val)) { // For backward compatibility when $val='id'.
637 $val = array('id' => $val);
638 }
639
640 if ($val['id'] > 0) {
641 if (!empty($already_inserted[$val['id']])) {
642 continue;
643 }
644
645 $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
646 $sql .= " VALUES(".((int) $this->id).", 'user', ".((int) $val['id']).", ".(empty($val['mandatory']) ? '0' : ((int) $val['mandatory'])).", ".(empty($val['transparency']) ? '0' : ((int) $val['transparency'])).", ".(empty($val['answer_status']) ? '0' : ((int) $val['answer_status'])).")";
647
648 $resql = $this->db->query($sql);
649 if (!$resql) {
650 $error++;
651 dol_syslog('Error to process userassigned: ' . $this->db->lasterror(), LOG_ERR);
652 $this->errors[] = $this->db->lasterror();
653 } else {
654 $already_inserted[$val['id']] = true;
655 }
656 //var_dump($sql);exit;
657 }
658 }
659 }
660
661 if (!$error) {
662 if (!empty($this->socpeopleassigned)) {
663 $already_inserted = array();
664 foreach ($this->socpeopleassigned as $id => $val) {
665 // Common value with new behavior is to have $this->socpeopleassigned an array of idcontact => dummyvalue
666 if (!empty($already_inserted[$id])) {
667 continue;
668 }
669
670 $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
671 $sql .= " VALUES(".((int) $this->id).", 'socpeople', ".((int) $id).", 0, 0, 0)";
672
673 $resql = $this->db->query($sql);
674 if (!$resql) {
675 $error++;
676 dol_syslog('Error to process socpeopleassigned: ' . $this->db->lasterror(), LOG_ERR);
677 $this->errors[] = $this->db->lasterror();
678 } else {
679 $already_inserted[$id] = true;
680 }
681 }
682 }
683 }
684
685 if (!$error) {
686 // Actions on extra fields
687 $result = $this->insertExtraFields();
688 if ($result < 0) {
689 $error++;
690 }
691 }
692
693 if (!$error && !$notrigger) {
694 // Call trigger
695 $result = $this->call_trigger('ACTION_CREATE', $user);
696 if ($result < 0) {
697 $error++;
698 }
699 // End call triggers
700 }
701
702 if (!$error) {
703 $this->db->commit();
704 return $this->id;
705 } else {
706 $this->db->rollback();
707 return -1;
708 }
709 } else {
710 $this->db->rollback();
711 $this->error = $this->db->lasterror();
712 return -1;
713 }
714 }
715
723 public function createFromClone(User $fuser, $socid)
724 {
725 global $hookmanager;
726
727 $error = 0;
728
729 $this->db->begin();
730
731 // Load source object
732 $objFrom = clone $this;
733
734 // Retrieve all extrafield
735 // fetch optionals attributes and labels
736 $this->fetch_optionals();
737
738 //$this->fetch_userassigned();
739 $this->fetchResources();
740
741 $this->id = 0;
742 $this->recurid = '';
743 $this->recurrule = '';
744 $this->recurdateend = '';
745
746 // Create clone
747 $this->context['createfromclone'] = 'createfromclone';
748 $result = $this->create($fuser);
749 if ($result < 0) {
750 $error++;
751 }
752
753 if (!$error) {
754 // Hook of thirdparty module
755 if (is_object($hookmanager)) {
756 $parameters = array('objFrom' => $objFrom);
757 $action = '';
758 $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
759 if ($reshook < 0) {
760 $this->setErrorsFromObject($hookmanager);
761 $error++;
762 }
763 }
764
765 // Call trigger
766 $result = $this->call_trigger('ACTION_CLONE', $fuser);
767 if ($result < 0) {
768 $error++;
769 }
770 // End call triggers
771 }
772
773 unset($this->context['createfromclone']);
774
775 // End
776 if (!$error) {
777 $this->db->commit();
778 return $this->id;
779 } else {
780 $this->db->rollback();
781 return -1;
782 }
783 }
784
795 public function fetch($id, $ref = '', $ref_ext = '', $email_msgid = '', $loadresources = 1)
796 {
797 global $langs;
798
799 if (empty($id) && empty($ref) && empty($ref_ext) && empty($email_msgid)) {
800 dol_syslog(get_class($this)."::fetch Bad parameters", LOG_WARNING);
801 return -1;
802 }
803
804 $sql = "SELECT a.id,";
805 $sql .= " a.ref as ref,";
806 $sql .= " a.entity,";
807 $sql .= " a.ref_ext,";
808 $sql .= " a.datep,";
809 $sql .= " a.datep2,";
810 $sql .= " a.durationp,"; // deprecated
811 $sql .= " a.datec,";
812 $sql .= " a.tms as datem,";
813 $sql .= " a.code, a.label, a.note as note_private,";
814 $sql .= " a.fk_soc,";
815 $sql .= " a.fk_project,";
816 $sql .= " a.fk_user_author, a.fk_user_mod,";
817 $sql .= " a.fk_user_action,";
818 $sql .= " a.fk_contact, a.percent as percentage,";
819 $sql .= " a.fk_element as elementid, a.elementtype,";
820 $sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
821 $sql .= " a.email_msgid, a.email_subject, a.email_from, a.email_sender, a.email_to, a.email_tocc, a.email_tobcc, a.errors_to,";
822 $sql .= " c.id as type_id, c.type as type_type, c.code as type_code, c.libelle as type_label, c.color as type_color, c.picto as type_picto,";
823 $sql .= " s.nom as socname,";
824 $sql .= " u.firstname, u.lastname as lastname,";
825 $sql .= " num_vote, event_paid, a.status";
826 $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a ";
827 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action=c.id ";
828 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author";
829 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
830 $sql .= " WHERE ";
831 if ($ref) {
832 $sql .= " a.ref = '".$this->db->escape($ref)."'";
833 } elseif ($ref_ext) {
834 $sql .= " a.ref_ext = '".$this->db->escape($ref_ext)."'";
835 } elseif ($email_msgid) {
836 $sql .= " a.email_msgid = '".$this->db->escape($email_msgid)."'";
837 } else {
838 $sql .= " a.id = ".((int) $id);
839 }
840
841 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
842 $resql = $this->db->query($sql);
843 if ($resql) {
844 $num = $this->db->num_rows($resql);
845 if ($num) {
846 $obj = $this->db->fetch_object($resql);
847
848 $this->id = $obj->id;
849 $this->entity = $obj->entity;
850 $this->ref = $obj->ref;
851 $this->ref_ext = $obj->ref_ext;
852
853 // Properties of parent table llx_c_actioncomm
854 $this->type_id = $obj->type_id;
855 $this->type_code = $obj->type_code;
856 $this->type_color = $obj->type_color;
857 $this->type_picto = $obj->type_picto;
858 $this->type = $obj->type_type;
859 $this->type_label = $obj->type_label;
860
861 $this->code = $obj->code;
862 $this->label = $obj->label;
863 $this->datep = $this->db->jdate($obj->datep);
864 $this->datef = $this->db->jdate($obj->datep2);
865
866 $this->datec = $this->db->jdate($obj->datec);
867 $this->datem = $this->db->jdate($obj->datem);
868
869 $this->note = $obj->note_private; // deprecated
870 $this->note_private = $obj->note_private;
871 $this->percentage = $obj->percentage;
872
873 $this->authorid = $obj->fk_user_author;
874 $this->usermodid = $obj->fk_user_mod;
875
876 if (!is_object($this->author)) {
877 $this->author = new User($this->db); // To avoid warning
878 }
879 $this->author->id = $obj->fk_user_author; // deprecated
880 $this->author->firstname = $obj->firstname; // deprecated
881 $this->author->lastname = $obj->lastname; // deprecated
882 if (!is_object($this->usermod)) {
883 $this->usermod = new User($this->db); // To avoid warning
884 }
885 $this->usermod->id = $obj->fk_user_mod; // deprecated
886
887 $this->userownerid = $obj->fk_user_action;
888 $this->priority = $obj->priority;
889 $this->fulldayevent = $obj->fulldayevent;
890 $this->location = $obj->location;
891 $this->transparency = $obj->transparency;
892
893 $this->socid = $obj->fk_soc; // To have fetch_thirdparty method working
894 $this->contact_id = $obj->fk_contact; // To have fetch_contact method working
895 $this->fk_project = $obj->fk_project; // To have fetch_projet method working
896
897 //$this->societe->id = $obj->fk_soc; // deprecated
898 //$this->contact->id = $obj->fk_contact; // deprecated
899
900 $this->fk_element = $obj->elementid;
901 $this->elementid = $obj->elementid;
902 $this->elementtype = $obj->elementtype;
903
904 $this->num_vote = $obj->num_vote;
905 $this->event_paid = $obj->event_paid;
906 $this->status = $obj->status;
907
908 //email information
909 $this->email_msgid = $obj->email_msgid;
910 $this->email_from = $obj->email_from;
911 $this->email_sender = $obj->email_sender;
912 $this->email_to = $obj->email_to;
913 $this->email_tocc = $obj->email_tocc;
914 $this->email_tobcc = $obj->email_tobcc;
915 $this->email_subject = $obj->email_subject;
916 $this->errors_to = $obj->errors_to;
917
918 $this->fetch_optionals();
919
920 if ($loadresources) {
921 $this->fetchResources();
922 }
923 }
924
925 $this->db->free($resql);
926 } else {
927 $this->error = $this->db->lasterror();
928 return -1;
929 }
930
931 return $num;
932 }
933
939 public function fetchResources()
940 {
941 $this->userassigned = array();
942 $this->socpeopleassigned = array();
943
944 $sql = 'SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency';
945 $sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm_resources';
946 $sql .= ' WHERE fk_actioncomm = '.((int) $this->id);
947 $sql .= " AND element_type IN ('user', 'socpeople')";
948 $resql = $this->db->query($sql);
949 if ($resql) {
950 // If owner is known, we must but id first into list
951 if ($this->userownerid > 0) {
952 $this->userassigned[$this->userownerid] = array('id' => $this->userownerid); // Set first so will be first into list.
953 }
954
955 while ($obj = $this->db->fetch_object($resql)) {
956 if ($obj->fk_element > 0) {
957 switch ($obj->element_type) {
958 case 'user':
959 $this->userassigned[$obj->fk_element] = array('id' => $obj->fk_element, 'mandatory' => $obj->mandatory, 'answer_status' => $obj->answer_status, 'transparency' => $obj->transparency);
960 if (empty($this->userownerid)) {
961 $this->userownerid = $obj->fk_element; // If not defined (should not happened, we fix this)
962 }
963 break;
964 case 'socpeople':
965 $this->socpeopleassigned[$obj->fk_element] = array('id' => $obj->fk_element, 'mandatory' => $obj->mandatory, 'answer_status' => $obj->answer_status, 'transparency' => $obj->transparency);
966 break;
967 }
968 }
969 }
970
971 return 1;
972 } else {
973 dol_print_error($this->db);
974 return -1;
975 }
976 }
977
978 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
985 public function fetch_userassigned($override = true)
986 {
987 // phpcs:enable
988 $sql = "SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency";
989 $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm_resources";
990 $sql .= " WHERE element_type = 'user' AND fk_actioncomm = ".((int) $this->id);
991
992 $resql2 = $this->db->query($sql);
993 if ($resql2) {
994 $this->userassigned = array();
995
996 // If owner is known, we must but id first into list
997 if ($this->userownerid > 0) {
998 // Set first so will be first into list.
999 $this->userassigned[$this->userownerid] = array('id' => $this->userownerid);
1000 }
1001
1002 while ($obj = $this->db->fetch_object($resql2)) {
1003 if ($obj->fk_element > 0) {
1004 $this->userassigned[$obj->fk_element] = array('id' => $obj->fk_element,
1005 'mandatory' => $obj->mandatory,
1006 'answer_status' => $obj->answer_status,
1007 'transparency' => $obj->transparency);
1008 }
1009
1010 if ($override === true) {
1011 // If not defined (should not happened, we fix this)
1012 if (empty($this->userownerid)) {
1013 $this->userownerid = $obj->fk_element;
1014 }
1015 }
1016 }
1017
1018 return 1;
1019 } else {
1020 dol_print_error($this->db);
1021 return -1;
1022 }
1023 }
1024
1032 public function delete($user, $notrigger = 0)
1033 {
1034 $error = 0;
1035
1036 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1037
1038 $this->db->begin();
1039
1040 // remove categorie association
1041 if (!$error) {
1042 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_actioncomm";
1043 $sql .= " WHERE fk_actioncomm=".((int) $this->id);
1044
1045 $res = $this->db->query($sql);
1046 if (!$res) {
1047 $this->error = $this->db->lasterror();
1048 $error++;
1049 }
1050 }
1051
1052 // remove actioncomm_resources
1053 if (!$error) {
1054 $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources";
1055 $sql .= " WHERE fk_actioncomm=".((int) $this->id);
1056
1057 $res = $this->db->query($sql);
1058 if (!$res) {
1059 $this->error = $this->db->lasterror();
1060 $error++;
1061 }
1062 }
1063
1064 if (!$error) {
1065 $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
1066 $sql .= " WHERE fk_actioncomm = ".((int) $this->id);
1067
1068 $res = $this->db->query($sql);
1069 if (!$res) {
1070 $this->error = $this->db->lasterror();
1071 $error++;
1072 }
1073 }
1074
1075 // Removed extrafields
1076 if (!$error) {
1077 $result = $this->deleteExtraFields();
1078 if ($result < 0) {
1079 $error++;
1080 dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
1081 }
1082 }
1083
1084 // remove actioncomm
1085 if (!$error) {
1086 $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm";
1087 $sql .= " WHERE id=".((int) $this->id);
1088
1089 $res = $this->db->query($sql);
1090 if (!$res) {
1091 $this->error = $this->db->lasterror();
1092 $error++;
1093 }
1094 }
1095
1096 if (!$error) {
1097 if (!$notrigger) {
1098 // Call trigger
1099 $result = $this->call_trigger('ACTION_DELETE', $user);
1100 if ($result < 0) {
1101 $error++;
1102 }
1103 // End call triggers
1104 }
1105
1106 if (!$error) {
1107 $this->db->commit();
1108 return 1;
1109 } else {
1110 $this->db->rollback();
1111 return -2;
1112 }
1113 } else {
1114 $this->db->rollback();
1115 $this->error = $this->db->lasterror();
1116 return -1;
1117 }
1118 }
1119
1128 public function update(User $user, $notrigger = 0)
1129 {
1130 $error = 0;
1131
1132 // Clean parameters
1133 $this->label = trim($this->label);
1134 $this->note_private = dol_htmlcleanlastbr(trim(!isset($this->note_private) ? $this->note : $this->note_private));
1135 if (empty($this->percentage)) {
1136 $this->percentage = 0;
1137 }
1138 if (empty($this->priority) || !is_numeric($this->priority)) {
1139 $this->priority = 0;
1140 }
1141 if (empty($this->transparency)) {
1142 $this->transparency = 0;
1143 }
1144 if (empty($this->fulldayevent)) {
1145 $this->fulldayevent = 0;
1146 }
1147 if ($this->percentage > 100) {
1148 $this->percentage = 100;
1149 }
1150 //if ($this->percentage == 100 && ! $this->dateend) $this->dateend = $this->date;
1151 if ($this->datep && $this->datef) {
1152 $this->durationp = ($this->datef - $this->datep); // deprecated
1153 }
1154 //if ($this->date && $this->dateend) $this->durationa=($this->dateend - $this->date);
1155 if ($this->datep && $this->datef && $this->datep > $this->datef) {
1156 $this->datef = $this->datep;
1157 }
1158 //if ($this->date && $this->dateend && $this->date > $this->dateend) $this->dateend=$this->date;
1159 if ($this->fk_project < 0) {
1160 $this->fk_project = 0;
1161 }
1162
1163 $socid = (($this->socid > 0) ? $this->socid : 0);
1164 $contactid = (($this->contact_id > 0) ? $this->contact_id : 0);
1165 $userownerid = ($this->userownerid ? $this->userownerid : 0);
1166
1167 // If a type_id is set, we must also have the type_code set
1168 if ($this->type_id > 0) {
1169 if (empty($this->type_code)) {
1170 $cactioncomm = new CActionComm($this->db);
1171 $result = $cactioncomm->fetch($this->type_id);
1172 if ($result >= 0 && !empty($cactioncomm->code)) {
1173 $this->type_code = $cactioncomm->code;
1174 }
1175 }
1176 }
1177
1178 $code = $this->code;
1179 if (empty($code) || (!empty($this->oldcopy) && $this->oldcopy->type_code != $this->type_code)) { // If code unknown or if we change the type, we reset $code too
1180 $code = $this->type_code;
1181 }
1182
1183 $this->db->begin();
1184
1185 $sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm";
1186 $sql .= " SET percent = '".$this->db->escape($this->percentage)."'";
1187 $sql .= ", fk_action = ".(int) $this->type_id;
1188 $sql .= ", code = " . ($code ? "'".$this->db->escape($code)."'" : "null");
1189 $sql .= ", label = ".($this->label ? "'".$this->db->escape($this->label)."'" : "null");
1190 $sql .= ", datep = ".(strval($this->datep) != '' ? "'".$this->db->idate($this->datep)."'" : 'null');
1191 $sql .= ", datep2 = ".(strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : 'null');
1192 $sql .= ", durationp = ".(isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '' ? "'".$this->db->escape($this->durationp)."'" : "null"); // deprecated
1193 $sql .= ", note = '".$this->db->escape($this->note_private)."'";
1194 $sql .= ", fk_project =".($this->fk_project > 0 ? ((int) $this->fk_project) : "null");
1195 $sql .= ", fk_soc =".($socid > 0 ? ((int) $socid) : "null");
1196 $sql .= ", fk_contact =".($contactid > 0 ? ((int) $contactid) : "null");
1197 $sql .= ", priority = '".$this->db->escape($this->priority)."'";
1198 $sql .= ", fulldayevent = '".$this->db->escape($this->fulldayevent)."'";
1199 $sql .= ", location = ".($this->location ? "'".$this->db->escape($this->location)."'" : "null");
1200 $sql .= ", transparency = '".$this->db->escape($this->transparency)."'";
1201 $sql .= ", fk_user_mod = ".((int) $user->id);
1202 $sql .= ", fk_user_action = ".($userownerid > 0 ? ((int) $userownerid) : "null");
1203 if (!empty($this->fk_element)) {
1204 $sql .= ", fk_element=".($this->fk_element ? ((int) $this->fk_element) : "null");
1205 }
1206 if (!empty($this->elementtype)) {
1207 $sql .= ", elementtype=".($this->elementtype ? "'".$this->db->escape($this->elementtype)."'" : "null");
1208 }
1209 if (!empty($this->num_vote)) {
1210 $sql .= ", num_vote=".($this->num_vote ? (int) $this->num_vote : null);
1211 }
1212 if (!empty($this->event_paid)) {
1213 $sql .= ", event_paid=".($this->event_paid ? (int) $this->event_paid : 0);
1214 }
1215 if (!empty($this->status)) {
1216 $sql .= ", status=".($this->status ? (int) $this->status : 0);
1217 }
1218 $sql .= " WHERE id=".((int) $this->id);
1219
1220 dol_syslog(get_class($this)."::update", LOG_DEBUG);
1221 if ($this->db->query($sql)) {
1222 $action = 'update';
1223
1224 // Actions on extra fields
1225 if (!$error) {
1226 $result = $this->insertExtraFields();
1227 if ($result < 0) {
1228 $error++;
1229 }
1230 }
1231
1232 // Now insert assignedusers
1233 if (!$error) {
1234 $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".((int) $this->id)." AND element_type = 'user'";
1235 $resql = $this->db->query($sql);
1236
1237 $already_inserted = array();
1238 foreach ($this->userassigned as $key => $val) {
1239 if (!is_array($val)) { // For backward compatibility when val=id
1240 $val = array('id' => $val);
1241 }
1242 if (!empty($already_inserted[$val['id']])) {
1243 continue;
1244 }
1245
1246 $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1247 $sql .= " VALUES(".((int) $this->id).", 'user', ".((int) $val['id']).", ".(empty($val['mandatory']) ? '0' : ((int) $val['mandatory'])).", ".(empty($val['transparency']) ? '0' : ((int) $val['transparency'])).", ".(empty($val['answer_status']) ? '0' : ((int) $val['answer_status'])).")";
1248
1249 $resql = $this->db->query($sql);
1250 if (!$resql) {
1251 $error++;
1252 $this->errors[] = $this->db->lasterror();
1253 } else {
1254 $already_inserted[$val['id']] = true;
1255 }
1256 //var_dump($sql);exit;
1257 }
1258 }
1259
1260 if (!$error) {
1261 $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".((int) $this->id)." AND element_type = 'socpeople'";
1262 $resql = $this->db->query($sql);
1263
1264 if (!empty($this->socpeopleassigned)) {
1265 $already_inserted = array();
1266 foreach ($this->socpeopleassigned as $val) {
1267 if (!is_array($val)) { // For backward compatibility when val=id
1268 $val = array('id' => $val);
1269 }
1270 if (!empty($already_inserted[$val['id']])) {
1271 continue;
1272 }
1273
1274 $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1275 $sql .= " VALUES(".((int) $this->id).", 'socpeople', ".((int) $val['id']).", 0, 0, 0)";
1276
1277 $resql = $this->db->query($sql);
1278 if (!$resql) {
1279 $error++;
1280 $this->errors[] = $this->db->lasterror();
1281 } else {
1282 $already_inserted[$val['id']] = true;
1283 }
1284 }
1285 }
1286 }
1287
1288 if (!$error && !$notrigger) {
1289 // Call trigger
1290 $result = $this->call_trigger('ACTION_MODIFY', $user);
1291 if ($result < 0) {
1292 $error++;
1293 }
1294 // End call triggers
1295 }
1296
1297 if (!$error) {
1298 $this->db->commit();
1299 return 1;
1300 } else {
1301 $this->db->rollback();
1302 dol_syslog(get_class($this)."::update ".implode(',', $this->errors), LOG_ERR);
1303 return -2;
1304 }
1305 } else {
1306 $this->db->rollback();
1307 $this->error = $this->db->lasterror();
1308 return -1;
1309 }
1310 }
1311
1325 public function getActions($socid = 0, $fk_element = 0, $elementtype = '', $filter = '', $sortfield = 'a.datep', $sortorder = 'DESC', $limit = 0)
1326 {
1327 global $hookmanager;
1328
1329 $resarray = array();
1330
1331 dol_syslog(get_class()."::getActions", LOG_DEBUG);
1332
1333 // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
1334 if (!is_object($hookmanager)) {
1335 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
1336 $hookmanager = new HookManager($this->db);
1337 }
1338 $hookmanager->initHooks(array('agendadao'));
1339
1340 $sql = "SELECT a.id";
1341 $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1342 // Fields from hook
1343 $parameters = array('sql' => &$sql, 'socid' => $socid, 'fk_element' => $fk_element, 'elementtype' => $elementtype);
1344 $reshook = $hookmanager->executeHooks('getActionsListFrom', $parameters); // Note that $action and $object may have been modified by hook
1345 if (!empty($hookmanager->resPrint)) {
1346 $sql .= $hookmanager->resPrint;
1347 }
1348 $sql .= " WHERE a.entity IN (".getEntity('agenda').")";
1349 if (!empty($socid)) {
1350 $sql .= " AND a.fk_soc = ".((int) $socid);
1351 }
1352 if (!empty($elementtype)) {
1353 if ($elementtype == 'project') {
1354 $sql .= ' AND a.fk_project = '.((int) $fk_element);
1355 } elseif ($elementtype == 'contact') {
1356 $sql .= ' AND EXISTS';
1357 $sql .= " (SELECT r.rowid FROM ".MAIN_DB_PREFIX."actioncomm_resources as r WHERE";
1358 $sql .= " r.element_type = 'socpeople' AND r.fk_element = ".((int) $fk_element).' AND r.fk_actioncomm = a.id)';
1359 } elseif ($elementtype == 'user') {
1360 $sql .= " AND (a.fk_user_action = ".((int) $fk_element)." OR EXISTS";
1361 $sql .= " (SELECT r.rowid FROM ".MAIN_DB_PREFIX."actioncomm_resources as r WHERE";
1362 $sql .= " r.element_type = 'user' AND r.fk_element = ".((int) $fk_element).' AND r.fk_actioncomm = a.id)';
1363 $sql .= ")";
1364 } else {
1365 $sql .= " AND a.fk_element = ".((int) $fk_element)." AND a.elementtype = '".$this->db->escape($elementtype)."'";
1366 }
1367 }
1368 if (!empty($filter)) {
1369 $sql .= $filter;
1370 }
1371 // Fields where hook
1372 $parameters = array('sql' => &$sql, 'socid' => $socid, 'fk_element' => $fk_element, 'elementtype' => $elementtype);
1373 $reshook = $hookmanager->executeHooks('getActionsListWhere', $parameters); // Note that $action and $object may have been modified by hook
1374 if (!empty($hookmanager->resPrint)) {
1375 $sql .= $hookmanager->resPrint;
1376 }
1377 if ($sortorder && $sortfield) {
1378 $sql .= $this->db->order($sortfield, $sortorder);
1379 }
1380 $sql .= $this->db->plimit($limit, 0);
1381
1382 $resql = $this->db->query($sql);
1383 if ($resql) {
1384 $num = $this->db->num_rows($resql);
1385
1386 if ($num) {
1387 for ($i = 0; $i < $num; $i++) {
1388 $obj = $this->db->fetch_object($resql);
1389 $actioncommstatic = new ActionComm($this->db);
1390 $actioncommstatic->fetch($obj->id);
1391 $resarray[$i] = $actioncommstatic;
1392 }
1393 }
1394 $this->db->free($resql);
1395 return $resarray;
1396 } else {
1397 return $this->db->lasterror();
1398 }
1399 }
1400
1401 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1409 public function load_board($user, $load_state_board = 0)
1410 {
1411 // phpcs:enable
1412 global $conf, $langs;
1413
1414 if (empty($load_state_board)) {
1415 $sql = "SELECT a.id, a.datep as dp";
1416 } else {
1417 $this->nb = array();
1418 $sql = "SELECT count(a.id) as nb";
1419 }
1420 $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1421 if (!$user->hasRight('agenda', 'allactions', 'read')) {
1422 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."actioncomm_resources AS ar ON a.id = ar.fk_actioncomm AND ar.element_type ='user' AND ar.fk_element = ".((int) $user->id);
1423 }
1424 $sql .= " WHERE 1 = 1";
1425 if (empty($load_state_board)) {
1426 $sql .= " AND a.percent >= 0 AND a.percent < 100";
1427 }
1428 $sql .= " AND a.entity IN (".getEntity('agenda').")";
1429 if (!$user->hasRight('agenda', 'allactions', 'read')) {
1430 $sql .= " AND (a.fk_user_author = ".((int) $user->id)." OR a.fk_user_action = ".((int) $user->id);
1431 $sql .= " OR ar.fk_element = ".((int) $user->id);
1432 $sql .= ")";
1433 }
1434 // If the internal user must only see his customers, force searching by him
1435 $search_sale = 0;
1436 if (!$user->hasRight('societe', 'client', 'voir')) {
1437 $search_sale = $user->id;
1438 }
1439 // Search on sale representative
1440 if ($search_sale && $search_sale != '-1') {
1441 if ($search_sale == -2) {
1442 $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = a.fk_soc)";
1443 } elseif ($search_sale > 0) {
1444 $sql .= " AND EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = a.fk_soc AND sc.fk_user = ".((int) $search_sale).")";
1445 }
1446 }
1447
1448 $resql = $this->db->query($sql);
1449 if ($resql) {
1450 $response = null; // Ensure the variable is defined
1451 if (empty($load_state_board)) {
1452 $agenda_static = new ActionComm($this->db);
1453 $response = new WorkboardResponse();
1454 $response->warning_delay = $conf->agenda->warning_delay / 60 / 60 / 24;
1455 $response->label = $langs->trans("ActionsToDo");
1456 $response->labelShort = $langs->trans("ActionsToDoShort");
1457 $response->url = DOL_URL_ROOT.'/comm/action/list.php?mode=show_list&actioncode=0&status=todo&mainmenu=agenda';
1458 if ($user->hasRight("agenda", "allactions", "read")) {
1459 $response->url .= '&filtert=-1';
1460 }
1461 $response->img = img_object('', "action", 'class="inline-block valigntextmiddle"');
1462 }
1463 // This assignment in condition is not a bug. It allows walking the results.
1464 while ($obj = $this->db->fetch_object($resql)) {
1465 if (empty($load_state_board)) {
1466 '@phan-var-force WorkboardResponse $response
1467 @phan-var-force ActionComm $agenda_static';
1468 $response->nbtodo++;
1469 $agenda_static->datep = $this->db->jdate($obj->dp);
1470 if ($agenda_static->hasDelay()) {
1471 $response->nbtodolate++;
1472 }
1473 } else {
1474 $this->nb["actionscomm"] = $obj->nb;
1475 }
1476 }
1477
1478 $this->db->free($resql);
1479 if (empty($load_state_board) && $response instanceof WorkboardResponse) {
1480 return $response;
1481 } else {
1482 return 1;
1483 }
1484 } else {
1485 dol_print_error($this->db);
1486 $this->error = $this->db->error();
1487 return -1;
1488 }
1489 }
1490
1491
1498 public function info($id)
1499 {
1500 $sql = 'SELECT ';
1501 $sql .= ' a.id,';
1502 $sql .= ' datec,';
1503 $sql .= ' tms as datem,';
1504 $sql .= ' fk_user_author,';
1505 $sql .= ' fk_user_mod';
1506 $sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a';
1507 $sql .= ' WHERE a.id = '.((int) $id);
1508
1509 dol_syslog(get_class($this)."::info", LOG_DEBUG);
1510 $result = $this->db->query($sql);
1511 if ($result) {
1512 if ($this->db->num_rows($result)) {
1513 $obj = $this->db->fetch_object($result);
1514
1515 $this->id = $obj->id;
1516
1517 $this->user_creation_id = $obj->fk_user_author;
1518 $this->user_modification_id = $obj->fk_user_mod;
1519 $this->date_creation = $this->db->jdate($obj->datec);
1520 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1521 }
1522 $this->db->free($result);
1523 } else {
1524 dol_print_error($this->db);
1525 }
1526 }
1527
1528
1536 public function getLibStatut($mode, $hidenastatus = 0)
1537 {
1538 return $this->LibStatut($this->percentage, $mode, $hidenastatus, $this->datep);
1539 }
1540
1541 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1551 public function LibStatut($percent, $mode, $hidenastatus = 0, $datestart = '')
1552 {
1553 // phpcs:enable
1554 global $langs;
1555
1556 $labelStatus = $langs->transnoentitiesnoconv('StatusNotApplicable');
1557 if ($percent == -1 && !$hidenastatus) {
1558 $labelStatus = $langs->transnoentitiesnoconv('StatusNotApplicable');
1559 } elseif ($percent == 0) {
1560 $labelStatus = $langs->transnoentitiesnoconv('StatusActionToDo').' (0%)';
1561 } elseif ($percent > 0 && $percent < 100) {
1562 $labelStatus = $langs->transnoentitiesnoconv('StatusActionInProcess').' ('.$percent.'%)';
1563 } elseif ($percent >= 100) {
1564 $labelStatus = $langs->transnoentitiesnoconv('StatusActionDone').' (100%)';
1565 }
1566
1567 $labelStatusShort = $langs->transnoentitiesnoconv('StatusNotApplicable');
1568 if ($percent == -1 && !$hidenastatus) {
1569 $labelStatusShort = $langs->trans('NA');
1570 } elseif ($percent == 0) {
1571 $labelStatusShort = '0%';
1572 } elseif ($percent > 0 && $percent < 100) {
1573 $labelStatusShort = $percent.'%';
1574 } elseif ($percent >= 100) {
1575 $labelStatusShort = '100%';
1576 }
1577
1578 $statusType = 'status9';
1579 if ($percent == -1 && !$hidenastatus) {
1580 $statusType = 'status9';
1581 }
1582 if ($percent == 0) {
1583 $statusType = 'status1';
1584 }
1585 if ($percent > 0 && $percent < 100) {
1586 $statusType = 'status3';
1587 }
1588 if ($percent >= 100) {
1589 $statusType = 'status6';
1590 }
1591
1592 return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1593 }
1594
1601 public function getTooltipContentArray($params)
1602 {
1603 global $langs, $form;
1604
1605 $langs->load('agenda');
1606
1607 $datas = array();
1608 $nofetch = !empty($params['nofetch']);
1609
1610 // Set label of type
1611 $labeltype = '';
1612 if ($this->type_code) {
1613 $langs->load("commercial");
1614 $labeltype = ($langs->transnoentities("Action".$this->type_code) != "Action".$this->type_code) ? $langs->transnoentities("Action".$this->type_code) : $this->type_label;
1615 }
1616 if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1617 if ($this->type_code != 'AC_OTH_AUTO') {
1618 $labeltype = $langs->trans('ActionAC_MANUAL');
1619 }
1620 }
1621 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans('Action').'</u>';
1622 if (!empty($this->ref)) {
1623 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.dol_escape_htmltag($this->ref);
1624 }
1625 if (!empty($this->label)) {
1626 $datas['title'] = '<br><b>'.$langs->trans('Title').':</b> '.dol_escape_htmltag($this->label);
1627 }
1628 if (!empty($labeltype)) {
1629 $datas['labeltype'] = '<br><b>'.$langs->trans('Type').':</b> '.dol_escape_htmltag($labeltype);
1630 }
1631 if (!empty($this->location)) {
1632 $datas['location'] = '<br><b>'.$langs->trans('Location').':</b> '.dol_escape_htmltag($this->location);
1633 }
1634 if (isset($this->transparency)) {
1635 $datas['transparency'] = '<br><b>'.$langs->trans('Busy').':</b> '.yn($this->transparency);
1636 }
1637 if (!empty($this->email_msgid)) {
1638 $langs->load("mails");
1639 $datas['space'] = '<br>';
1640 // $datas['email'] = '<br><b>'.img_picto('', 'email').' '.$langs->trans("Email").'</b>';
1641 $datas['mailtopic'] = '<br><b>'.$langs->trans('MailTopic').':</b> '.dol_escape_htmltag($this->email_subject);
1642 $datas['mailfrom'] = '<br><b>'.$langs->trans('MailFrom').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_from);
1643 $datas['mailto'] = '<br><b>'.$langs->trans('MailTo').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_to);
1644 if (!empty($this->email_tocc)) {
1645 $datas['mailcc'] = '<br><b>'.$langs->trans('MailCC').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_tocc);
1646 }
1647 /* Disabled because bcc must remain by definition not visible
1648 if (!empty($this->email_tobcc)) {
1649 $datas['mailccc'] = '<br><b>'.$langs->trans('MailCCC').':</b> '.$this->email_tobcc;
1650 } */
1651 }
1652 if (!empty($this->note_private)) {
1653 $datas['description'] = '<br><hr>';
1654 // Try to limit length of content
1655 $texttoshow = dolGetFirstLineOfText($this->note_private, 10);
1656 // Restrict height of content into the tooltip
1657 $datas['note'] = '<div class="tenlinesmax">';
1658 $datas['note'] .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), '<br>', $texttoshow));
1659 $datas['note'] .= '</div>';
1660 }
1661 // show categories for this record only in ajax to not overload lists
1662 if (isModEnabled('category') && !$nofetch) {
1663 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1664 if (empty($form)) {
1665 include_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
1666 $form = new Form($this->db);
1667 }
1668 $tmpcategstring = $form->showCategories($this->id, Categorie::TYPE_ACTIONCOMM, 1);
1669 if ($tmpcategstring) {
1670 $datas['categories'] = '<br>'.$tmpcategstring;
1671 }
1672 }
1673
1674 return $datas;
1675 }
1676
1690 public function getNomUrl($withpicto = 0, $maxlength = 0, $classname = '', $option = '', $overwritepicto = 0, $notooltip = 0, $save_lastsearch_value = -1)
1691 {
1692 global $conf, $langs, $user, $hookmanager, $action;
1693
1694 if (!empty($conf->dol_no_mouse_hover)) {
1695 $notooltip = 1; // Force disable tooltips
1696 }
1697
1698 $canread = 0;
1699 if ($user->hasRight('agenda', 'myactions', 'read') && ($this->authorid == $user->id || $this->userownerid == $user->id)) {
1700 $canread = 1; // Can read my event
1701 }
1702 if ($user->hasRight('agenda', 'myactions', 'read') && array_key_exists($user->id, $this->userassigned)) {
1703 $canread = 1; // Can read my event i am assigned
1704 }
1705 if ($user->hasRight('agenda', 'allactions', 'read')) {
1706 $canread = 1; // Can read all event of other
1707 }
1708 if (!$canread) {
1709 $option = 'nolink';
1710 }
1711
1712 $label = $this->label;
1713
1714 $result = '';
1715
1716 // Set label of type
1717 $labeltype = $this->getTypeLabel(1);
1718
1719 $tooltip = img_picto('', $this->picto).' <u>'.$langs->trans('Action').'</u>';
1720
1721 $tooltip .= ' &nbsp; - &nbsp; '.$this->getTypePicto('pictofixedwidth paddingright valignmiddle').$labeltype;
1722 if (!empty($this->ref)) {
1723 $tooltip .= '<br><b>'.$langs->trans('Ref').':</b> '.dol_escape_htmltag($this->ref);
1724 }
1725 if (!empty($label)) {
1726 $tooltip .= '<br><b>'.$langs->trans('Title').':</b> '.dol_escape_htmltag($label);
1727 }
1728 if (!empty($this->location)) {
1729 $tooltip .= '<br><b>'.$langs->trans('Location').':</b> '.dol_escape_htmltag($this->location);
1730 }
1731
1732 $tooltip .= '<br><b>'.$langs->trans('Date').':</b> '.dol_print_date($this->datep, 'dayhourreduceformat', 'tzuserrel');
1733 if ($this->datef) {
1734 $tmpa = dol_getdate($this->datep);
1735 $tmpb = dol_getdate($this->datef);
1736 if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) {
1737 if ($tmpa['hours'] != $tmpb['hours'] || $tmpa['minutes'] != $tmpb['minutes']) {
1738 $tooltip .= '-'.dol_print_date($this->datef, 'hour', 'tzuserrel');
1739 }
1740 } else {
1741 $tooltip .= '-'.dol_print_date($this->datef, 'dayhourreduceformat', 'tzuserrel');
1742 }
1743 }
1744
1745 if ($this->datef && $this->datep != $this->datef && isset($this->transparency)) {
1746 $tooltip .= '<br><b>'.$langs->trans('Busy').':</b> '.yn($this->transparency);
1747 }
1748 if (!empty($this->email_msgid)) {
1749 $langs->load("mails");
1750 $tooltip .= '<br>';
1751 //$tooltip .= '<br><b>'.img_picto('', 'email').' '.$langs->trans("Email").'</b>';
1752 $tooltip .= '<br><b>'.$langs->trans('MailTopic').':</b> '.dol_escape_htmltag($this->email_subject);
1753 $tooltip .= '<br><b>'.$langs->trans('MailFrom').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), !empty($this->email_from) ? $this->email_from : '');
1754 $tooltip .= '<br><b>'.$langs->trans('MailTo').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), !empty($this->email_to) ? $this->email_to : '');
1755 if (!empty($this->email_tocc)) {
1756 $tooltip .= '<br><b>'.$langs->trans('MailCC').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_tocc);
1757 }
1758 /* Disabled because bcc must remain by definition not visible
1759 if (!empty($this->email_tobcc)) {
1760 $tooltip .= '<br><b>'.$langs->trans('MailCCC').':</b> '.$this->email_tobcc;
1761 } */
1762 }
1763 if (!empty($this->note_private)) {
1764 $tooltip .= '<br><hr>';
1765 $texttoshow = dolGetFirstLineOfText($this->note_private, 8); // Try to limit length of content
1766 $tooltip .= '<div class="tenlinesmax">'; // Restrict height of content into the tooltip
1767 $tooltip .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), '<br>', $texttoshow));
1768 $tooltip .= '</div>';
1769 }
1770 $linkclose = '';
1771 $classfortooltip = 'classfortooltip';
1772 $dataparams = '';
1773 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1774 $params = [
1775 'id' => $this->id,
1776 'objecttype' => $this->element,
1777 'option' => $option,
1778 'nofetch' => 1,
1779 ];
1780 $classfortooltip = 'classforajaxtooltip';
1781 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1782 $tooltip = '';
1783 }
1784 if (empty($notooltip)) {
1785 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1786 $label = $langs->trans("ShowAction");
1787 $linkclose .= ' alt="'.dol_escape_htmltag($tooltip, 1).'"';
1788 }
1789 $linkclose .= ($tooltip ? ' title="'.dol_escape_htmltag($tooltip, 1).'"' : ' title="tocomplete"');
1790 $linkclose .= $dataparams.' class="'.$classname.' '.$classfortooltip.'"';
1791 } else {
1792 $linkclose .= ' class="'.$classname.'"';
1793 }
1794
1795 $url = '';
1796 if ($option == 'birthday') {
1797 $url = DOL_URL_ROOT.'/contact/perso.php?id='.$this->id;
1798 } elseif ($option == 'holiday') {
1799 $url = DOL_URL_ROOT.'/holiday/card.php?id='.$this->id;
1800 } else {
1801 $url = DOL_URL_ROOT.'/comm/action/card.php?id='.$this->id;
1802 }
1803
1804 if ($option !== 'nolink') {
1805 // Add param to save lastsearch_values or not
1806 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1807 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1808 $add_save_lastsearch_values = 1;
1809 }
1810 if ($add_save_lastsearch_values) {
1811 $url .= '&save_lastsearch_values=1';
1812 }
1813 }
1814
1815 $linkstart = '<a href="'.$url.'"';
1816 $linkstart .= $linkclose.'>';
1817 $linkend = '</a>';
1818
1819 if ($option == 'nolink') {
1820 $linkstart = '';
1821 $linkend = '';
1822 }
1823
1824 if ($withpicto == 2) {
1825 if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1826 $label = $labeltype;
1827 }
1828 $labelshort = '';
1829 } else {
1830 if (getDolGlobalString('AGENDA_USE_EVENT_TYPE') && empty($label)) {
1831 $label = $labeltype;
1832 }
1833 if ($maxlength < 0) {
1834 $labelshort = $this->ref;
1835 } else {
1836 $labelshort = dol_trunc($label, $maxlength);
1837 }
1838 }
1839
1840 if ($withpicto) {
1841 if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) { // Add code into ()
1842 if ($labeltype) {
1843 $label .= (preg_match('/'.preg_quote($labeltype, '/').'/', $label) ? '' : ' ('.$langs->transnoentities("Action".$this->type_code).')');
1844 }
1845 }
1846 }
1847
1848 $result .= $linkstart;
1849 if ($withpicto) {
1850 $result .= img_object(($notooltip ? '' : $langs->trans("ShowAction").': '.$label), ($overwritepicto ? $overwritepicto : 'action'), (($this->type_color && $overwritepicto) ? 'style="color: #'.$this->type_color.' !important;" ' : '').($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : ' class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
1851 }
1852 $result .= dol_escape_htmltag($labelshort);
1853 $result .= $linkend;
1854
1855 global $action;
1856 $hookmanager->initHooks(array('actiondao'));
1857 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1858 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1859 if ($reshook > 0) {
1860 $result = $hookmanager->resPrint;
1861 } else {
1862 $result .= $hookmanager->resPrint;
1863 }
1864
1865 return $result;
1866 }
1867
1875 public function getTypePicto($morecss = 'pictofixedwidth paddingright valignmiddle', $titlealt = '')
1876 {
1877 $imgpicto = '';
1878 if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1879 $color = '';
1880 if ($this->type_color) {
1881 $color = 'style="color: #'.$this->type_color.' !important;"';
1882 }
1883 if ($this->type_picto) {
1884 $imgpicto = img_picto($titlealt, $this->type_picto, '', 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1885 } else {
1886 if ($this->type_code == 'AC_RDV') {
1887 $imgpicto = img_picto($titlealt, 'meeting', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1888 } elseif ($this->type_code == 'AC_TEL') {
1889 $imgpicto = img_picto($titlealt, 'object_phoning', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1890 } elseif ($this->type_code == 'AC_FAX') {
1891 $imgpicto = img_picto($titlealt, 'object_phoning_fax', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1892 } elseif ($this->type_code == 'AC_EMAIL' || $this->type_code == 'AC_EMAIL_IN' || (!empty($this->code) && preg_match('/_SENTBYMAIL/', $this->code))) {
1893 $imgpicto = img_picto($titlealt, 'object_email', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1894 } elseif ($this->type_code == 'AC_INT') {
1895 $imgpicto = img_picto($titlealt, 'object_intervention', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1896 } elseif (!empty($this->code) && preg_match('/^TICKET_MSG/', $this->code)) {
1897 $imgpicto = img_picto($titlealt, 'object_conversation', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1898 } elseif ($this->type != 'systemauto') {
1899 $imgpicto = img_picto($titlealt, 'user-cog', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1900 } else {
1901 $imgpicto = img_picto($titlealt, 'cog', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1902 }
1903 }
1904 } else {
1905 // 2 picto: 1 for auto, 1 for manual
1906 if ($this->type != 'systemauto') {
1907 $imgpicto = img_picto($titlealt, 'user-cog', '', 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1908 } else {
1909 $imgpicto = img_picto($titlealt, 'cog', '', 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1910 }
1911 }
1912
1913 return $imgpicto;
1914 }
1915
1916
1923 public function getTypeLabel($mode = 0)
1924 {
1925 global $conf, $langs;
1926
1927 // If cache for array of types unknown, we load it
1928 if (!empty($conf->cache['actioncommgetypelabel'])) {
1929 $arraylist = $conf->cache['actioncommgetypelabel'];
1930 } else {
1931 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php';
1932 $caction = new CActionComm($this->db);
1933 $arraylist = $caction->liste_array(1, 'code', '', (getDolGlobalString('AGENDA_USE_EVENT_TYPE') ? 0 : 1), '', 1);
1934 $conf->cache['actioncommgetypelabel'] = $arraylist;
1935 }
1936
1937 $labeltype = $this->type_code;
1938 if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE') && empty($arraylist[$labeltype])) {
1939 $labeltype = 'AC_OTH';
1940 }
1941 if (preg_match('/^TICKET_MSG/', $this->code)) {
1942 $labeltype = $langs->trans("Message");
1943 } else {
1944 if (!empty($arraylist[$labeltype])) {
1945 $labeltype = $arraylist[$labeltype];
1946 }
1947 if ($this->type_code == 'AC_OTH_AUTO' && ($this->type_code != $this->code) && $labeltype && !empty($arraylist[$this->code])) {
1948 $labeltype .= ' - '.$arraylist[$this->code]; // Use code in priority over type_code
1949 }
1950 }
1951
1952 if ($this->type == 'systemauto' && $mode == 1) {
1953 $labeltype .= ' ('.$langs->trans("auto").')';
1954 }
1955
1956
1957 return $labeltype;
1958 }
1959
1970 public function setCategories($categories)
1971 {
1972 // Handle single category
1973 if (!is_array($categories)) {
1974 $categories = array($categories);
1975 }
1976
1977 // Get current categories
1978 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1979 $c = new Categorie($this->db);
1980 $existing = $c->containing($this->id, Categorie::TYPE_ACTIONCOMM, 'id');
1981
1982 // Diff
1983 if (is_array($existing)) {
1984 $to_del = array_diff($existing, $categories);
1985 $to_add = array_diff($categories, $existing);
1986 } else {
1987 $to_del = array(); // Nothing to delete
1988 $to_add = $categories;
1989 }
1990
1991 // Process
1992 foreach ($to_del as $del) {
1993 if ($c->fetch($del) > 0) {
1994 $c->del_type($this, Categorie::TYPE_ACTIONCOMM);
1995 }
1996 }
1997 foreach ($to_add as $add) {
1998 if ($c->fetch($add) > 0) {
1999 $c->add_type($this, Categorie::TYPE_ACTIONCOMM);
2000 }
2001 }
2002 return 1;
2003 }
2004
2005 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2017 public function build_exportfile($format, $type, $cachedelay, $filename, $filters, $exportholiday = 0)
2018 {
2019 global $hookmanager;
2020
2021 // phpcs:enable
2022 global $conf, $langs, $dolibarr_main_url_root, $mysoc;
2023
2024 require_once DOL_DOCUMENT_ROOT."/core/lib/xcal.lib.php";
2025 require_once DOL_DOCUMENT_ROOT."/core/lib/date.lib.php";
2026 require_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php";
2027
2028 dol_syslog(get_class($this)."::build_exportfile Build export file format=".$format.", type=".$type.", cachedelay=".$cachedelay.", filename=".$filename.", filters size=".count($filters), LOG_DEBUG);
2029
2030 // Check parameters
2031 if (empty($format)) {
2032 return -1;
2033 }
2034
2035 // Clean parameters
2036 if (!$filename) {
2037 $extension = 'vcs';
2038 if ($format == 'ical') {
2039 $extension = 'ics';
2040 }
2041 $filename = $format.'.'.$extension;
2042 }
2043
2044 // Create dir and define output file (definitive and temporary)
2045 $result = dol_mkdir($conf->agenda->dir_temp);
2046 $outputfile = $conf->agenda->dir_temp.'/'.$filename;
2047
2048 $result = 0;
2049
2050 $buildfile = true;
2051 $login = '';
2052 $logina = '';
2053 $logint = '';
2054 $eventorganization = '';
2055
2056 $now = dol_now();
2057
2058 if ($cachedelay) {
2059 $nowgmt = dol_now();
2060 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2061 if (dol_filemtime($outputfile) > ($nowgmt - $cachedelay)) {
2062 dol_syslog(get_class($this)."::build_exportfile file ".$outputfile." is not older than now - cachedelay (".$nowgmt." - ".$cachedelay."). Build is canceled");
2063 $buildfile = false;
2064 }
2065 }
2066
2067 if ($buildfile) {
2068 // Build event array
2069 $eventarray = array();
2070
2071 if (!empty($filters['module']) && $filters['module'] == 'project@eventorganization') {
2072 $sql = "SELECT p.rowid as id,";
2073 $sql .= " p.date_start_event as datep,"; // Start
2074 $sql .= " p.date_end_event as datep2,"; // End
2075 $sql .= " p.datec, p.tms as datem,";
2076 $sql .= " p.title as label, '' as code, p.note_public, p.note_private, 0 as type_id,";
2077 $sql .= " p.fk_soc,";
2078 $sql .= " p.fk_user_creat as fk_user_author, p.fk_user_modif as fk_user_mod,";
2079 $sql .= " 0 as fk_user_action,";
2080 $sql .= " 0 as fk_contact, 100 as percentage,";
2081 $sql .= " 0 as fk_element, '' as elementtype,";
2082 $sql .= " 1 as priority, 0 as fulldayevent, p.location, 0 as transparency,";
2083 $sql .= " u.firstname, u.lastname, '".$this->db->escape(getDolGlobalString("MAIN_INFO_SOCIETE_MAIL"))."' as email,";
2084 $sql .= " s.nom as socname,";
2085 $sql .= " 0 as type_id, '' as type_code, '' as type_label";
2086 $sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
2087 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = p.fk_user_creat"; // Link to get author of event for export
2088 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = p.fk_soc";
2089
2090 $parameters = array('filters' => $filters);
2091 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
2092 $sql .= $hookmanager->resPrint;
2093
2094 $sql .= " WHERE p.entity IN (".getEntity('project').")";
2095
2096 foreach ($filters as $key => $value) {
2097 if ($key == 'notolderthan' && $value != '') {
2098 $sql .= " AND p.date_start_event >= '".$this->db->idate($now - ($value * 24 * 60 * 60))."'";
2099 }
2100 if ($key == 'year') {
2101 $sql .= " AND p.date_start_event BETWEEN '".$this->db->idate(dol_get_first_day($value, 1))."' AND '".$this->db->idate(dol_get_last_day($value, 12))."'";
2102 }
2103 if ($key == 'id') {
2104 $sql .= " AND p.id = ".(is_numeric($value) ? $value : 0);
2105 }
2106 if ($key == 'idfrom') {
2107 $sql .= " AND p.id >= ".(is_numeric($value) ? $value : 0);
2108 }
2109 if ($key == 'idto') {
2110 $sql .= " AND p.id <= ".(is_numeric($value) ? $value : 0);
2111 }
2112 if ($key == 'project') {
2113 $sql .= " AND p.rowid = ".(is_numeric($value) ? $value : 0);
2114 }
2115 if ($key == 'status') {
2116 $sql .= " AND p.fk_statut = ".((int) $value);
2117 }
2118 // TODO Add filters on event code of meetings/talks only
2119 }
2120
2121 $sql .= " ORDER by date_start_event";
2122
2123 $eventorganization = 'project';
2124 } else {
2125 $sql = "SELECT a.id,";
2126 $sql .= " a.datep,"; // Start
2127 $sql .= " a.datep2,"; // End
2128 $sql .= " a.datec, a.tms as datem,";
2129 $sql .= " a.label, a.code, '' as note_public, a.note as note_private, a.fk_action as type_id,";
2130 $sql .= " a.fk_soc,";
2131 $sql .= " a.fk_user_author, a.fk_user_mod,";
2132 $sql .= " a.fk_user_action,";
2133 $sql .= " a.fk_contact, a.percent as percentage,";
2134 $sql .= " a.fk_element, a.elementtype,";
2135 $sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
2136 $sql .= " u.firstname, u.lastname, u.email,";
2137 $sql .= " s.nom as socname,";
2138 $sql .= " c.id as type_id, c.code as type_code, c.libelle as type_label,";
2139 $sql .= " num_vote, event_paid, a.status";
2140 $sql .= " FROM (".MAIN_DB_PREFIX."c_actioncomm as c, ".MAIN_DB_PREFIX."actioncomm as a)";
2141 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author"; // Link to get author of event for export
2142 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
2143
2144 $parameters = array('filters' => $filters);
2145 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
2146 $sql .= $hookmanager->resPrint;
2147
2148 // We must filter on assignment table
2149 if (!empty($filters['logint']) && $filters['logint']) {
2150 $sql .= ", ".MAIN_DB_PREFIX."actioncomm_resources as ar";
2151 }
2152 $sql .= " WHERE a.fk_action = c.id";
2153 $sql .= " AND a.entity IN (".getEntity('agenda').")";
2154
2155 foreach ($filters as $key => $value) {
2156 if ($key == 'notolderthan' && $value != '') {
2157 $sql .= " AND a.datep >= '".$this->db->idate($now - ($value * 24 * 60 * 60))."'";
2158 }
2159 if ($key == 'year') {
2160 $sql .= " AND a.datep BETWEEN '".$this->db->idate(dol_get_first_day($value, 1))."' AND '".$this->db->idate(dol_get_last_day($value, 12))."'";
2161 }
2162 if ($key == 'id') {
2163 $sql .= " AND a.id = ".(is_numeric($value) ? $value : 0);
2164 }
2165 if ($key == 'idfrom') {
2166 $sql .= " AND a.id >= ".(is_numeric($value) ? $value : 0);
2167 }
2168 if ($key == 'idto') {
2169 $sql .= " AND a.id <= ".(is_numeric($value) ? $value : 0);
2170 }
2171 if ($key == 'project') {
2172 $sql .= " AND a.fk_project = ".(is_numeric($value) ? $value : 0);
2173 }
2174 if ($key == 'notactiontype') { // deprecated
2175 $sql .= " AND c.type <> '".$this->db->escape($value)."'";
2176 }
2177 if ($key == 'actiontype') { // 'system', 'systemauto', 'module', ...
2178 $newvalue = $value;
2179 $usenotin = 0;
2180 if (preg_match('/^!/', $newvalue)) {
2181 $newvalue = preg_replace('/^!/', '', $value);
2182 $usenotin = 1;
2183 }
2184 $arraynewvalue = explode(',', $newvalue);
2185 $newvalue = "";
2186 foreach ($arraynewvalue as $tmpval) {
2187 $newvalue .= ($newvalue ? "," : "")."'".$tmpval."'";
2188 }
2189 if ($usenotin) {
2190 $sql .= " AND c.type NOT IN (".$this->db->sanitize($newvalue, 1).")";
2191 } else {
2192 $sql .= " AND c.type IN (".$this->db->sanitize($newvalue, 1).")";
2193 }
2194 }
2195 if ($key == 'actioncode') { // 'AC_COMPANY_CREATE', 'AC_COMPANY_MODIFY', ...
2196 $newvalue = $value;
2197 $usenotin = 0;
2198 if (preg_match('/^!/', $newvalue)) {
2199 $newvalue = preg_replace('/^!/', '', $value);
2200 $usenotin = 1;
2201 }
2202 $arraynewvalue = explode(',', $newvalue);
2203 $newvalue = "";
2204 foreach ($arraynewvalue as $tmpval) {
2205 $newvalue .= ($newvalue ? "," : "")."'".$tmpval."'";
2206 }
2207 if ($usenotin) {
2208 $sql .= " AND a.code NOT IN (".$this->db->sanitize($newvalue, 1).")";
2209 } else {
2210 $sql .= " AND a.code IN (".$this->db->sanitize($newvalue, 1).")";
2211 }
2212 }
2213
2214 // We must filter on assignment table
2215 if ($key == 'logint') {
2216 $sql .= " AND ar.fk_actioncomm = a.id AND ar.element_type='user'";
2217 }
2218 if ($key == 'logina') {
2219 $logina = $value;
2220 $condition = '=';
2221 if (preg_match('/^!/', $logina)) {
2222 $logina = preg_replace('/^!/', '', $logina);
2223 $condition = '<>';
2224 }
2225 $userforfilter = new User($this->db);
2226 $result = $userforfilter->fetch(0, $logina);
2227 if ($result > 0) {
2228 $sql .= " AND a.fk_user_author ".$condition." ".$userforfilter->id;
2229 } elseif ($result < 0 || $condition == '=') {
2230 $sql .= " AND a.fk_user_author = 0";
2231 }
2232 }
2233 if ($key == 'logint') {
2234 $logint = $value;
2235 $condition = '=';
2236 if (preg_match('/^!/', $logint)) {
2237 $logint = preg_replace('/^!/', '', $logint);
2238 $condition = '<>';
2239 }
2240 $userforfilter = new User($this->db);
2241 $result = $userforfilter->fetch(0, $logint);
2242 if ($result > 0) {
2243 $sql .= " AND ar.fk_element = ".((int) $userforfilter->id);
2244 } elseif ($result < 0 || $condition == '=') {
2245 $sql .= " AND ar.fk_element = 0";
2246 }
2247 }
2248 if ($key == 'module') {
2249 if ($value == 'conforbooth@eventorganization') {
2250 $value = '@eventorganization';
2251 }
2252 $sql .= " AND c.module LIKE '%".$this->db->escape($value)."'";
2253 }
2254 if ($key == 'status') {
2255 $sql .= " AND a.status = ".((int) $value);
2256 }
2257 }
2258
2259 $sql .= " AND a.datep IS NOT NULL"; // To exclude corrupted events and avoid errors in lightning/sunbird import
2260
2261 $parameters = array('filters' => $filters);
2262 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
2263 $sql .= $hookmanager->resPrint;
2264
2265 $sql .= " ORDER by datep";
2266 }
2267
2268 if (!empty($filters['limit'])) {
2269 $sql .= $this->db->plimit((int) $filters['limit']);
2270 }
2271
2272 //print $sql;exit;
2273
2274 dol_syslog(get_class($this)."::build_exportfile select event(s)", LOG_DEBUG);
2275
2276 $resql = $this->db->query($sql);
2277 if ($resql) {
2278 $diff = 0;
2279 while ($obj = $this->db->fetch_object($resql)) {
2280 $qualified = true;
2281
2282 // 'eid','startdate','duration','enddate','title','summary','category','email','url','desc','author'
2283 $event = array();
2284 $event['uid'] = 'dolibarragenda-'.$this->db->database_name.'-'.$obj->id."@".$_SERVER["SERVER_NAME"];
2285 $event['type'] = $type;
2286
2287 $datestart = (int) $this->db->jdate($obj->datep) - (getDolGlobalInt('AGENDA_EXPORT_FIX_TZ') * 3600);
2288
2289 // fix for -> Warning: A non-numeric value encountered
2290 if (is_numeric($this->db->jdate($obj->datep2))) {
2291 $dateend = (int) $this->db->jdate($obj->datep2) - (getDolGlobalInt('AGENDA_EXPORT_FIX_TZ') * 3600);
2292 } else {
2293 // use start date as fall-back to avoid pb with empty end date on ICS readers
2294 $dateend = $datestart;
2295 }
2296
2297 $duration = ($datestart && $dateend) ? ($dateend - $datestart) : 0;
2298 $event['summary'] = $obj->label.($obj->socname ? " (".$obj->socname.")" : "");
2299
2300 if (!empty($filters['module']) && $filters['module'] == 'project@eventorganization') {
2301 $event['desc'] = $obj->note_public;
2302 } else {
2303 $event['desc'] = $obj->note_private;
2304 }
2305 $event['startdate'] = $datestart;
2306 $event['enddate'] = $dateend; // Not required with type 'journal'
2307 $event['duration'] = $duration; // Not required with type 'journal'
2308 $event['author'] = dolGetFirstLastname($obj->firstname, $obj->lastname);
2309 $event['priority'] = $obj->priority;
2310 $event['fulldayevent'] = $obj->fulldayevent;
2311 $event['location'] = $obj->location;
2312 $event['transparency'] = (($obj->transparency > 0) ? 'OPAQUE' : 'TRANSPARENT'); // OPAQUE (busy) or TRANSPARENT (not busy)
2313 $event['category'] = $obj->type_label;
2314 $event['email'] = $obj->email;
2315
2316 // Public URL of event
2317 if ($eventorganization != '') {
2318 $link_subscription = $dolibarr_main_url_root.'/public/eventorganization/attendee_new.php?id='.((int) $obj->id).'&type=global&noregistration=1';
2319 $encodedsecurekey = dol_hash(getDolGlobalString('EVENTORGANIZATION_SECUREKEY').'conferenceorbooth'.((int) $obj->id), 'md5');
2320 $link_subscription .= '&securekey='.urlencode($encodedsecurekey);
2321
2322 $event['url'] = $link_subscription;
2323 }
2324
2325 $event['created'] = (int) $this->db->jdate($obj->datec) - (getDolGlobalInt('AGENDA_EXPORT_FIX_TZ') * 3600);
2326 $event['modified'] = (int) $this->db->jdate($obj->datem) - (getDolGlobalInt('AGENDA_EXPORT_FIX_TZ') * 3600);
2327 $event['num_vote'] = $this->num_vote;
2328 $event['event_paid'] = $this->event_paid;
2329 $event['status'] = $this->status;
2330
2331 // TODO: find a way to call "$this->fetch_userassigned();" without override "$this" properties
2332 $this->id = $obj->id;
2333 $this->fetch_userassigned(false);
2334
2335 $assignedUserArray = array();
2336
2337 foreach ($this->userassigned as $key => $value) {
2338 $assignedUser = new User($this->db);
2339 $assignedUser->fetch($value['id']);
2340
2341 $assignedUserArray[$key] = $assignedUser;
2342 }
2343
2344 if ($filters['module'] != 'project@eventorganization') {
2345 $event['assignedUsers'] = $assignedUserArray;
2346 }
2347
2348 if ($qualified && $datestart) {
2349 $eventarray[] = $event;
2350 }
2351 $diff++;
2352 }
2353
2354 $parameters = array('filters' => $filters, 'eventarray' => &$eventarray);
2355 $reshook = $hookmanager->executeHooks('addMoreEventsExport', $parameters); // Note that $action and $object may have been modified by hook
2356 if ($reshook > 0) {
2357 $eventarray = $hookmanager->resArray;
2358 }
2359 } else {
2360 $this->error = $this->db->lasterror();
2361 return -1;
2362 }
2363
2364 if ($exportholiday == 1) {
2365 $langs->load("holiday");
2366 $title = $langs->transnoentities("Holidays");
2367
2368 $sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.email, u.statut, x.rowid, x.date_debut as date_start, x.date_fin as date_end, x.halfday, x.statut as status";
2369 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as x, ".MAIN_DB_PREFIX."user as u";
2370 $sql .= " WHERE u.rowid = x.fk_user";
2371 $sql .= " AND u.statut = '1'"; // Show only active users (0 = inactive user, 1 = active user)
2372 $sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
2373
2374 $resql = $this->db->query($sql);
2375 if ($resql) {
2376 $num = $this->db->num_rows($resql);
2377 $i = 0;
2378
2379 while ($i < $num) {
2380 $obj = $this->db->fetch_object($resql);
2381 $event = array();
2382
2383 if ($obj->halfday == 1) {
2384 $event['fulldayevent'] = false;
2385
2386 $timestampStart = dol_stringtotime($obj->date_start." 00:00:00", 0);
2387 $timestampEnd = dol_stringtotime($obj->date_end." 12:00:00", 0);
2388 } elseif ($obj->halfday == -1) {
2389 $event['fulldayevent'] = false;
2390
2391 $timestampStart = dol_stringtotime($obj->date_start." 12:00:00", 0);
2392 $timestampEnd = dol_stringtotime($obj->date_end." 23:59:59", 0);
2393 } else {
2394 $event['fulldayevent'] = true;
2395
2396 $timestampStart = dol_stringtotime($obj->date_start." 00:00:00", 0);
2397 $timestampEnd = dol_stringtotime($obj->date_end." 23:59:59", 0);
2398 }
2399
2400 if (getDolGlobalString('AGENDA_EXPORT_FIX_TZ')) {
2401 $timestampStart -= ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
2402 $timestampEnd -= ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
2403 }
2404
2405 $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
2406 $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT;
2407 $url = $urlwithroot.'/holiday/card.php?id='.$obj->rowid;
2408
2409 $event['uid'] = 'dolibarrholiday-'.$this->db->database_name.'-'.$obj->rowid."@".$_SERVER["SERVER_NAME"];
2410 $event['author'] = dolGetFirstLastname($obj->firstname, $obj->lastname);
2411 $event['type'] = 'event';
2412 $event['category'] = "Holiday";
2413 $event['transparency'] = 'OPAQUE';
2414 $event['email'] = $obj->email;
2415 $event['created'] = $timestampStart;
2416 $event['modified'] = $timestampStart;
2417 $event['startdate'] = $timestampStart;
2418 $event['enddate'] = $timestampEnd;
2419 $event['duration'] = $timestampEnd - $timestampStart;
2420 $event['url'] = $url;
2421
2422 if ($obj->status == 2) {
2423 // 2 = leave wait for approval
2424 $event['summary'] = $title." - ".$obj->lastname." (wait for approval)";
2425 } else {
2426 // 3 = leave approved
2427 $event['summary'] = $title." - ".$obj->lastname;
2428 }
2429
2430 $eventarray[] = $event;
2431
2432 $i++;
2433 }
2434 }
2435 }
2436
2437 $langs->load("agenda");
2438
2439 // Define title and desc
2440 $title = '';
2441 $more = '';
2442 if ($login) {
2443 $more = $langs->transnoentities("User").' '.$login;
2444 }
2445 if ($logina) {
2446 $more = $langs->transnoentities("ActionsAskedBy").' '.$logina;
2447 }
2448 if ($logint) {
2449 $more = $langs->transnoentities("ActionsToDoBy").' '.$logint;
2450 }
2451 if ($eventorganization) {
2452 $langs->load("eventorganization");
2453 $title = $langs->transnoentities("OrganizedEvent").(empty($eventarray[0]['label']) ? '' : ' '.$eventarray[0]['label']);
2454 $more = 'ICS file - '.$langs->transnoentities("OrganizedEvent").(empty($eventarray[0]['label']) ? '' : ' '.$eventarray[0]['label']);
2455 }
2456 if ($more) {
2457 if (empty($title)) {
2458 $title = 'Dolibarr actions '.$mysoc->name.' - '.$more;
2459 }
2460 $desc = $more;
2461 $desc .= ' ('.$mysoc->name.' - built by Dolibarr)';
2462 } else {
2463 if (empty($title)) {
2464 $title = 'Dolibarr actions '.$mysoc->name;
2465 }
2466 $desc = $langs->transnoentities('ListOfActions');
2467 $desc .= ' ('.$mysoc->name.' - built by Dolibarr)';
2468 }
2469
2470 // Create temp file
2471 $outputfiletmp = tempnam($conf->agenda->dir_temp, 'tmp'); // Temporary file (allow call of function by different threads
2472 dolChmod($outputfiletmp);
2473
2474 // Write file
2475 if ($format == 'vcal') {
2476 $result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
2477 } elseif ($format == 'ical') {
2478 $result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
2479 } elseif ($format == 'rss') {
2480 $result = build_rssfile($format, $title, $desc, $eventarray, $outputfiletmp);
2481 }
2482
2483 if ($result >= 0) {
2484 if (dol_move($outputfiletmp, $outputfile, '0', 1, 0, 0)) {
2485 $result = 1;
2486 } else {
2487 $this->error = 'Failed to rename '.$outputfiletmp.' into '.$outputfile;
2488 dol_syslog(get_class($this)."::build_exportfile ".$this->error, LOG_ERR);
2489 dol_delete_file($outputfiletmp, 0, 1);
2490 $result = -1;
2491 }
2492 } else {
2493 dol_syslog(get_class($this)."::build_exportfile build_xxxfile function fails to for format=".$format." outputfiletmp=".$outputfile, LOG_ERR);
2494 dol_delete_file($outputfiletmp, 0, 1);
2495 $langs->load("errors");
2496 $this->error = $langs->trans("ErrorFailToCreateFile", $outputfile);
2497 }
2498 }
2499
2500 return $result;
2501 }
2502
2510 public function initAsSpecimen()
2511 {
2512 global $user;
2513
2514 $now = dol_now();
2515
2516 // Initialise parameters
2517 $this->id = 0;
2518 $this->specimen = 1;
2519
2520 $this->type_code = 'AC_OTH';
2521 $this->code = 'AC_SPECIMEN_CODE';
2522 $this->label = 'Label of event Specimen';
2523 $this->datec = $now;
2524 $this->datem = $now;
2525 $this->datep = $now;
2526 $this->datef = $now;
2527 $this->fulldayevent = 0;
2528 $this->percentage = 0;
2529 $this->status = 0;
2530 $this->location = 'Location';
2531 $this->transparency = 1; // 1 means opaque
2532 $this->priority = 1;
2533 //$this->note_public = "This is a 'public' note.";
2534 $this->note_private = "This is a 'private' note.";
2535
2536 $this->userownerid = $user->id;
2537 $this->userassigned[$user->id] = array('id' => $user->id, 'transparency' => 1);
2538 return 1;
2539 }
2540
2549 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
2550 {
2551 $tables = array(
2552 'actioncomm'
2553 );
2554
2555 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
2556 }
2557
2566 public static function replaceProduct(DoliDB $dbs, $origin_id, $dest_id)
2567 {
2568 $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'actioncomm SET fk_element = ' . ((int) $dest_id) . ' WHERE elementtype="product" AND fk_element = '.((int) $origin_id);
2569 // using $dbs, not $this->db because function is static
2570 if (!$dbs->query($sql)) {
2571 //$this->errors = $dbs->lasterror();
2572 return false;
2573 }
2574
2575 return true;
2576 }
2577
2583 public function hasDelay()
2584 {
2585 global $conf;
2586
2587 $now = dol_now();
2588
2589 return $this->datep && ($this->datep < ($now - $conf->agenda->warning_delay));
2590 }
2591
2592
2601 public function loadReminders($type = '', $fk_user = 0, $onlypast = true)
2602 {
2603 global $conf, $langs, $user;
2604
2605 $error = 0;
2606
2607 $this->reminders = array();
2608
2609 //Select all action comm reminders for event
2610 $sql = "SELECT rowid as id, typeremind, dateremind, status, offsetvalue, offsetunit, fk_user, fk_email_template, lasterror";
2611 $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2612 $sql .= " WHERE fk_actioncomm = ".((int) $this->id);
2613 if ($onlypast) {
2614 $sql .= " AND dateremind <= '".$this->db->idate(dol_now())."'";
2615 }
2616 if ($type) {
2617 $sql .= " AND typeremind = '".$this->db->escape($type)."'";
2618 }
2619 if ($fk_user > 0) {
2620 $sql .= " AND fk_user = ".((int) $fk_user);
2621 }
2622 if (!getDolGlobalString('AGENDA_REMINDER_EMAIL')) {
2623 $sql .= " AND typeremind <> 'email'";
2624 }
2625 if (!getDolGlobalString('AGENDA_REMINDER_BROWSER')) {
2626 $sql .= " AND typeremind <> 'browser'";
2627 }
2628
2629 $sql .= $this->db->order("dateremind", "ASC");
2630 $resql = $this->db->query($sql);
2631
2632 if ($resql) {
2633 while ($obj = $this->db->fetch_object($resql)) {
2634 $tmpactioncommreminder = new ActionCommReminder($this->db);
2635 $tmpactioncommreminder->id = $obj->id;
2636 $tmpactioncommreminder->typeremind = $obj->typeremind;
2637 $tmpactioncommreminder->dateremind = $obj->dateremind;
2638 $tmpactioncommreminder->offsetvalue = $obj->offsetvalue;
2639 $tmpactioncommreminder->offsetunit = $obj->offsetunit;
2640 $tmpactioncommreminder->status = $obj->status;
2641 $tmpactioncommreminder->fk_user = $obj->fk_user;
2642 $tmpactioncommreminder->fk_email_template = $obj->fk_email_template;
2643 $tmpactioncommreminder->lasterror = $obj->lasterror;
2644
2645 $this->reminders[$obj->id] = $tmpactioncommreminder;
2646 }
2647 } else {
2648 $this->error = $this->db->lasterror();
2649 $error++;
2650 }
2651
2652 return count($this->reminders);
2653 }
2654
2655
2662 public function sendEmailsReminder()
2663 {
2664 global $conf, $langs, $user;
2665
2666 $error = 0;
2667 $this->output = '';
2668 $this->error = '';
2669 $nbMailSend = 0;
2670 $errorsMsg = array();
2671
2672 if (!isModEnabled('agenda')) { // Should not happen. If module disabled, cron job should not be visible.
2673 $langs->load("agenda");
2674 $this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2675 return 0;
2676 }
2677 if (!getDolGlobalString('AGENDA_REMINDER_EMAIL')) {
2678 $langs->load("agenda");
2679 $this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2680 return 0;
2681 }
2682
2683 $now = dol_now();
2684 $actionCommReminder = new ActionCommReminder($this->db);
2685
2686 dol_syslog(__METHOD__." start", LOG_INFO);
2687
2688 $this->db->begin();
2689
2690 //Select all action comm reminders
2691 $sql = "SELECT rowid as id FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2692 $sql .= " WHERE typeremind = 'email'";
2693 $sql .= " AND status = 0"; // 0=No yet sent, -1=Error. TODO Include reminder in error once we can count number of error, so we can try 5 times and not more on errors.
2694 $sql .= " AND dateremind <= '".$this->db->idate($now)."'";
2695 $sql .= " AND entity IN (".getEntity('actioncomm').")";
2696 $sql .= $this->db->order("dateremind", "ASC");
2697 $resql = $this->db->query($sql);
2698
2699 if ($resql) {
2700 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2701 $formmail = new FormMail($this->db);
2702 $to = null; // Ensure 'to' is defined for static analysis
2703
2704 while ($obj = $this->db->fetch_object($resql)) {
2705 $res = $actionCommReminder->fetch($obj->id);
2706 if ($res < 0) {
2707 $error++;
2708 $errorsMsg[] = "Failed to load invoice ActionComm Reminder";
2709 }
2710
2711 if (!$error) {
2712 //Select email template
2713 $arraymessage = $formmail->getEMailTemplate($this->db, 'actioncomm_send', $user, $langs, (!empty($actionCommReminder->fk_email_template)) ? $actionCommReminder->fk_email_template : -1, 1);
2714
2715 // Load event
2716 $res = $this->fetch($actionCommReminder->fk_actioncomm);
2717 if ($res > 0) {
2718 $res = $this->fetch_thirdparty();
2719 }
2720 if ($res > 0) {
2721 // PREPARE EMAIL
2722 $errormesg = '';
2723
2724 // Make substitution in email content
2725 $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $this);
2726
2727 complete_substitutions_array($substitutionarray, $langs, $this);
2728
2729 // Content
2730 $sendContent = make_substitutions($langs->trans($arraymessage->content), $substitutionarray);
2731
2732 //Topic
2733 $sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->transnoentities('EventReminder'));
2734
2735 // Recipient
2736 $recipient = new User($this->db);
2737 $res = $recipient->fetch($actionCommReminder->fk_user);
2738 if ($res > 0) {
2739 if (!empty($recipient->email)) {
2740 $to = $recipient->email;
2741 } else {
2742 $errormesg = "Failed to send remind to user id=".$actionCommReminder->fk_user.". No email defined for user.";
2743 $error++;
2744 }
2745 } else {
2746 $errormesg = "Failed to load recipient with user id=".$actionCommReminder->fk_user;
2747 $error++;
2748 }
2749
2750 // Sender
2751 $from = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
2752 if (empty($from)) {
2753 $errormesg = "Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
2754 $error++;
2755 }
2756
2757 if (!$error) {
2758 // Errors Recipient
2759 $errors_to = getDolGlobalString('MAIN_MAIL_ERRORS_TO');
2760
2761 // Mail Creation
2762 $cMailFile = new CMailFile($sendTopic, $to, $from, $sendContent, array(), array(), array(), '', "", 0, 1, $errors_to, '', '', '', '', '');
2763
2764 // Sending Mail
2765 if ($cMailFile->sendfile()) {
2766 $nbMailSend++;
2767 } else {
2768 $errormesg = 'Failed to send email to: '.$to.' '.$cMailFile->error.implode(',', $cMailFile->errors);
2769 $error++;
2770 }
2771 }
2772
2773 if (!$error) {
2774 $actionCommReminder->status = $actionCommReminder::STATUS_DONE;
2775
2776 $res = $actionCommReminder->update($user);
2777 if ($res < 0) {
2778 $errorsMsg[] = "Failed to update status to done of ActionComm Reminder";
2779 $error++;
2780 break; // This is to avoid to have this error on all the selected email. If we fails here for one record, it may fails for others. We must solve first.
2781 }
2782 } else {
2783 $actionCommReminder->status = $actionCommReminder::STATUS_ERROR;
2784 $actionCommReminder->lasterror = dol_trunc($errormesg, 128, 'right', 'UTF-8', 1);
2785
2786 $res = $actionCommReminder->update($user);
2787 if ($res < 0) {
2788 $errorsMsg[] = "Failed to update status to error of ActionComm Reminder";
2789 $error++;
2790 break; // This is to avoid to have this error on all the selected email. If we fails here for one record, it may fails for others. We must solve first.
2791 } else {
2792 $errorsMsg[] = $errormesg;
2793 }
2794 }
2795 } else {
2796 $errorsMsg[] = 'Failed to fetch record actioncomm with ID = '.$actionCommReminder->fk_actioncomm;
2797 $error++;
2798 }
2799 }
2800 }
2801 } else {
2802 $error++;
2803 }
2804
2805 if (!$error) {
2806 // Delete also very old past events (we do not keep more than 1 month record in past)
2807 $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2808 $sql .= " WHERE dateremind < '".$this->db->idate($now - (3600 * 24 * 32))."'";
2809 $sql .= " AND status = ".((int) $actionCommReminder::STATUS_DONE);
2810 $resql = $this->db->query($sql);
2811
2812 if (!$resql) {
2813 $errorsMsg[] = 'Failed to delete old reminders';
2814 //$error++; // If this fails, we must not rollback other SQL requests already done. Never mind.
2815 }
2816 }
2817
2818 if (!$error) {
2819 $this->output = 'Nb of emails sent : '.$nbMailSend;
2820 $this->db->commit();
2821
2822 dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO);
2823
2824 return 0;
2825 } else {
2826 $this->db->commit(); // We commit also on error, to have the error message recorded.
2827 $this->error = 'Nb of emails sent : '.$nbMailSend.', '.(!empty($errorsMsg) ? implode(', ', $errorsMsg) : $error);
2828
2829 dol_syslog(__METHOD__." end - ".$this->error, LOG_INFO);
2830
2831 return $error;
2832 }
2833 }
2834
2843 public function updatePercent($id, $percent, $usermodid = 0)
2844 {
2845 $this->db->begin();
2846
2847 $sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm ";
2848 $sql .= " SET percent = ".(int) $percent;
2849 if ($usermodid > 0) {
2850 $sql .= ", fk_user_mod = ".$usermodid;
2851 }
2852 $sql .= " WHERE id = ".((int) $id);
2853
2854 if ($this->db->query($sql)) {
2855 $this->db->commit();
2856 return 1;
2857 } else {
2858 $this->db->rollback();
2859 $this->error = $this->db->lasterror();
2860 return -1;
2861 }
2862 }
2863}
$id
Definition account.php:39
$object ref
Definition info.php:79
Class to manage agenda events (actions)
const EVENT_FINISHED
Typical value for a event that is in a finished state.
hasDelay()
Is the action delayed?
build_exportfile($format, $type, $cachedelay, $filename, $filters, $exportholiday=0)
Export events from database into a cal file.
getTooltipContentArray($params)
getTooltipContentArray
update(User $user, $notrigger=0)
Update action into database If percentage = 100, on met a jour date 100%.
fetch_userassigned($override=true)
Initialize this->userassigned array with list of id of user assigned to event.
info($id)
Charge les information d'ordre info dans l'objet facture.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
const EVENT_IN_PROGRESS
Typical value for a event that is in a progress state.
getNomUrl($withpicto=0, $maxlength=0, $classname='', $option='', $overwritepicto=0, $notooltip=0, $save_lastsearch_value=-1)
Return URL of event Use $this->id, $this->type_code, $this->label and $this->type_label.
sendEmailsReminder()
Send reminders by emails CAN BE A CRON TASK.
create(User $user, $notrigger=0)
Add an action/event into database.
const EVENT_TODO
Typical value for a event that is in a todo state.
setCategories($categories)
Sets object to supplied categories.
createFromClone(User $fuser, $socid)
Load an object from its id and create a new one in database.
LibStatut($percent, $mode, $hidenastatus=0, $datestart='')
Return label of action status.
getActions($socid=0, $fk_element=0, $elementtype='', $filter='', $sortfield='a.datep', $sortorder='DESC', $limit=0)
Load all objects with filters.
load_board($user, $load_state_board=0)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
fetch($id, $ref='', $ref_ext='', $email_msgid='', $loadresources=1)
Load object from database.
updatePercent($id, $percent, $usermodid=0)
Update the percent value of a event with the given id.
getTypeLabel($mode=0)
Return label of type of event.
loadReminders($type='', $fk_user=0, $onlypast=true)
Load event reminder of events.
fetchResources()
Initialize $this->userassigned & this->socpeopleassigned array with list of id of user and contact as...
static replaceProduct(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a product id with another one.
getTypePicto($morecss='pictofixedwidth paddingright valignmiddle', $titlealt='')
Return Picto of type of event.
__construct(DoliDB $db)
Constructor.
initAsSpecimen()
Initialise an instance with random values.
getLibStatut($mode, $hidenastatus=0)
Return the label of the status.
Class for ActionCommReminder.
Class to manage different types of events.
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
Class to manage categories.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
setErrorsFromObject($object)
setErrorsFromObject
deleteExtraFields()
Delete all extra fields values for the current object.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage Dolibarr database access.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new Form...
Class to manage hooks.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:162
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:596
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition date.lib.php:427
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:615
dol_filemtime($pathoffile)
Return time of a file.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_move($srcfile, $destfile, $newmask='0', $overwriteifexists=1, $testvirus=0, $indexdatabase=1, $moreinfo=array())
Move a file into another name.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
dolChmod($filepath, $newmask='')
Change mod of a file.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
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...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_textishtml($msg, $option=0)
Return if a text is a html content.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null, $include=null)
Return array of possible common substitutions.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
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...
query($query, $usesavepoint=0, $type='auto', $result_mode=0)
Execute a SQL request and return the resultset.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:137
dol_hash($chain, $type='0', $nosalt=0)
Returns a hash (non reversible encryption) of a string.
build_calfile($format, $title, $desc, $events_array, $outputfile)
Build a file from an array of events All input params and data must be encoded in $conf->charset_outp...
Definition xcal.lib.php:35
build_rssfile($format, $title, $desc, $events_array, $outputfile, $filter='', $url='', $langcode='')
Build a file from an array of events.
Definition xcal.lib.php:325