dolibarr 21.0.3
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 (!isset($val['id']) || !is_scalar($val['id'])) {
1243 continue;
1244 }
1245 if (!empty($already_inserted[$val['id']])) {
1246 continue;
1247 }
1248
1249 $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1250 $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'])).")";
1251
1252 $resql = $this->db->query($sql);
1253 if (!$resql) {
1254 $error++;
1255 $this->errors[] = $this->db->lasterror();
1256 } else {
1257 $already_inserted[$val['id']] = true;
1258 }
1259 //var_dump($sql);exit;
1260 }
1261 }
1262
1263 if (!$error) {
1264 $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".((int) $this->id)." AND element_type = 'socpeople'";
1265 $resql = $this->db->query($sql);
1266
1267 if (!empty($this->socpeopleassigned)) {
1268 $already_inserted = array();
1269 foreach ($this->socpeopleassigned as $val) {
1270 if (!is_array($val)) { // For backward compatibility when val=id
1271 $val = array('id' => $val);
1272 }
1273 if (!empty($already_inserted[$val['id']])) {
1274 continue;
1275 }
1276
1277 $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1278 $sql .= " VALUES(".((int) $this->id).", 'socpeople', ".((int) $val['id']).", 0, 0, 0)";
1279
1280 $resql = $this->db->query($sql);
1281 if (!$resql) {
1282 $error++;
1283 $this->errors[] = $this->db->lasterror();
1284 } else {
1285 $already_inserted[$val['id']] = true;
1286 }
1287 }
1288 }
1289 }
1290
1291 if (!$error && !$notrigger) {
1292 // Call trigger
1293 $result = $this->call_trigger('ACTION_MODIFY', $user);
1294 if ($result < 0) {
1295 $error++;
1296 }
1297 // End call triggers
1298 }
1299
1300 if (!$error) {
1301 $this->db->commit();
1302 return 1;
1303 } else {
1304 $this->db->rollback();
1305 dol_syslog(get_class($this)."::update ".implode(',', $this->errors), LOG_ERR);
1306 return -2;
1307 }
1308 } else {
1309 $this->db->rollback();
1310 $this->error = $this->db->lasterror();
1311 return -1;
1312 }
1313 }
1314
1328 public function getActions($socid = 0, $fk_element = 0, $elementtype = '', $filter = '', $sortfield = 'a.datep', $sortorder = 'DESC', $limit = 0)
1329 {
1330 global $hookmanager;
1331
1332 $resarray = array();
1333
1334 dol_syslog(get_class($this)."::getActions", LOG_DEBUG);
1335
1336 // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
1337 if (!is_object($hookmanager)) {
1338 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
1339 $hookmanager = new HookManager($this->db);
1340 }
1341 $hookmanager->initHooks(array('agendadao'));
1342
1343 $sql = "SELECT a.id";
1344 $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1345 // Fields from hook
1346 $parameters = array('sql' => &$sql, 'socid' => $socid, 'fk_element' => $fk_element, 'elementtype' => $elementtype);
1347 $reshook = $hookmanager->executeHooks('getActionsListFrom', $parameters); // Note that $action and $object may have been modified by hook
1348 if (!empty($hookmanager->resPrint)) {
1349 $sql .= $hookmanager->resPrint;
1350 }
1351 $sql .= " WHERE a.entity IN (".getEntity('agenda').")";
1352 if (!empty($socid)) {
1353 $sql .= " AND a.fk_soc = ".((int) $socid);
1354 }
1355 if (!empty($elementtype)) {
1356 if ($elementtype == 'project') {
1357 $sql .= ' AND a.fk_project = '.((int) $fk_element);
1358 } elseif ($elementtype == 'contact') {
1359 $sql .= ' AND EXISTS';
1360 $sql .= " (SELECT r.rowid FROM ".MAIN_DB_PREFIX."actioncomm_resources as r WHERE";
1361 $sql .= " r.element_type = 'socpeople' AND r.fk_element = ".((int) $fk_element).' AND r.fk_actioncomm = a.id)';
1362 } elseif ($elementtype == 'user') {
1363 $sql .= " AND (a.fk_user_action = ".((int) $fk_element)." OR EXISTS";
1364 $sql .= " (SELECT r.rowid FROM ".MAIN_DB_PREFIX."actioncomm_resources as r WHERE";
1365 $sql .= " r.element_type = 'user' AND r.fk_element = ".((int) $fk_element).' AND r.fk_actioncomm = a.id)';
1366 $sql .= ")";
1367 } else {
1368 $sql .= " AND a.fk_element = ".((int) $fk_element)." AND a.elementtype = '".$this->db->escape($elementtype)."'";
1369 }
1370 }
1371 if (!empty($filter)) {
1372 $sql .= $filter;
1373 }
1374 // Fields where hook
1375 $parameters = array('sql' => &$sql, 'socid' => $socid, 'fk_element' => $fk_element, 'elementtype' => $elementtype);
1376 $reshook = $hookmanager->executeHooks('getActionsListWhere', $parameters); // Note that $action and $object may have been modified by hook
1377 if (!empty($hookmanager->resPrint)) {
1378 $sql .= $hookmanager->resPrint;
1379 }
1380 if ($sortorder && $sortfield) {
1381 $sql .= $this->db->order($sortfield, $sortorder);
1382 }
1383 $sql .= $this->db->plimit($limit, 0);
1384
1385 $resql = $this->db->query($sql);
1386 if ($resql) {
1387 $num = $this->db->num_rows($resql);
1388
1389 if ($num) {
1390 for ($i = 0; $i < $num; $i++) {
1391 $obj = $this->db->fetch_object($resql);
1392 $actioncommstatic = new ActionComm($this->db);
1393 $actioncommstatic->fetch($obj->id);
1394 $resarray[$i] = $actioncommstatic;
1395 }
1396 }
1397 $this->db->free($resql);
1398 return $resarray;
1399 } else {
1400 return $this->db->lasterror();
1401 }
1402 }
1403
1404 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1412 public function load_board($user, $load_state_board = 0)
1413 {
1414 // phpcs:enable
1415 global $conf, $langs;
1416
1417 if (empty($load_state_board)) {
1418 $sql = "SELECT a.id, a.datep as dp";
1419 } else {
1420 $this->nb = array();
1421 $sql = "SELECT count(a.id) as nb";
1422 }
1423 $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1424 if (!$user->hasRight('agenda', 'allactions', 'read')) {
1425 $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);
1426 }
1427 $sql .= " WHERE 1 = 1";
1428 if (empty($load_state_board)) {
1429 $sql .= " AND a.percent >= 0 AND a.percent < 100";
1430 }
1431 $sql .= " AND a.entity IN (".getEntity('agenda').")";
1432 if (!$user->hasRight('agenda', 'allactions', 'read')) {
1433 $sql .= " AND (a.fk_user_author = ".((int) $user->id)." OR a.fk_user_action = ".((int) $user->id);
1434 $sql .= " OR ar.fk_element = ".((int) $user->id);
1435 $sql .= ")";
1436 }
1437 // If the internal user must only see his customers, force searching by him
1438 $search_sale = 0;
1439 if (!$user->hasRight('societe', 'client', 'voir')) {
1440 $search_sale = $user->id;
1441 }
1442 // Search on sale representative
1443 if ($search_sale && $search_sale != '-1') {
1444 if ($search_sale == -2) {
1445 $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = a.fk_soc)";
1446 } elseif ($search_sale > 0) {
1447 $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).")";
1448 }
1449 }
1450
1451 $resql = $this->db->query($sql);
1452 if ($resql) {
1453 $response = null; // Ensure the variable is defined
1454 if (empty($load_state_board)) {
1455 $agenda_static = new ActionComm($this->db);
1456 $response = new WorkboardResponse();
1457 $response->warning_delay = $conf->agenda->warning_delay / 60 / 60 / 24;
1458 $response->label = $langs->trans("ActionsToDo");
1459 $response->labelShort = $langs->trans("ActionsToDoShort");
1460 $response->url = DOL_URL_ROOT.'/comm/action/list.php?mode=show_list&actioncode=0&status=todo&mainmenu=agenda';
1461 if ($user->hasRight("agenda", "allactions", "read")) {
1462 $response->url .= '&filtert=-1';
1463 }
1464 $response->img = img_object('', "action", 'class="inline-block valigntextmiddle"');
1465 }
1466 // This assignment in condition is not a bug. It allows walking the results.
1467 while ($obj = $this->db->fetch_object($resql)) {
1468 if (empty($load_state_board)) {
1469 '@phan-var-force WorkboardResponse $response
1470 @phan-var-force ActionComm $agenda_static';
1471 $response->nbtodo++;
1472 $agenda_static->datep = $this->db->jdate($obj->dp);
1473 if ($agenda_static->hasDelay()) {
1474 $response->nbtodolate++;
1475 }
1476 } else {
1477 $this->nb["actionscomm"] = $obj->nb;
1478 }
1479 }
1480
1481 $this->db->free($resql);
1482 if (empty($load_state_board) && $response instanceof WorkboardResponse) {
1483 return $response;
1484 } else {
1485 return 1;
1486 }
1487 } else {
1488 dol_print_error($this->db);
1489 $this->error = $this->db->error();
1490 return -1;
1491 }
1492 }
1493
1494
1501 public function info($id)
1502 {
1503 $sql = 'SELECT ';
1504 $sql .= ' a.id,';
1505 $sql .= ' datec,';
1506 $sql .= ' tms as datem,';
1507 $sql .= ' fk_user_author,';
1508 $sql .= ' fk_user_mod';
1509 $sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a';
1510 $sql .= ' WHERE a.id = '.((int) $id);
1511
1512 dol_syslog(get_class($this)."::info", LOG_DEBUG);
1513 $result = $this->db->query($sql);
1514 if ($result) {
1515 if ($this->db->num_rows($result)) {
1516 $obj = $this->db->fetch_object($result);
1517
1518 $this->id = $obj->id;
1519
1520 $this->user_creation_id = $obj->fk_user_author;
1521 $this->user_modification_id = $obj->fk_user_mod;
1522 $this->date_creation = $this->db->jdate($obj->datec);
1523 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1524 }
1525 $this->db->free($result);
1526 } else {
1527 dol_print_error($this->db);
1528 }
1529 }
1530
1531
1539 public function getLibStatut($mode, $hidenastatus = 0)
1540 {
1541 return $this->LibStatut($this->percentage, $mode, $hidenastatus, $this->datep);
1542 }
1543
1544 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1554 public function LibStatut($percent, $mode, $hidenastatus = 0, $datestart = '')
1555 {
1556 // phpcs:enable
1557 global $langs;
1558
1559 $labelStatus = $langs->transnoentitiesnoconv('StatusNotApplicable');
1560 if ($percent == -1 && !$hidenastatus) {
1561 $labelStatus = $langs->transnoentitiesnoconv('StatusNotApplicable');
1562 } elseif ($percent == 0) {
1563 $labelStatus = $langs->transnoentitiesnoconv('StatusActionToDo').' (0%)';
1564 } elseif ($percent > 0 && $percent < 100) {
1565 $labelStatus = $langs->transnoentitiesnoconv('StatusActionInProcess').' ('.$percent.'%)';
1566 } elseif ($percent >= 100) {
1567 $labelStatus = $langs->transnoentitiesnoconv('StatusActionDone').' (100%)';
1568 }
1569
1570 $labelStatusShort = $langs->transnoentitiesnoconv('StatusNotApplicable');
1571 if ($percent == -1 && !$hidenastatus) {
1572 $labelStatusShort = $langs->trans('NA');
1573 } elseif ($percent == 0) {
1574 $labelStatusShort = '0%';
1575 } elseif ($percent > 0 && $percent < 100) {
1576 $labelStatusShort = $percent.'%';
1577 } elseif ($percent >= 100) {
1578 $labelStatusShort = '100%';
1579 }
1580
1581 $statusType = 'status9';
1582 if ($percent == -1 && !$hidenastatus) {
1583 $statusType = 'status9';
1584 }
1585 if ($percent == 0) {
1586 $statusType = 'status1';
1587 }
1588 if ($percent > 0 && $percent < 100) {
1589 $statusType = 'status3';
1590 }
1591 if ($percent >= 100) {
1592 $statusType = 'status6';
1593 }
1594
1595 return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1596 }
1597
1604 public function getTooltipContentArray($params)
1605 {
1606 global $langs, $form;
1607
1608 $langs->load('agenda');
1609
1610 $datas = array();
1611 $nofetch = !empty($params['nofetch']);
1612
1613 // Set label of type
1614 $labeltype = '';
1615 if ($this->type_code) {
1616 $langs->load("commercial");
1617 $labeltype = ($langs->transnoentities("Action".$this->type_code) != "Action".$this->type_code) ? $langs->transnoentities("Action".$this->type_code) : $this->type_label;
1618 }
1619 if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1620 if ($this->type_code != 'AC_OTH_AUTO') {
1621 $labeltype = $langs->trans('ActionAC_MANUAL');
1622 }
1623 }
1624 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans('Action').'</u>';
1625 if (!empty($this->ref)) {
1626 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.dol_escape_htmltag($this->ref);
1627 }
1628 if (!empty($this->label)) {
1629 $datas['title'] = '<br><b>'.$langs->trans('Title').':</b> '.dol_escape_htmltag($this->label);
1630 }
1631 if (!empty($labeltype)) {
1632 $datas['labeltype'] = '<br><b>'.$langs->trans('Type').':</b> '.dol_escape_htmltag($labeltype);
1633 }
1634 if (!empty($this->location)) {
1635 $datas['location'] = '<br><b>'.$langs->trans('Location').':</b> '.dol_escape_htmltag($this->location);
1636 }
1637 if (isset($this->transparency)) {
1638 $datas['transparency'] = '<br><b>'.$langs->trans('Busy').':</b> '.yn($this->transparency);
1639 }
1640 if (!empty($this->email_msgid)) {
1641 $langs->load("mails");
1642 $datas['space'] = '<br>';
1643 // $datas['email'] = '<br><b>'.img_picto('', 'email').' '.$langs->trans("Email").'</b>';
1644 $datas['mailtopic'] = '<br><b>'.$langs->trans('MailTopic').':</b> '.dol_escape_htmltag($this->email_subject);
1645 $datas['mailfrom'] = '<br><b>'.$langs->trans('MailFrom').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_from);
1646 $datas['mailto'] = '<br><b>'.$langs->trans('MailTo').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_to);
1647 if (!empty($this->email_tocc)) {
1648 $datas['mailcc'] = '<br><b>'.$langs->trans('MailCC').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_tocc);
1649 }
1650 /* Disabled because bcc must remain by definition not visible
1651 if (!empty($this->email_tobcc)) {
1652 $datas['mailccc'] = '<br><b>'.$langs->trans('MailCCC').':</b> '.$this->email_tobcc;
1653 } */
1654 }
1655 if (!empty($this->note_private)) {
1656 $datas['description'] = '<br><hr>';
1657 // Try to limit length of content
1658 $texttoshow = dolGetFirstLineOfText($this->note_private, 10);
1659 // Restrict height of content into the tooltip
1660 $datas['note'] = '<div class="tenlinesmax">';
1661 $datas['note'] .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), '<br>', $texttoshow));
1662 $datas['note'] .= '</div>';
1663 }
1664
1665 // show categories for this record only in ajax to not overload lists
1666 if (isModEnabled('category') && !$nofetch) {
1667 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1668 if (empty($form)) {
1669 include_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
1670 $form = new Form($this->db);
1671 }
1672 $tmpcategstring = $form->showCategories($this->id, Categorie::TYPE_ACTIONCOMM, 1);
1673 if ($tmpcategstring) {
1674 $datas['categories'] = '<br>'.$tmpcategstring;
1675 }
1676 }
1677
1678 return $datas;
1679 }
1680
1694 public function getNomUrl($withpicto = 0, $maxlength = 0, $classname = '', $option = '', $overwritepicto = 0, $notooltip = 0, $save_lastsearch_value = -1)
1695 {
1696 global $conf, $langs, $user, $hookmanager, $action;
1697
1698 if (!empty($conf->dol_no_mouse_hover)) {
1699 $notooltip = 1; // Force disable tooltips
1700 }
1701
1702 $canread = 0;
1703 if ($user->hasRight('agenda', 'myactions', 'read') && ($this->authorid == $user->id || $this->userownerid == $user->id)) {
1704 $canread = 1; // Can read my event
1705 }
1706 if ($user->hasRight('agenda', 'myactions', 'read') && array_key_exists($user->id, $this->userassigned)) {
1707 $canread = 1; // Can read my event i am assigned
1708 }
1709 if ($user->hasRight('agenda', 'allactions', 'read')) {
1710 $canread = 1; // Can read all event of other
1711 }
1712 if (!$canread) {
1713 $option = 'nolink';
1714 }
1715
1716 $label = $this->label;
1717
1718 $result = '';
1719
1720 // Set label of type
1721 $labeltype = $this->getTypeLabel(1);
1722
1723 $tooltip = img_picto('', $this->picto).' <u>'.$langs->trans('Action').'</u>';
1724
1725 $tooltip .= ' &nbsp; - &nbsp; '.$this->getTypePicto('pictofixedwidth paddingright valignmiddle').$labeltype;
1726 if (!empty($this->ref)) {
1727 $tooltip .= '<br><b>'.$langs->trans('Ref').':</b> '.dol_escape_htmltag($this->ref);
1728 }
1729 if (!empty($label)) {
1730 $tooltip .= '<br><b>'.$langs->trans('Title').':</b> '.dol_escape_htmltag($label);
1731 }
1732 if (!empty($this->location)) {
1733 $tooltip .= '<br><b>'.$langs->trans('Location').':</b> '.dol_escape_htmltag($this->location);
1734 }
1735
1736 $tooltip .= '<br><b>'.$langs->trans('Date').':</b> '.dol_print_date($this->datep, 'dayhourreduceformat', 'tzuserrel');
1737 if ($this->datef) {
1738 $tmpa = dol_getdate($this->datep);
1739 $tmpb = dol_getdate($this->datef);
1740 if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) {
1741 if ($tmpa['hours'] != $tmpb['hours'] || $tmpa['minutes'] != $tmpb['minutes']) {
1742 $tooltip .= '-'.dol_print_date($this->datef, 'hour', 'tzuserrel');
1743 }
1744 } else {
1745 $tooltip .= '-'.dol_print_date($this->datef, 'dayhourreduceformat', 'tzuserrel');
1746 }
1747 }
1748
1749 if ($this->datef && $this->datep != $this->datef && isset($this->transparency)) {
1750 $tooltip .= '<br><b>'.$langs->trans('Busy').':</b> '.yn($this->transparency);
1751 }
1752 if (!empty($this->email_msgid)) {
1753 $langs->load("mails");
1754 $tooltip .= '<br>';
1755 //$tooltip .= '<br><b>'.img_picto('', 'email').' '.$langs->trans("Email").'</b>';
1756 $tooltip .= '<br><b>'.$langs->trans('MailTopic').':</b> '.dol_escape_htmltag($this->email_subject);
1757 $tooltip .= '<br><b>'.$langs->trans('MailFrom').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), !empty($this->email_from) ? $this->email_from : '');
1758 $tooltip .= '<br><b>'.$langs->trans('MailTo').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), !empty($this->email_to) ? $this->email_to : '');
1759 if (!empty($this->email_tocc)) {
1760 $tooltip .= '<br><b>'.$langs->trans('MailCC').':</b> '.str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_tocc);
1761 }
1762 /* Disabled because bcc must remain by definition not visible
1763 if (!empty($this->email_tobcc)) {
1764 $tooltip .= '<br><b>'.$langs->trans('MailCCC').':</b> '.$this->email_tobcc;
1765 } */
1766 }
1767 if (!empty($this->note_private)) {
1768 $tooltip .= '<br><hr>';
1769 $texttoshow = dolGetFirstLineOfText($this->note_private, 8); // Try to limit length of content
1770 $tooltip .= '<div class="tenlinesmax">'; // Restrict height of content into the tooltip
1771 $tooltip .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), '<br>', $texttoshow));
1772 $tooltip .= '</div>';
1773 }
1774
1775 $linkclose = '';
1776 $classfortooltip = 'classfortooltip';
1777 $dataparams = '';
1778 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1779 $params = [
1780 'id' => $this->id,
1781 'objecttype' => $this->element,
1782 'option' => $option,
1783 'nofetch' => 1,
1784 ];
1785 $classfortooltip = 'classforajaxtooltip';
1786 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
1787 $tooltip = '';
1788 }
1789 if (empty($notooltip)) {
1790 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1791 $label = $langs->trans("ShowAction");
1792 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($tooltip).'"';
1793 }
1794 $linkclose .= ($tooltip ? ' title="'.dolPrintHTMLForAttribute($tooltip).'"' : ' title="tocomplete"');
1795 $linkclose .= $dataparams.' class="'.$classname.' '.$classfortooltip.'"';
1796 } else {
1797 $linkclose .= ' class="'.$classname.'"';
1798 }
1799
1800 $url = '';
1801 if ($option == 'birthday') {
1802 $url = DOL_URL_ROOT.'/contact/perso.php?id='.$this->id;
1803 } elseif ($option == 'holiday') {
1804 $url = DOL_URL_ROOT.'/holiday/card.php?id='.$this->id;
1805 } else {
1806 $url = DOL_URL_ROOT.'/comm/action/card.php?id='.$this->id;
1807 }
1808
1809 if ($option !== 'nolink') {
1810 // Add param to save lastsearch_values or not
1811 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1812 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1813 $add_save_lastsearch_values = 1;
1814 }
1815 if ($add_save_lastsearch_values) {
1816 $url .= '&save_lastsearch_values=1';
1817 }
1818 }
1819
1820 $linkstart = '<a href="'.$url.'"';
1821 $linkstart .= $linkclose.'>';
1822 $linkend = '</a>';
1823
1824 if ($option == 'nolink') {
1825 $linkstart = '';
1826 $linkend = '';
1827 }
1828
1829 if ($withpicto == 2) {
1830 if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1831 $label = $labeltype;
1832 }
1833 $labelshort = '';
1834 } else {
1835 if (getDolGlobalString('AGENDA_USE_EVENT_TYPE') && empty($label)) {
1836 $label = $labeltype;
1837 }
1838 if ($maxlength < 0) {
1839 $labelshort = $this->ref;
1840 } else {
1841 $labelshort = dol_trunc($label, $maxlength);
1842 }
1843 }
1844
1845 if ($withpicto) {
1846 if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) { // Add code into ()
1847 if ($labeltype) {
1848 $label .= (preg_match('/'.preg_quote($labeltype, '/').'/', $label) ? '' : ' ('.$langs->transnoentities("Action".$this->type_code).')');
1849 }
1850 }
1851 }
1852
1853 $result .= $linkstart;
1854 if ($withpicto) {
1855 $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);
1856 }
1857 $result .= dol_escape_htmltag($labelshort);
1858 $result .= $linkend;
1859
1860 global $action;
1861 $hookmanager->initHooks(array('actiondao'));
1862 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1863 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1864 if ($reshook > 0) {
1865 $result = $hookmanager->resPrint;
1866 } else {
1867 $result .= $hookmanager->resPrint;
1868 }
1869
1870 return $result;
1871 }
1872
1880 public function getTypePicto($morecss = 'pictofixedwidth paddingright valignmiddle', $titlealt = '')
1881 {
1882 $imgpicto = '';
1883 if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1884 $color = '';
1885 if ($this->type_color) {
1886 $color = 'style="color: #'.$this->type_color.' !important;"';
1887 }
1888 if ($this->type_picto) {
1889 $imgpicto = img_picto($titlealt, $this->type_picto, '', 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1890 } else {
1891 if ($this->type_code == 'AC_RDV') {
1892 $imgpicto = img_picto($titlealt, 'meeting', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1893 } elseif ($this->type_code == 'AC_TEL') {
1894 $imgpicto = img_picto($titlealt, 'object_phoning', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1895 } elseif ($this->type_code == 'AC_FAX') {
1896 $imgpicto = img_picto($titlealt, 'object_phoning_fax', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1897 } elseif ($this->type_code == 'AC_EMAIL' || $this->type_code == 'AC_EMAIL_IN' || $this->type_code == 'AC_EMAILING' || (!empty($this->code) && preg_match('/_SENTBYMAIL/', $this->code))) {
1898 $imgpicto = img_picto($titlealt, 'object_email', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1899 } elseif ($this->type_code == 'AC_INT') {
1900 $imgpicto = img_picto($titlealt, 'object_intervention', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1901 } elseif (!empty($this->code) && preg_match('/^TICKET_MSG/', $this->code)) {
1902 $imgpicto = img_picto($titlealt, 'object_conversation', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1903 } elseif ($this->type != 'systemauto') {
1904 $imgpicto = img_picto($titlealt, 'user-cog', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1905 } else {
1906 $imgpicto = img_picto($titlealt, 'cog', $color, 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1907 }
1908 }
1909 } else {
1910 // 2 picto: 1 for auto, 1 for manual
1911 if ($this->type != 'systemauto') {
1912 $imgpicto = img_picto($titlealt, 'user-cog', '', 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1913 } else {
1914 $imgpicto = img_picto($titlealt, 'cog', '', 0, 0, 0, '', ($morecss ? ' '.$morecss : ''));
1915 }
1916 }
1917
1918 return $imgpicto;
1919 }
1920
1921
1928 public function getTypeLabel($mode = 0)
1929 {
1930 global $conf, $langs;
1931
1932 // If cache for array of types unknown, we load it
1933 if (!empty($conf->cache['actioncommgetypelabel'])) {
1934 $arraylist = $conf->cache['actioncommgetypelabel'];
1935 } else {
1936 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php';
1937 $caction = new CActionComm($this->db);
1938 $arraylist = $caction->liste_array(1, 'code', '', (getDolGlobalString('AGENDA_USE_EVENT_TYPE') ? 0 : 1), '', 1);
1939 $conf->cache['actioncommgetypelabel'] = $arraylist;
1940 }
1941
1942 $labeltype = $this->type_code;
1943 if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE') && empty($arraylist[$labeltype])) {
1944 $labeltype = 'AC_OTH';
1945 }
1946 if (!empty($this->code) && preg_match('/^TICKET_MSG/', $this->code)) {
1947 $labeltype = $langs->trans("Message");
1948 } else {
1949 if (!empty($arraylist[$labeltype])) {
1950 $labeltype = $arraylist[$labeltype];
1951 }
1952 if ($this->type_code == 'AC_OTH_AUTO' && ($this->type_code != $this->code) && $labeltype && !empty($arraylist[$this->code])) {
1953 $labeltype .= ' - '.$arraylist[$this->code]; // Use code in priority over type_code
1954 }
1955 }
1956
1957 if ($this->type == 'systemauto' && $mode == 1) {
1958 $labeltype .= ' ('.$langs->trans("auto").')';
1959 }
1960
1961
1962 return $labeltype;
1963 }
1964
1975 public function setCategories($categories)
1976 {
1977 // Handle single category
1978 if (!is_array($categories)) {
1979 $categories = array($categories);
1980 }
1981
1982 // Get current categories
1983 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1984 $c = new Categorie($this->db);
1985 $existing = $c->containing($this->id, Categorie::TYPE_ACTIONCOMM, 'id');
1986
1987 // Diff
1988 if (is_array($existing)) {
1989 $to_del = array_diff($existing, $categories);
1990 $to_add = array_diff($categories, $existing);
1991 } else {
1992 $to_del = array(); // Nothing to delete
1993 $to_add = $categories;
1994 }
1995
1996 // Process
1997 foreach ($to_del as $del) {
1998 if ($c->fetch($del) > 0) {
1999 $c->del_type($this, Categorie::TYPE_ACTIONCOMM);
2000 }
2001 }
2002 foreach ($to_add as $add) {
2003 if ($c->fetch($add) > 0) {
2004 $c->add_type($this, Categorie::TYPE_ACTIONCOMM);
2005 }
2006 }
2007 return 1;
2008 }
2009
2010 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2022 public function build_exportfile($format, $type, $cachedelay, $filename, $filters, $exportholiday = 0)
2023 {
2024 global $hookmanager;
2025
2026 // phpcs:enable
2027 global $conf, $langs, $dolibarr_main_url_root, $mysoc;
2028
2029 require_once DOL_DOCUMENT_ROOT."/core/lib/xcal.lib.php";
2030 require_once DOL_DOCUMENT_ROOT."/core/lib/date.lib.php";
2031 require_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php";
2032
2033 dol_syslog(get_class($this)."::build_exportfile Build export file format=".$format.", type=".$type.", cachedelay=".$cachedelay.", filename=".$filename.", filters size=".count($filters), LOG_DEBUG);
2034
2035 // Check parameters
2036 if (empty($format)) {
2037 return -1;
2038 }
2039
2040 // Clean parameters
2041 if (!$filename) {
2042 $extension = 'vcs';
2043 if ($format == 'ical') {
2044 $extension = 'ics';
2045 }
2046 $filename = $format.'.'.$extension;
2047 }
2048
2049 // Create dir and define output file (definitive and temporary)
2050 $result = dol_mkdir($conf->agenda->dir_temp);
2051 $outputfile = $conf->agenda->dir_temp.'/'.$filename;
2052
2053 $result = 0;
2054
2055 $buildfile = true;
2056 $login = '';
2057 $logina = '';
2058 $logint = '';
2059 $eventorganization = '';
2060
2061 $now = dol_now();
2062
2063 if ($cachedelay) {
2064 $nowgmt = dol_now();
2065 include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2066 if (dol_filemtime($outputfile) > ($nowgmt - $cachedelay)) {
2067 dol_syslog(get_class($this)."::build_exportfile file ".$outputfile." is not older than now - cachedelay (".$nowgmt." - ".$cachedelay."). Build is canceled");
2068 $buildfile = false;
2069 }
2070 }
2071
2072 if ($buildfile) {
2073 // Build event array
2074 $eventarray = array();
2075
2076 if (!empty($filters['module']) && $filters['module'] == 'project@eventorganization') {
2077 $sql = "SELECT p.rowid as id,";
2078 $sql .= " p.date_start_event as datep,"; // Start
2079 $sql .= " p.date_end_event as datep2,"; // End
2080 $sql .= " p.datec, p.tms as datem,";
2081 $sql .= " p.title as label, '' as code, p.note_public, p.note_private, 0 as type_id,";
2082 $sql .= " p.fk_soc,";
2083 $sql .= " p.fk_user_creat as fk_user_author, p.fk_user_modif as fk_user_mod,";
2084 $sql .= " 0 as fk_user_action,";
2085 $sql .= " 0 as fk_contact, 100 as percentage,";
2086 $sql .= " 0 as fk_element, '' as elementtype,";
2087 $sql .= " 1 as priority, 0 as fulldayevent, p.location, 0 as transparency,";
2088 $sql .= " u.firstname, u.lastname, '".$this->db->escape(getDolGlobalString("MAIN_INFO_SOCIETE_MAIL"))."' as email,";
2089 $sql .= " s.nom as socname,";
2090 $sql .= " 0 as type_id, '' as type_code, '' as type_label";
2091 $sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
2092 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = p.fk_user_creat"; // Link to get author of event for export
2093 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = p.fk_soc";
2094
2095 $parameters = array('filters' => $filters);
2096 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
2097 $sql .= $hookmanager->resPrint;
2098
2099 $sql .= " WHERE p.entity IN (".getEntity('project').")";
2100
2101 foreach ($filters as $key => $value) {
2102 if ($key == 'notolderthan' && $value != '') {
2103 $sql .= " AND p.date_start_event >= '".$this->db->idate($now - ($value * 24 * 60 * 60))."'";
2104 }
2105 if ($key == 'year') {
2106 $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))."'";
2107 }
2108 if ($key == 'id') {
2109 $sql .= " AND p.id = ".(is_numeric($value) ? $value : 0);
2110 }
2111 if ($key == 'idfrom') {
2112 $sql .= " AND p.id >= ".(is_numeric($value) ? $value : 0);
2113 }
2114 if ($key == 'idto') {
2115 $sql .= " AND p.id <= ".(is_numeric($value) ? $value : 0);
2116 }
2117 if ($key == 'project') {
2118 $sql .= " AND p.rowid = ".(is_numeric($value) ? $value : 0);
2119 }
2120 if ($key == 'status') {
2121 $sql .= " AND p.fk_statut = ".((int) $value);
2122 }
2123 // TODO Add filters on event code of meetings/talks only
2124 }
2125
2126 $sql .= " ORDER by date_start_event";
2127
2128 $eventorganization = 'project';
2129 } else {
2130 $sql = "SELECT a.id,";
2131 $sql .= " a.datep,"; // Start
2132 $sql .= " a.datep2,"; // End
2133 $sql .= " a.datec, a.tms as datem,";
2134 $sql .= " a.label, a.code, '' as note_public, a.note as note_private, a.fk_action as type_id,";
2135 $sql .= " a.fk_soc,";
2136 $sql .= " a.fk_user_author, a.fk_user_mod,";
2137 $sql .= " a.fk_user_action,";
2138 $sql .= " a.fk_contact, a.percent as percentage,";
2139 $sql .= " a.fk_element, a.elementtype,";
2140 $sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
2141 $sql .= " u.firstname, u.lastname, u.email,";
2142 $sql .= " s.nom as socname,";
2143 $sql .= " c.id as type_id, c.code as type_code, c.libelle as type_label,";
2144 $sql .= " num_vote, event_paid, a.status";
2145 $sql .= " FROM (".MAIN_DB_PREFIX."c_actioncomm as c, ".MAIN_DB_PREFIX."actioncomm as a)";
2146 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author"; // Link to get author of event for export
2147 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
2148
2149 $parameters = array('filters' => $filters);
2150 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
2151 $sql .= $hookmanager->resPrint;
2152
2153 // We must filter on assignment table
2154 if (!empty($filters['logint']) && $filters['logint']) {
2155 $sql .= ", ".MAIN_DB_PREFIX."actioncomm_resources as ar";
2156 }
2157 $sql .= " WHERE a.fk_action = c.id";
2158 $sql .= " AND a.entity IN (".getEntity('agenda').")";
2159
2160 foreach ($filters as $key => $value) {
2161 if ($key == 'notolderthan' && $value != '') {
2162 $sql .= " AND a.datep >= '".$this->db->idate($now - ($value * 24 * 60 * 60))."'";
2163 }
2164 if ($key == 'year') {
2165 $sql .= " AND a.datep BETWEEN '".$this->db->idate(dol_get_first_day($value, 1))."' AND '".$this->db->idate(dol_get_last_day($value, 12))."'";
2166 }
2167 if ($key == 'id') {
2168 $sql .= " AND a.id = ".(is_numeric($value) ? $value : 0);
2169 }
2170 if ($key == 'idfrom') {
2171 $sql .= " AND a.id >= ".(is_numeric($value) ? $value : 0);
2172 }
2173 if ($key == 'idto') {
2174 $sql .= " AND a.id <= ".(is_numeric($value) ? $value : 0);
2175 }
2176 if ($key == 'project') {
2177 $sql .= " AND a.fk_project = ".(is_numeric($value) ? $value : 0);
2178 }
2179 if ($key == 'notactiontype') { // deprecated
2180 $sql .= " AND c.type <> '".$this->db->escape($value)."'";
2181 }
2182 if ($key == 'actiontype') { // 'system', 'systemauto', 'module', ...
2183 $newvalue = $value;
2184 $usenotin = 0;
2185 if (preg_match('/^!/', $newvalue)) {
2186 $newvalue = preg_replace('/^!/', '', $value);
2187 $usenotin = 1;
2188 }
2189 $arraynewvalue = explode(',', $newvalue);
2190 $newvalue = "";
2191 foreach ($arraynewvalue as $tmpval) {
2192 $newvalue .= ($newvalue ? "," : "")."'".$tmpval."'";
2193 }
2194 if ($usenotin) {
2195 $sql .= " AND c.type NOT IN (".$this->db->sanitize($newvalue, 1).")";
2196 } else {
2197 $sql .= " AND c.type IN (".$this->db->sanitize($newvalue, 1).")";
2198 }
2199 }
2200 if ($key == 'actioncode') { // 'AC_COMPANY_CREATE', 'AC_COMPANY_MODIFY', ...
2201 $newvalue = $value;
2202 $usenotin = 0;
2203 if (preg_match('/^!/', $newvalue)) {
2204 $newvalue = preg_replace('/^!/', '', $value);
2205 $usenotin = 1;
2206 }
2207 $arraynewvalue = explode(',', $newvalue);
2208 $newvalue = "";
2209 foreach ($arraynewvalue as $tmpval) {
2210 $newvalue .= ($newvalue ? "," : "")."'".$tmpval."'";
2211 }
2212 if ($usenotin) {
2213 $sql .= " AND a.code NOT IN (".$this->db->sanitize($newvalue, 1).")";
2214 } else {
2215 $sql .= " AND a.code IN (".$this->db->sanitize($newvalue, 1).")";
2216 }
2217 }
2218
2219 // We must filter on assignment table
2220 if ($key == 'logint') {
2221 $sql .= " AND ar.fk_actioncomm = a.id AND ar.element_type='user'";
2222 }
2223 if ($key == 'logina') {
2224 $logina = $value;
2225 $condition = '=';
2226 if (preg_match('/^!/', $logina)) {
2227 $logina = preg_replace('/^!/', '', $logina);
2228 $condition = '<>';
2229 }
2230 $userforfilter = new User($this->db);
2231 $result = $userforfilter->fetch(0, $logina);
2232 if ($result > 0) {
2233 $sql .= " AND a.fk_user_author ".$condition." ".$userforfilter->id;
2234 } elseif ($result < 0 || $condition == '=') {
2235 $sql .= " AND a.fk_user_author = 0";
2236 }
2237 }
2238 if ($key == 'logint') {
2239 $logint = $value;
2240 $condition = '=';
2241 if (preg_match('/^!/', $logint)) {
2242 $logint = preg_replace('/^!/', '', $logint);
2243 $condition = '<>';
2244 }
2245 $userforfilter = new User($this->db);
2246 $result = $userforfilter->fetch(0, $logint);
2247 if ($result > 0) {
2248 $sql .= " AND ar.fk_element = ".((int) $userforfilter->id);
2249 } elseif ($result < 0 || $condition == '=') {
2250 $sql .= " AND ar.fk_element = 0";
2251 }
2252 }
2253 if ($key == 'module') {
2254 if ($value == 'conforbooth@eventorganization') {
2255 $value = '@eventorganization';
2256 }
2257 $sql .= " AND c.module LIKE '%".$this->db->escape($value)."'";
2258 }
2259 if ($key == 'status') {
2260 $sql .= " AND a.status = ".((int) $value);
2261 }
2262 }
2263
2264 $sql .= " AND a.datep IS NOT NULL"; // To exclude corrupted events and avoid errors in lightning/sunbird import
2265
2266 $parameters = array('filters' => $filters);
2267 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
2268 $sql .= $hookmanager->resPrint;
2269
2270 $sql .= " ORDER by datep";
2271 }
2272
2273 if (!empty($filters['limit'])) {
2274 $sql .= $this->db->plimit((int) $filters['limit']);
2275 }
2276
2277 //print $sql;exit;
2278
2279 dol_syslog(get_class($this)."::build_exportfile select event(s)", LOG_DEBUG);
2280
2281 $resql = $this->db->query($sql);
2282 if ($resql) {
2283 $diff = 0;
2284 while ($obj = $this->db->fetch_object($resql)) {
2285 $qualified = true;
2286
2287 // 'eid','startdate','duration','enddate','title','summary','category','email','url','desc','author'
2288 $event = array();
2289 $event['uid'] = 'dolibarragenda-'.$this->db->database_name.'-'.$obj->id."@".$_SERVER["SERVER_NAME"];
2290 $event['type'] = $type;
2291
2292 $datestart = (int) $this->db->jdate($obj->datep) - (getDolGlobalInt('AGENDA_EXPORT_FIX_TZ') * 3600);
2293
2294 // fix for -> Warning: A non-numeric value encountered
2295 if (is_numeric($this->db->jdate($obj->datep2))) {
2296 $dateend = (int) $this->db->jdate($obj->datep2) - (getDolGlobalInt('AGENDA_EXPORT_FIX_TZ') * 3600);
2297 } else {
2298 // use start date as fall-back to avoid pb with empty end date on ICS readers
2299 $dateend = $datestart;
2300 }
2301
2302 $duration = ($datestart && $dateend) ? ($dateend - $datestart) : 0;
2303 $event['summary'] = $obj->label.($obj->socname ? " (".$obj->socname.")" : "");
2304
2305 if (!empty($filters['module']) && $filters['module'] == 'project@eventorganization') {
2306 $event['desc'] = $obj->note_public;
2307 } else {
2308 $event['desc'] = $obj->note_private;
2309 }
2310 $event['startdate'] = $datestart;
2311 $event['enddate'] = $dateend; // Not required with type 'journal'
2312 $event['duration'] = $duration; // Not required with type 'journal'
2313 $event['author'] = dolGetFirstLastname($obj->firstname, $obj->lastname);
2314 $event['priority'] = $obj->priority;
2315 $event['fulldayevent'] = $obj->fulldayevent;
2316 $event['location'] = $obj->location;
2317 $event['transparency'] = (($obj->transparency > 0) ? 'OPAQUE' : 'TRANSPARENT'); // OPAQUE (busy) or TRANSPARENT (not busy)
2318 $event['category'] = $obj->type_label;
2319 $event['email'] = $obj->email;
2320
2321 // Public URL of event
2322 if ($eventorganization != '') {
2323 $link_subscription = $dolibarr_main_url_root.'/public/eventorganization/attendee_new.php?id='.((int) $obj->id).'&type=global&noregistration=1';
2324 $encodedsecurekey = dol_hash(getDolGlobalString('EVENTORGANIZATION_SECUREKEY').'conferenceorbooth'.((int) $obj->id), 'md5');
2325 $link_subscription .= '&securekey='.urlencode($encodedsecurekey);
2326
2327 $event['url'] = $link_subscription;
2328 }
2329
2330 $event['created'] = (int) $this->db->jdate($obj->datec) - (getDolGlobalInt('AGENDA_EXPORT_FIX_TZ') * 3600);
2331 $event['modified'] = (int) $this->db->jdate($obj->datem) - (getDolGlobalInt('AGENDA_EXPORT_FIX_TZ') * 3600);
2332 $event['num_vote'] = $this->num_vote;
2333 $event['event_paid'] = $this->event_paid;
2334 $event['status'] = $this->status;
2335
2336 // TODO: find a way to call "$this->fetch_userassigned();" without override "$this" properties
2337 $this->id = $obj->id;
2338 $this->fetch_userassigned(false);
2339
2340 $assignedUserArray = array();
2341
2342 foreach ($this->userassigned as $key => $value) {
2343 $assignedUser = new User($this->db);
2344 $assignedUser->fetch($value['id']);
2345
2346 $assignedUserArray[$key] = $assignedUser;
2347 }
2348
2349 if ($filters['module'] != 'project@eventorganization') {
2350 $event['assignedUsers'] = $assignedUserArray;
2351 }
2352
2353 if ($qualified && $datestart) {
2354 $eventarray[] = $event;
2355 }
2356 $diff++;
2357 }
2358
2359 $parameters = array('filters' => $filters, 'eventarray' => &$eventarray);
2360 $reshook = $hookmanager->executeHooks('addMoreEventsExport', $parameters); // Note that $action and $object may have been modified by hook
2361 if ($reshook > 0) {
2362 $eventarray = $hookmanager->resArray;
2363 }
2364 } else {
2365 $this->error = $this->db->lasterror();
2366 return -1;
2367 }
2368
2369 if ($exportholiday == 1) {
2370 $langs->load("holiday");
2371 $title = $langs->transnoentities("Holidays");
2372
2373 $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";
2374 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as x, ".MAIN_DB_PREFIX."user as u";
2375 $sql .= " WHERE u.rowid = x.fk_user";
2376 $sql .= " AND u.statut = '1'"; // Show only active users (0 = inactive user, 1 = active user)
2377 $sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
2378
2379 $resql = $this->db->query($sql);
2380 if ($resql) {
2381 $num = $this->db->num_rows($resql);
2382 $i = 0;
2383
2384 while ($i < $num) {
2385 $obj = $this->db->fetch_object($resql);
2386 $event = array();
2387
2388 if ($obj->halfday == 1) {
2389 $event['fulldayevent'] = false;
2390
2391 $timestampStart = dol_stringtotime($obj->date_start." 00:00:00", 0);
2392 $timestampEnd = dol_stringtotime($obj->date_end." 12:00:00", 0);
2393 } elseif ($obj->halfday == -1) {
2394 $event['fulldayevent'] = false;
2395
2396 $timestampStart = dol_stringtotime($obj->date_start." 12:00:00", 0);
2397 $timestampEnd = dol_stringtotime($obj->date_end." 23:59:59", 0);
2398 } else {
2399 $event['fulldayevent'] = true;
2400
2401 $timestampStart = dol_stringtotime($obj->date_start." 00:00:00", 0);
2402 $timestampEnd = dol_stringtotime($obj->date_end." 23:59:59", 0);
2403 }
2404
2405 if (getDolGlobalString('AGENDA_EXPORT_FIX_TZ')) {
2406 $timestampStart -= ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
2407 $timestampEnd -= ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
2408 }
2409
2410 $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
2411 $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT;
2412 $url = $urlwithroot.'/holiday/card.php?id='.$obj->rowid;
2413
2414 $event['uid'] = 'dolibarrholiday-'.$this->db->database_name.'-'.$obj->rowid."@".$_SERVER["SERVER_NAME"];
2415 $event['author'] = dolGetFirstLastname($obj->firstname, $obj->lastname);
2416 $event['type'] = 'event';
2417 $event['category'] = "Holiday";
2418 $event['transparency'] = 'OPAQUE';
2419 $event['email'] = $obj->email;
2420 $event['created'] = $timestampStart;
2421 $event['modified'] = $timestampStart;
2422 $event['startdate'] = $timestampStart;
2423 $event['enddate'] = $timestampEnd;
2424 $event['duration'] = $timestampEnd - $timestampStart;
2425 $event['url'] = $url;
2426
2427 if ($obj->status == 2) {
2428 // 2 = leave wait for approval
2429 $event['summary'] = $title." - ".$obj->lastname." (wait for approval)";
2430 } else {
2431 // 3 = leave approved
2432 $event['summary'] = $title." - ".$obj->lastname;
2433 }
2434
2435 $eventarray[] = $event;
2436
2437 $i++;
2438 }
2439 }
2440 }
2441
2442 $langs->load("agenda");
2443
2444 // Define title and desc
2445 $title = '';
2446 $more = '';
2447 if ($login) {
2448 $more = $langs->transnoentities("User").' '.$login;
2449 }
2450 if ($logina) {
2451 $more = $langs->transnoentities("ActionsAskedBy").' '.$logina;
2452 }
2453 if ($logint) {
2454 $more = $langs->transnoentities("ActionsToDoBy").' '.$logint;
2455 }
2456 if ($eventorganization) {
2457 $langs->load("eventorganization");
2458 $title = $langs->transnoentities("OrganizedEvent").(empty($eventarray[0]['label']) ? '' : ' '.$eventarray[0]['label']);
2459 $more = 'ICS file - '.$langs->transnoentities("OrganizedEvent").(empty($eventarray[0]['label']) ? '' : ' '.$eventarray[0]['label']);
2460 }
2461 if ($more) {
2462 if (empty($title)) {
2463 $title = 'Dolibarr actions '.$mysoc->name.' - '.$more;
2464 }
2465 $desc = $more;
2466 $desc .= ' ('.$mysoc->name.' - built by Dolibarr)';
2467 } else {
2468 if (empty($title)) {
2469 $title = 'Dolibarr actions '.$mysoc->name;
2470 }
2471 $desc = $langs->transnoentities('ListOfActions');
2472 $desc .= ' ('.$mysoc->name.' - built by Dolibarr)';
2473 }
2474
2475 // Create temp file
2476 $outputfiletmp = tempnam($conf->agenda->dir_temp, 'tmp'); // Temporary file (allow call of function by different threads
2477 dolChmod($outputfiletmp);
2478
2479 // Write file
2480 if ($format == 'vcal') {
2481 $result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
2482 } elseif ($format == 'ical') {
2483 $result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
2484 } elseif ($format == 'rss') {
2485 $result = build_rssfile($format, $title, $desc, $eventarray, $outputfiletmp);
2486 }
2487
2488 if ($result >= 0) {
2489 if (dol_move($outputfiletmp, $outputfile, '0', 1, 0, 0)) {
2490 $result = 1;
2491 } else {
2492 $this->error = 'Failed to rename '.$outputfiletmp.' into '.$outputfile;
2493 dol_syslog(get_class($this)."::build_exportfile ".$this->error, LOG_ERR);
2494 dol_delete_file($outputfiletmp, 0, 1);
2495 $result = -1;
2496 }
2497 } else {
2498 dol_syslog(get_class($this)."::build_exportfile build_xxxfile function fails to for format=".$format." outputfiletmp=".$outputfile, LOG_ERR);
2499 dol_delete_file($outputfiletmp, 0, 1);
2500 $langs->load("errors");
2501 $this->error = $langs->trans("ErrorFailToCreateFile", $outputfile);
2502 }
2503 }
2504
2505 return $result;
2506 }
2507
2515 public function initAsSpecimen()
2516 {
2517 global $user;
2518
2519 $now = dol_now();
2520
2521 // Initialise parameters
2522 $this->id = 0;
2523 $this->specimen = 1;
2524
2525 $this->type_code = 'AC_OTH';
2526 $this->code = 'AC_SPECIMEN_CODE';
2527 $this->label = 'Label of event Specimen';
2528 $this->datec = $now;
2529 $this->datem = $now;
2530 $this->datep = $now;
2531 $this->datef = $now;
2532 $this->fulldayevent = 0;
2533 $this->percentage = 0;
2534 $this->status = 0;
2535 $this->location = 'Location';
2536 $this->transparency = 1; // 1 means opaque
2537 $this->priority = 1;
2538 //$this->note_public = "This is a 'public' note.";
2539 $this->note_private = "This is a 'private' note.";
2540
2541 $this->userownerid = $user->id;
2542 $this->userassigned[$user->id] = array('id' => $user->id, 'transparency' => 1);
2543 return 1;
2544 }
2545
2554 public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
2555 {
2556 $tables = array(
2557 'actioncomm'
2558 );
2559
2560 return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
2561 }
2562
2571 public static function replaceProduct(DoliDB $dbs, $origin_id, $dest_id)
2572 {
2573 $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'actioncomm SET fk_element = ' . ((int) $dest_id) . ' WHERE elementtype="product" AND fk_element = '.((int) $origin_id);
2574 // using $dbs, not $this->db because function is static
2575 if (!$dbs->query($sql)) {
2576 //$this->errors = $dbs->lasterror();
2577 return false;
2578 }
2579
2580 return true;
2581 }
2582
2588 public function hasDelay()
2589 {
2590 global $conf;
2591
2592 $now = dol_now();
2593
2594 return $this->datep && ($this->datep < ($now - $conf->agenda->warning_delay));
2595 }
2596
2597
2606 public function loadReminders($type = '', $fk_user = 0, $onlypast = true)
2607 {
2608 global $conf, $langs, $user;
2609
2610 $error = 0;
2611
2612 $this->reminders = array();
2613
2614 //Select all action comm reminders for event
2615 $sql = "SELECT rowid as id, typeremind, dateremind, status, offsetvalue, offsetunit, fk_user, fk_email_template, lasterror";
2616 $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2617 $sql .= " WHERE fk_actioncomm = ".((int) $this->id);
2618 if ($onlypast) {
2619 $sql .= " AND dateremind <= '".$this->db->idate(dol_now())."'";
2620 }
2621 if ($type) {
2622 $sql .= " AND typeremind = '".$this->db->escape($type)."'";
2623 }
2624 if ($fk_user > 0) {
2625 $sql .= " AND fk_user = ".((int) $fk_user);
2626 }
2627 if (!getDolGlobalString('AGENDA_REMINDER_EMAIL')) {
2628 $sql .= " AND typeremind <> 'email'";
2629 }
2630 if (!getDolGlobalString('AGENDA_REMINDER_BROWSER')) {
2631 $sql .= " AND typeremind <> 'browser'";
2632 }
2633
2634 $sql .= $this->db->order("dateremind", "ASC");
2635 $resql = $this->db->query($sql);
2636
2637 if ($resql) {
2638 while ($obj = $this->db->fetch_object($resql)) {
2639 $tmpactioncommreminder = new ActionCommReminder($this->db);
2640 $tmpactioncommreminder->id = $obj->id;
2641 $tmpactioncommreminder->typeremind = $obj->typeremind;
2642 $tmpactioncommreminder->dateremind = $obj->dateremind;
2643 $tmpactioncommreminder->offsetvalue = $obj->offsetvalue;
2644 $tmpactioncommreminder->offsetunit = $obj->offsetunit;
2645 $tmpactioncommreminder->status = $obj->status;
2646 $tmpactioncommreminder->fk_user = $obj->fk_user;
2647 $tmpactioncommreminder->fk_email_template = $obj->fk_email_template;
2648 $tmpactioncommreminder->lasterror = $obj->lasterror;
2649
2650 $this->reminders[$obj->id] = $tmpactioncommreminder;
2651 }
2652 } else {
2653 $this->error = $this->db->lasterror();
2654 $error++;
2655 }
2656
2657 return count($this->reminders);
2658 }
2659
2660
2667 public function sendEmailsReminder()
2668 {
2669 global $conf, $langs, $user;
2670
2671 $error = 0;
2672 $this->output = '';
2673 $this->error = '';
2674 $nbMailSend = 0;
2675 $errorsMsg = array();
2676
2677 if (!isModEnabled('agenda')) { // Should not happen. If module disabled, cron job should not be visible.
2678 $langs->load("agenda");
2679 $this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2680 return 0;
2681 }
2682 if (!getDolGlobalString('AGENDA_REMINDER_EMAIL')) {
2683 $langs->load("agenda");
2684 $this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2685 return 0;
2686 }
2687
2688 $now = dol_now();
2689 $actionCommReminder = new ActionCommReminder($this->db);
2690
2691 dol_syslog(__METHOD__." start", LOG_INFO);
2692
2693 $this->db->begin();
2694
2695 //Select all action comm reminders
2696 $sql = "SELECT rowid as id FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2697 $sql .= " WHERE typeremind = 'email'";
2698 $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.
2699 $sql .= " AND dateremind <= '".$this->db->idate($now)."'";
2700 $sql .= " AND entity IN (".getEntity('actioncomm').")";
2701 $sql .= $this->db->order("dateremind", "ASC");
2702 $resql = $this->db->query($sql);
2703
2704 if ($resql) {
2705 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2706 $formmail = new FormMail($this->db);
2707 $to = null; // Ensure 'to' is defined for static analysis
2708
2709 while ($obj = $this->db->fetch_object($resql)) {
2710 $res = $actionCommReminder->fetch($obj->id);
2711 if ($res < 0) {
2712 $error++;
2713 $errorsMsg[] = "Failed to load invoice ActionComm Reminder";
2714 }
2715
2716 if (!$error) {
2717 //Select email template
2718 $arraymessage = $formmail->getEMailTemplate($this->db, 'actioncomm_send', $user, $langs, (!empty($actionCommReminder->fk_email_template)) ? $actionCommReminder->fk_email_template : -1, 1);
2719
2720 // Load event
2721 $res = $this->fetch($actionCommReminder->fk_actioncomm);
2722 if ($res > 0) {
2723 $res2 = $this->fetch_thirdparty();
2724 if ($res2 >= 0) {
2725 // PREPARE EMAIL
2726 $errormesg = '';
2727
2728 // Make substitution in email content
2729 $substitutionarray = getCommonSubstitutionArray($langs, 0, null, $this);
2730
2731 complete_substitutions_array($substitutionarray, $langs, $this);
2732
2733 // Content
2734 $sendContent = make_substitutions($langs->trans($arraymessage->content), $substitutionarray);
2735
2736 //Topic
2737 $sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->transnoentities('EventReminder'));
2738
2739 // Recipient
2740 $recipient = new User($this->db);
2741 $res = $recipient->fetch($actionCommReminder->fk_user);
2742 if ($res > 0) {
2743 if (!empty($recipient->email)) {
2744 $to = $recipient->email;
2745 } else {
2746 $errormesg = "Failed to send remind to user id=".$actionCommReminder->fk_user.". No email defined for user.";
2747 $error++;
2748 }
2749 } else {
2750 $errormesg = "Failed to load recipient with user id=".$actionCommReminder->fk_user;
2751 $error++;
2752 }
2753
2754 // Sender
2755 $from = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
2756 if (empty($from)) {
2757 $errormesg = "Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
2758 $error++;
2759 }
2760
2761 if (!$error) {
2762 // Errors Recipient
2763 $errors_to = getDolGlobalString('MAIN_MAIL_ERRORS_TO');
2764
2765 // Mail Creation
2766 $cMailFile = new CMailFile($sendTopic, $to, $from, $sendContent, array(), array(), array(), '', "", 0, 1, $errors_to, '', '', '', '', '');
2767
2768 // Sending Mail
2769 if ($cMailFile->sendfile()) {
2770 $nbMailSend++;
2771 } else {
2772 $errormesg = 'Failed to send email to: '.$to.' '.$cMailFile->error.implode(',', $cMailFile->errors);
2773 $error++;
2774 }
2775 }
2776
2777 if (!$error) {
2778 $actionCommReminder->status = $actionCommReminder::STATUS_DONE;
2779
2780 $res = $actionCommReminder->update($user);
2781 if ($res < 0) {
2782 $errorsMsg[] = "Failed to update status to done of ActionComm Reminder";
2783 $error++;
2784 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.
2785 }
2786 } else {
2787 $actionCommReminder->status = $actionCommReminder::STATUS_ERROR;
2788 $actionCommReminder->lasterror = dol_trunc($errormesg, 128, 'right', 'UTF-8', 1);
2789
2790 $res = $actionCommReminder->update($user);
2791 if ($res < 0) {
2792 $errorsMsg[] = "Failed to update status to error of ActionComm Reminder";
2793 $error++;
2794 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.
2795 } else {
2796 $errorsMsg[] = $errormesg;
2797 }
2798 }
2799 } else {
2800 $errorsMsg[] = 'Failed to fetch record thirdparty on actioncomm with ID = '.$actionCommReminder->fk_actioncomm;
2801 $error++;
2802 }
2803 } else {
2804 $errorsMsg[] = 'Failed to fetch record actioncomm with ID = '.$actionCommReminder->fk_actioncomm;
2805 $error++;
2806 }
2807 }
2808 }
2809 } else {
2810 $error++;
2811 }
2812
2813 if (!$error) {
2814 // Delete also very old past events (we do not keep more than 1 month record in past)
2815 $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2816 $sql .= " WHERE dateremind < '".$this->db->idate($now - (3600 * 24 * 32))."'";
2817 $sql .= " AND status = ".((int) $actionCommReminder::STATUS_DONE);
2818 $resql = $this->db->query($sql);
2819
2820 if (!$resql) {
2821 $errorsMsg[] = 'Failed to delete old reminders';
2822 //$error++; // If this fails, we must not rollback other SQL requests already done. Never mind.
2823 }
2824 }
2825
2826 if (!$error) {
2827 $this->output = 'Nb of emails sent : '.$nbMailSend;
2828 $this->db->commit();
2829
2830 dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO);
2831
2832 return 0;
2833 } else {
2834 $this->db->commit(); // We commit also on error, to have the error message recorded.
2835 $this->error = 'Nb of emails sent : '.$nbMailSend.', '.(!empty($errorsMsg) ? implode(', ', $errorsMsg) : $error);
2836
2837 dol_syslog(__METHOD__." end - ".$this->error, LOG_INFO);
2838
2839 return $error;
2840 }
2841 }
2842
2851 public function updatePercent($id, $percent, $usermodid = 0)
2852 {
2853 $this->db->begin();
2854
2855 $sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm ";
2856 $sql .= " SET percent = ".(int) $percent;
2857 if ($usermodid > 0) {
2858 $sql .= ", fk_user_mod = ".$usermodid;
2859 }
2860 $sql .= " WHERE id = ".((int) $id);
2861
2862 if ($this->db->query($sql)) {
2863 $this->db->commit();
2864 return 1;
2865 } else {
2866 $this->db->rollback();
2867 $this->error = $this->db->lasterror();
2868 return -1;
2869 }
2870 }
2871}
$id
Definition account.php:48
$c
Definition line.php:327
$object ref
Definition info.php:89
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:171
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:600
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:431
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:619
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_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
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...
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
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.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:150
dol_hash($chain, $type='0', $nosalt=0, $mode=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:36
build_rssfile($format, $title, $desc, $events_array, $outputfile, $filter='', $url='', $langcode='')
Build a file from an array of events.
Definition xcal.lib.php:326