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