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