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