dolibarr  9.0.0
actioncomm.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2002-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
7  * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
8  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
29 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
31 
32 
36 class ActionComm extends CommonObject
37 {
41  public $element='action';
42 
46  public $table_element = 'actioncomm';
47 
48  public $table_rowid = 'id';
49 
53  public $picto = 'action';
54 
59  public $ismultientitymanaged = 1;
60 
65  public $restrictiononfksoc = 2;
66 
71  public $id;
72 
77  public $ref;
78 
79  public $type_id; // Id into parent table llx_c_actioncomm (used only if option to use type is set)
80  public $type_code; // Code into parent table llx_c_actioncomm (used only if option to use type is set). With default setup, should be AC_OTH_AUTO or AC_OTH.
81  public $type_label;
82  public $type; // Label into parent table llx_c_actioncomm (used only if option to use type is set)
83  public $type_color; // Color into parent table llx_c_actioncomm (used only if option to use type is set)
84  public $code; // Free code to identify action. Ie: Agenda trigger add here AC_TRIGGERNAME ('AC_COMPANY_CREATE', 'AC_PROPAL_VALIDATE', ...)
85 
89  public $label;
90 
91  public $datec; // Date creation record (datec)
92  public $datem; // Date modification record (tms)
93 
100  public $author;
101 
108  public $usermod;
109 
114  public $authorid;
115 
120  public $usermodid;
121 
122  public $datep; // Date action start (datep)
123  public $datef; // Date action end (datep2)
124 
129  public $durationp = -1;
130  public $fulldayevent = 0; // 1=Event on full day
131 
137  public $punctual = 1;
138  public $percentage; // Percentage
139  public $location; // Location
140 
141  public $transparency; // Transparency (ical standard). Used to say if people assigned to event are busy or not by event. 0=available, 1=busy, 2=busy (refused events)
142  public $priority; // Small int (0 By default)
143 
144  public $userassigned = array(); // Array of user ids
145  public $userownerid; // Id of user owner = fk_user_action into table
146  public $userdoneid; // Id of user done (deprecated)
147 
148  public $socpeopleassigned = array(); // Array of contact ids
149 
150  public $otherassigned = array(); // Array of other contact emails (not user, not contact)
151 
152 
159  public $usertodo;
160 
167  public $userdone;
168 
169  public $socid;
170  public $contactid;
171 
178  public $societe;
179 
186  public $contact;
187 
188  // Properties for links to other objects
189  public $fk_element; // Id of record
190  public $elementid; // Id of record alternative for API
191  public $elementtype; // Type of record. This if property ->element of object linked to.
192 
193  // Ical
194  public $icalname;
195  public $icalcolor;
196 
197  public $actions=array();
198 
199  // Fields for emails
200  public $email_msgid;
201  public $email_from;
202  public $email_sender;
203  public $email_to;
204  public $email_tocc;
205  public $email_tobcc;
206  public $email_subject;
207  public $errors_to;
208 
209 
215  public function __construct(DoliDB $db)
216  {
217  $this->db = $db;
218 
219  $this->societe = new stdClass(); // deprecated
220  $this->contact = new stdClass(); // deprecated
221  }
222 
231  public function create(User $user, $notrigger = 0)
232  {
233  global $langs,$conf,$hookmanager;
234 
235  $error=0;
236  $now=dol_now();
237 
238  // Check parameters
239  if (! isset($this->userownerid) || $this->userownerid === '') // $this->userownerid may be 0 (anonymous event) of > 0
240  {
241  dol_syslog("You tried to create an event but mandatory property ownerid was not defined", LOG_WARNING);
242  $this->errors[]='ErrorPropertyUserowneridNotDefined';
243  return -1;
244  }
245 
246  // Clean parameters
247  $this->label=dol_trunc(trim($this->label),128);
248  $this->location=dol_trunc(trim($this->location),128);
249  $this->note=dol_htmlcleanlastbr(trim($this->note));
250  if (empty($this->percentage)) $this->percentage = 0;
251  if (empty($this->priority) || ! is_numeric($this->priority)) $this->priority = 0;
252  if (empty($this->fulldayevent)) $this->fulldayevent = 0;
253  if (empty($this->punctual)) $this->punctual = 0;
254  if (empty($this->transparency)) $this->transparency = 0;
255  if ($this->percentage > 100) $this->percentage = 100;
256  //if ($this->percentage == 100 && ! $this->dateend) $this->dateend = $this->date;
257  if (! empty($this->datep) && ! empty($this->datef)) $this->durationp=($this->datef - $this->datep); // deprecated
258  //if (! empty($this->date) && ! empty($this->dateend)) $this->durationa=($this->dateend - $this->date);
259  if (! empty($this->datep) && ! empty($this->datef) && $this->datep > $this->datef) $this->datef=$this->datep;
260  //if (! empty($this->date) && ! empty($this->dateend) && $this->date > $this->dateend) $this->dateend=$this->date;
261  if (! isset($this->fk_project) || $this->fk_project < 0) $this->fk_project = 0;
262  if ($this->elementtype=='facture') $this->elementtype='invoice';
263  if ($this->elementtype=='commande') $this->elementtype='order';
264  if ($this->elementtype=='contrat') $this->elementtype='contract';
265 
266  if (! is_array($this->userassigned) && ! empty($this->userassigned)) // For backward compatibility when userassigned was an int instead fo array
267  {
268  $tmpid=$this->userassigned;
269  $this->userassigned=array();
270  $this->userassigned[$tmpid]=array('id'=>$tmpid, 'transparency'=>$this->transparency);
271  }
272 
273  if (is_object($this->contact) && isset($this->contact->id) && $this->contact->id > 0 && ! ($this->contactid > 0)) $this->contactid = $this->contact->id; // For backward compatibility. Using this->contact->xx is deprecated
274 
275 
276  $userownerid=$this->userownerid;
277  $userdoneid=$this->userdoneid;
278 
279  // Be sure assigned user is defined as an array of array('id'=>,'mandatory'=>,...).
280  if (empty($this->userassigned) || count($this->userassigned) == 0 || ! is_array($this->userassigned))
281  $this->userassigned = array($userownerid=>array('id'=>$userownerid, 'transparency'=>$this->transparency));
282 
283  if (! $this->type_id || ! $this->type_code)
284  {
285  $key=empty($this->type_id)?$this->type_code:$this->type_id;
286 
287  // Get id from code
288  $cactioncomm=new CActionComm($this->db);
289  $result=$cactioncomm->fetch($key);
290 
291  if ($result > 0)
292  {
293  $this->type_id=$cactioncomm->id;
294  $this->type_code=$cactioncomm->code;
295  }
296  else if ($result == 0)
297  {
298  $this->error='Failed to get record with id '.$this->type_id.' code '.$this->type_code.' from dictionary "type of events"';
299  return -1;
300  }
301  else
302  {
303  $this->error=$cactioncomm->error;
304  return -1;
305  }
306  }
307  $code = empty($this->code)?$this->type_code:$this->code;
308 
309  // Check parameters
310  if (! $this->type_id)
311  {
312  $this->error="ErrorWrongParameters";
313  return -1;
314  }
315 
316  $this->db->begin();
317 
318  $sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm";
319  $sql.= "(datec,";
320  $sql.= "datep,";
321  $sql.= "datep2,";
322  $sql.= "durationp,"; // deprecated
323  $sql.= "fk_action,";
324  $sql.= "code,";
325  $sql.= "fk_soc,";
326  $sql.= "fk_project,";
327  $sql.= "note,";
328  $sql.= "fk_contact,";
329  $sql.= "fk_user_author,";
330  $sql.= "fk_user_action,";
331  $sql.= "fk_user_done,";
332  $sql.= "label,percent,priority,fulldayevent,location,punctual,";
333  $sql.= "transparency,";
334  $sql.= "fk_element,";
335  $sql.= "elementtype,";
336  $sql.= "entity,";
337  $sql.= "extraparams,";
338  // Fields emails
339  $sql.= "email_msgid,";
340  $sql.= "email_from,";
341  $sql.= "email_sender,";
342  $sql.= "email_to,";
343  $sql.= "email_tocc,";
344  $sql.= "email_tobcc,";
345  $sql.= "email_subject,";
346  $sql.= "errors_to";
347  $sql.= ") VALUES (";
348  $sql.= "'".$this->db->idate($now)."', ";
349  $sql.= (strval($this->datep)!=''?"'".$this->db->idate($this->datep)."'":"null").", ";
350  $sql.= (strval($this->datef)!=''?"'".$this->db->idate($this->datef)."'":"null").", ";
351  $sql.= ((isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '')?"'".$this->db->escape($this->durationp)."'":"null").", "; // deprecated
352  $sql.= (isset($this->type_id)?$this->type_id:"null").",";
353  $sql.= ($code?("'".$code."'"):"null").", ";
354  $sql.= ((isset($this->socid) && $this->socid > 0) ? $this->socid:"null").", ";
355  $sql.= ((isset($this->fk_project) && $this->fk_project > 0) ? $this->fk_project:"null").", ";
356  $sql.= " '".$this->db->escape($this->note_private?$this->note_private:$this->note)."', ";
357  $sql.= ((isset($this->contactid) && $this->contactid > 0) ? $this->contactid:"null").", ";
358  $sql.= (isset($user->id) && $user->id > 0 ? $user->id:"null").", ";
359  $sql.= ($userownerid>0 ? $userownerid:"null").", ";
360  $sql.= ($userdoneid>0 ? $userdoneid:"null").", ";
361  $sql.= "'".$this->db->escape($this->label)."','".$this->db->escape($this->percentage)."','".$this->db->escape($this->priority)."','".$this->db->escape($this->fulldayevent)."','".$this->db->escape($this->location)."','".$this->db->escape($this->punctual)."', ";
362  $sql.= "'".$this->db->escape($this->transparency)."', ";
363  $sql.= (! empty($this->fk_element)?$this->fk_element:"null").", ";
364  $sql.= (! empty($this->elementtype)?"'".$this->db->escape($this->elementtype)."'":"null").", ";
365  $sql.= $conf->entity.",";
366  $sql.= (! empty($this->extraparams)?"'".$this->db->escape($this->extraparams)."'":"null").", ";
367  // Fields emails
368  $sql.= (! empty($this->email_msgid)?"'".$this->db->escape($this->email_msgid)."'":"null").", ";
369  $sql.= (! empty($this->email_from)?"'".$this->db->escape($this->email_from)."'":"null").", ";
370  $sql.= (! empty($this->email_sender)?"'".$this->db->escape($this->email_sender)."'":"null").", ";
371  $sql.= (! empty($this->email_to)?"'".$this->db->escape($this->email_to)."'":"null").", ";
372  $sql.= (! empty($this->email_tocc)?"'".$this->db->escape($this->email_tocc)."'":"null").", ";
373  $sql.= (! empty($this->email_tobcc)?"'".$this->db->escape($this->email_tobcc)."'":"null").", ";
374  $sql.= (! empty($this->email_subject)?"'".$this->db->escape($this->email_subject)."'":"null").", ";
375  $sql.= (! empty($this->errors_to)?"'".$this->db->escape($this->errors_to)."'":"null");
376  $sql.= ")";
377 
378  dol_syslog(get_class($this)."::add", LOG_DEBUG);
379  $resql=$this->db->query($sql);
380  if ($resql)
381  {
382  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."actioncomm","id");
383 
384  // Now insert assignedusers
385  if (! $error)
386  {
387  foreach($this->userassigned as $key => $val)
388  {
389  if (! is_array($val)) // For backward compatibility when val=id
390  {
391  $val=array('id'=>$val);
392  }
393 
394  $sql ="INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
395  $sql.=" VALUES(".$this->id.", 'user', ".$val['id'].", ".(empty($val['mandatory'])?'0':$val['mandatory']).", ".(empty($val['transparency'])?'0':$val['transparency']).", ".(empty($val['answer_status'])?'0':$val['answer_status']).")";
396 
397  $resql = $this->db->query($sql);
398  if (! $resql)
399  {
400  $error++;
401  $this->errors[]=$this->db->lasterror();
402  }
403  //var_dump($sql);exit;
404  }
405  }
406 
407  if (!$error)
408  {
409  if (!empty($this->socpeopleassigned))
410  {
411  foreach ($this->socpeopleassigned as $id => $Tab)
412  {
413  $sql ="INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
414  $sql.=" VALUES(".$this->id.", 'socpeople', ".$id.", 0, 0, 0)";
415 
416  $resql = $this->db->query($sql);
417  if (! $resql)
418  {
419  $error++;
420  $this->errors[]=$this->db->lasterror();
421  }
422  }
423  }
424  }
425 
426  if (! $error)
427  {
428  $action='create';
429 
430  // Actions on extra fields
431  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
432  {
433  $result=$this->insertExtraFields();
434  if ($result < 0)
435  {
436  $error++;
437  }
438  }
439  }
440 
441  if (! $error && ! $notrigger)
442  {
443  // Call trigger
444  $result=$this->call_trigger('ACTION_CREATE',$user);
445  if ($result < 0) { $error++; }
446  // End call triggers
447  }
448 
449  if (! $error)
450  {
451  $this->db->commit();
452  return $this->id;
453  }
454  else
455  {
456  $this->db->rollback();
457  return -1;
458  }
459  }
460  else
461  {
462  $this->db->rollback();
463  $this->error=$this->db->lasterror();
464  return -1;
465  }
466  }
467 
477  public function add(User $user, $notrigger = 0)
478  {
479  return $this->create($user, $notrigger);
480  }
481 
489  function createFromClone($fuser, $socid)
490  {
491  global $db, $user, $langs, $conf, $hookmanager;
492 
493  $error=0;
494  $now=dol_now();
495 
496  $this->db->begin();
497 
498  // Load source object
499  $objFrom = clone $this;
500 
501  // Retreive all extrafield
502  // fetch optionals attributes and labels
503  $this->fetch_optionals();
504 
505 // $this->fetch_userassigned();
506  $this->fetchResources();
507 
508  $this->id=0;
509 
510  if (!is_object($fuser))
511  {
512  if ($fuser > 0)
513  {
514  $u = new User($db);
515  $u->fetch($fuser);
516  $fuser = $u;
517  }
518  else
519  {
520  $fuser = $user;
521  }
522  }
523 
524  // Create clone
525  $this->context['createfromclone']='createfromclone';
526  $result=$this->create($fuser);
527  if ($result < 0) $error++;
528 
529  if (! $error)
530  {
531  // Hook of thirdparty module
532  if (is_object($hookmanager))
533  {
534  $parameters=array('objFrom'=>$objFrom);
535  $action='';
536  $reshook=$hookmanager->executeHooks('createFrom',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
537  if ($reshook < 0) $error++;
538  }
539 
540  // Call trigger
541  $result=$this->call_trigger('ACTION_CLONE', $fuser);
542  if ($result < 0) { $error++; }
543  // End call triggers
544  }
545 
546  unset($this->context['createfromclone']);
547 
548  // End
549  if (! $error)
550  {
551  $this->db->commit();
552  return $this->id;
553  }
554  else
555  {
556  $this->db->rollback();
557  return -1;
558  }
559  }
560 
569  function fetch($id, $ref='',$ref_ext='')
570  {
571  global $langs;
572 
573  $sql = "SELECT a.id,";
574  $sql.= " a.id as ref,";
575  $sql.= " a.ref_ext,";
576  $sql.= " a.datep,";
577  $sql.= " a.datep2,";
578  $sql.= " a.durationp,"; // deprecated
579  $sql.= " a.datec,";
580  $sql.= " a.tms as datem,";
581  $sql.= " a.code, a.label, a.note,";
582  $sql.= " a.fk_soc,";
583  $sql.= " a.fk_project,";
584  $sql.= " a.fk_user_author, a.fk_user_mod,";
585  $sql.= " a.fk_user_action, a.fk_user_done,";
586  $sql.= " a.fk_contact, a.percent as percentage,";
587  $sql.= " a.fk_element as elementid, a.elementtype,";
588  $sql.= " a.priority, a.fulldayevent, a.location, a.punctual, a.transparency,";
589  $sql.= " c.id as type_id, c.code as type_code, c.libelle as type_label, c.color as type_color, c.picto as type_picto,";
590  $sql.= " s.nom as socname,";
591  $sql.= " u.firstname, u.lastname as lastname";
592  $sql.= " FROM ".MAIN_DB_PREFIX."actioncomm as a ";
593  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action=c.id ";
594  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author";
595  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
596  $sql.= " WHERE ";
597  if ($ref) $sql.= " a.id=".$ref; // No field ref, we use id
598  elseif ($ref_ext) $sql.= " a.ref_ext='".$this->db->escape($ref_ext)."'";
599  else $sql.= " a.id=".$id;
600 
601  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
602  $resql=$this->db->query($sql);
603  if ($resql)
604  {
605  $num=$this->db->num_rows($resql);
606  if ($num)
607  {
608  $obj = $this->db->fetch_object($resql);
609 
610  $this->id = $obj->id;
611  $this->ref = $obj->ref;
612  $this->ref_ext = $obj->ref_ext;
613 
614  // Properties of parent table llx_c_actioncomm
615  $this->type_id = $obj->type_id;
616  $this->type_code = $obj->type_code;
617  $this->type_color = $obj->type_color;
618  $this->type_picto = $obj->type_picto;
619  $transcode=$langs->trans("Action".$obj->type_code);
620  $this->type = (($transcode!="Action".$obj->type_code) ? $transcode : $obj->type_label);
621  $transcode=$langs->trans("Action".$obj->type_code.'Short');
622  $this->type_short = (($transcode!="Action".$obj->type_code.'Short') ? $transcode : '');
623 
624  $this->code = $obj->code;
625  $this->label = $obj->label;
626  $this->datep = $this->db->jdate($obj->datep);
627  $this->datef = $this->db->jdate($obj->datep2);
628 
629  $this->datec = $this->db->jdate($obj->datec);
630  $this->datem = $this->db->jdate($obj->datem);
631 
632  $this->note = $obj->note;
633  $this->note_private = $obj->note;
634  $this->percentage = $obj->percentage;
635 
636  $this->authorid = $obj->fk_user_author;
637  $this->usermodid = $obj->fk_user_mod;
638 
639  if (!is_object($this->author)) $this->author = new stdClass(); // To avoid warning
640  $this->author->id = $obj->fk_user_author; // deprecated
641  $this->author->firstname = $obj->firstname; // deprecated
642  $this->author->lastname = $obj->lastname; // deprecated
643  if (!is_object($this->usermod)) $this->usermod = new stdClass(); // To avoid warning
644  $this->usermod->id = $obj->fk_user_mod; // deprecated
645 
646  $this->userownerid = $obj->fk_user_action;
647  $this->userdoneid = $obj->fk_user_done;
648  $this->priority = $obj->priority;
649  $this->fulldayevent = $obj->fulldayevent;
650  $this->location = $obj->location;
651  $this->transparency = $obj->transparency;
652  $this->punctual = $obj->punctual; // deprecated
653 
654  $this->socid = $obj->fk_soc; // To have fetch_thirdparty method working
655  $this->contactid = $obj->fk_contact; // To have fetch_contact method working
656  $this->fk_project = $obj->fk_project; // To have fetch_project method working
657 
658  $this->societe->id = $obj->fk_soc; // deprecated
659  $this->contact->id = $obj->fk_contact; // deprecated
660 
661  $this->fk_element = $obj->elementid;
662  $this->elementid = $obj->elementid;
663  $this->elementtype = $obj->elementtype;
664 
665  $this->fetchResources();
666  }
667  $this->db->free($resql);
668  }
669  else
670  {
671  $this->error=$this->db->lasterror();
672  return -1;
673  }
674 
675  return $num;
676  }
677 
683  function fetchResources()
684  {
685  $sql ='SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency';
686  $sql.=' FROM '.MAIN_DB_PREFIX.'actioncomm_resources';
687  $sql.=' WHERE fk_actioncomm = '.$this->id;
688  $sql.=" AND element_type IN ('user', 'socpeople')";
689  $resql=$this->db->query($sql);
690  if ($resql)
691  {
692  $this->userassigned=array();
693  $this->socpeopleassigned=array();
694 
695  // If owner is known, we must but id first into list
696  if ($this->userownerid > 0) $this->userassigned[$this->userownerid]=array('id'=>$this->userownerid); // Set first so will be first into list.
697 
698  while ($obj = $this->db->fetch_object($resql))
699  {
700  if ($obj->fk_element > 0)
701  {
702  switch ($obj->element_type) {
703  case 'user':
704  $this->userassigned[$obj->fk_element]=array('id'=>$obj->fk_element, 'mandatory'=>$obj->mandatory, 'answer_status'=>$obj->answer_status, 'transparency'=>$obj->transparency);
705  if (empty($this->userownerid)) $this->userownerid=$obj->fk_element; // If not defined (should not happened, we fix this)
706  break;
707  case 'socpeople':
708  $this->socpeopleassigned[$obj->fk_element]=array('id'=>$obj->fk_element, 'mandatory'=>$obj->mandatory, 'answer_status'=>$obj->answer_status, 'transparency'=>$obj->transparency);
709  break;
710  }
711  }
712  }
713 
714  return 1;
715  }
716  else
717  {
718  dol_print_error($this->db);
719  return -1;
720  }
721  }
722 
723  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
730  {
731  // phpcs:enable
732  $sql ="SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency";
733  $sql.=" FROM ".MAIN_DB_PREFIX."actioncomm_resources";
734  $sql.=" WHERE element_type = 'user' AND fk_actioncomm = ".$this->id;
735  $resql2=$this->db->query($sql);
736  if ($resql2)
737  {
738  $this->userassigned=array();
739 
740  // If owner is known, we must but id first into list
741  if ($this->userownerid > 0) $this->userassigned[$this->userownerid]=array('id'=>$this->userownerid); // Set first so will be first into list.
742 
743  while ($obj = $this->db->fetch_object($resql2))
744  {
745  if ($obj->fk_element > 0) $this->userassigned[$obj->fk_element]=array('id'=>$obj->fk_element, 'mandatory'=>$obj->mandatory, 'answer_status'=>$obj->answer_status, 'transparency'=>$obj->transparency);
746  if (empty($this->userownerid)) $this->userownerid=$obj->fk_element; // If not defined (should not happened, we fix this)
747  }
748 
749  return 1;
750  }
751  else
752  {
753  dol_print_error($this->db);
754  return -1;
755  }
756  }
757 
764  function delete($notrigger=0)
765  {
766  global $user,$langs,$conf;
767 
768  $error=0;
769 
770  $this->db->begin();
771 
772  $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm";
773  $sql.= " WHERE id=".$this->id;
774 
775  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
776  $res=$this->db->query($sql);
777  if ($res < 0) {
778  $this->error=$this->db->lasterror();
779  $error++;
780  }
781 
782  if (! $error) {
783  $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources";
784  $sql.= " WHERE fk_actioncomm=".$this->id;
785 
786  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
787  $res=$this->db->query($sql);
788  if ($res < 0) {
789  $this->error=$this->db->lasterror();
790  $error++;
791  }
792  }
793 
794  // Removed extrafields
795  if (! $error) {
796  $result=$this->deleteExtraFields();
797  if ($result < 0)
798  {
799  $error++;
800  dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
801  }
802  }
803 
804  if (!$error)
805  {
806  if (! $notrigger)
807  {
808  // Call trigger
809  $result=$this->call_trigger('ACTION_DELETE',$user);
810  if ($result < 0) { $error++; }
811  // End call triggers
812  }
813 
814  if (! $error)
815  {
816  $this->db->commit();
817  return 1;
818  }
819  else
820  {
821  $this->db->rollback();
822  return -2;
823  }
824  }
825  else
826  {
827  $this->db->rollback();
828  $this->error=$this->db->lasterror();
829  return -1;
830  }
831  }
832 
841  function update($user,$notrigger=0)
842  {
843  global $langs,$conf,$hookmanager;
844 
845  $error=0;
846 
847  // Clean parameters
848  $this->label=trim($this->label);
849  $this->note=trim($this->note);
850  if (empty($this->percentage)) $this->percentage = 0;
851  if (empty($this->priority) || ! is_numeric($this->priority)) $this->priority = 0;
852  if (empty($this->transparency)) $this->transparency = 0;
853  if (empty($this->fulldayevent)) $this->fulldayevent = 0;
854  if ($this->percentage > 100) $this->percentage = 100;
855  //if ($this->percentage == 100 && ! $this->dateend) $this->dateend = $this->date;
856  if ($this->datep && $this->datef) $this->durationp=($this->datef - $this->datep); // deprecated
857  //if ($this->date && $this->dateend) $this->durationa=($this->dateend - $this->date);
858  if ($this->datep && $this->datef && $this->datep > $this->datef) $this->datef=$this->datep;
859  //if ($this->date && $this->dateend && $this->date > $this->dateend) $this->dateend=$this->date;
860  if ($this->fk_project < 0) $this->fk_project = 0;
861 
862  // Check parameters
863  if ($this->percentage == 0 && $this->userdoneid > 0)
864  {
865  $this->error="ErrorCantSaveADoneUserWithZeroPercentage";
866  return -1;
867  }
868 
869  $socid=($this->socid?$this->socid:((isset($this->societe->id) && $this->societe->id > 0) ? $this->societe->id : 0));
870  $contactid=($this->contactid?$this->contactid:((isset($this->contact->id) && $this->contact->id > 0) ? $this->contact->id : 0));
871  $userownerid=($this->userownerid?$this->userownerid:0);
872  $userdoneid=($this->userdoneid?$this->userdoneid:0);
873 
874  $this->db->begin();
875 
876  $sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm ";
877  $sql.= " SET percent = '".$this->db->escape($this->percentage)."'";
878  if ($this->type_id > 0) $sql.= ", fk_action = '".$this->db->escape($this->type_id)."'";
879  $sql.= ", label = ".($this->label ? "'".$this->db->escape($this->label)."'":"null");
880  $sql.= ", datep = ".(strval($this->datep)!='' ? "'".$this->db->idate($this->datep)."'" : 'null');
881  $sql.= ", datep2 = ".(strval($this->datef)!='' ? "'".$this->db->idate($this->datef)."'" : 'null');
882  $sql.= ", durationp = ".(isset($this->durationp) && $this->durationp >= 0 && $this->durationp != ''?"'".$this->db->escape($this->durationp)."'":"null"); // deprecated
883  $sql.= ", note = '".$this->db->escape($this->note_private?$this->note_private:$this->note)."'";
884  $sql.= ", fk_project =". ($this->fk_project > 0 ? $this->fk_project:"null");
885  $sql.= ", fk_soc =". ($socid > 0 ? $socid:"null");
886  $sql.= ", fk_contact =". ($contactid > 0 ? $contactid:"null");
887  $sql.= ", priority = '".$this->db->escape($this->priority)."'";
888  $sql.= ", fulldayevent = '".$this->db->escape($this->fulldayevent)."'";
889  $sql.= ", location = ".($this->location ? "'".$this->db->escape($this->location)."'":"null");
890  $sql.= ", transparency = '".$this->db->escape($this->transparency)."'";
891  $sql.= ", fk_user_mod = ".$user->id;
892  $sql.= ", fk_user_action=".($userownerid > 0 ? "'".$userownerid."'":"null");
893  $sql.= ", fk_user_done=".($userdoneid > 0 ? "'".$userdoneid."'":"null");
894  if (! empty($this->fk_element)) $sql.= ", fk_element=".($this->fk_element?$this->db->escape($this->fk_element):"null");
895  if (! empty($this->elementtype)) $sql.= ", elementtype=".($this->elementtype?"'".$this->db->escape($this->elementtype)."'":"null");
896  $sql.= " WHERE id=".$this->id;
897 
898  dol_syslog(get_class($this)."::update", LOG_DEBUG);
899  if ($this->db->query($sql))
900  {
901  $action='update';
902 
903  // Actions on extra fields
904  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
905  {
906  $result=$this->insertExtraFields();
907  if ($result < 0)
908  {
909  $error++;
910  }
911  }
912 
913  // Now insert assignedusers
914  if (! $error)
915  {
916  $sql ="DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".$this->id." AND element_type = 'user'";
917  $resql = $this->db->query($sql);
918 
919  foreach($this->userassigned as $key => $val)
920  {
921  if (! is_array($val)) // For backward compatibility when val=id
922  {
923  $val=array('id'=>$val);
924  }
925  $sql ="INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
926  $sql.=" VALUES(".$this->id.", 'user', ".$val['id'].", ".(empty($val['mandatory'])?'0':$val['mandatory']).", ".(empty($val['transparency'])?'0':$val['transparency']).", ".(empty($val['answer_status'])?'0':$val['answer_status']).")";
927 
928  $resql = $this->db->query($sql);
929  if (! $resql)
930  {
931  $error++;
932  $this->errors[]=$this->db->lasterror();
933  }
934  //var_dump($sql);exit;
935  }
936  }
937 
938  if (!$error)
939  {
940  $sql ="DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".$this->id." AND element_type = 'socpeople'";
941  $resql = $this->db->query($sql);
942 
943  if (!empty($this->socpeopleassigned))
944  {
945  foreach (array_keys($this->socpeopleassigned) as $id)
946  {
947  $sql ="INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
948  $sql.=" VALUES(".$this->id.", 'socpeople', ".$id.", 0, 0, 0)";
949 
950  $resql = $this->db->query($sql);
951  if (! $resql)
952  {
953  $error++;
954  $this->errors[]=$this->db->lasterror();
955  }
956  }
957  }
958  }
959 
960  if (! $error && ! $notrigger)
961  {
962  // Call trigger
963  $result=$this->call_trigger('ACTION_MODIFY',$user);
964  if ($result < 0) { $error++; }
965  // End call triggers
966  }
967 
968  if (! $error)
969  {
970  $this->db->commit();
971  return 1;
972  }
973  else
974  {
975  $this->db->rollback();
976  dol_syslog(get_class($this)."::update ".join(',',$this->errors),LOG_ERR);
977  return -2;
978  }
979  }
980  else
981  {
982  $this->db->rollback();
983  $this->error=$this->db->lasterror();
984  return -1;
985  }
986  }
987 
1002  static function getActions($db, $socid=0, $fk_element=0, $elementtype='', $filter='', $sortfield='a.datep', $sortorder='DESC', $limit=0)
1003  {
1004  global $conf, $langs;
1005 
1006  $resarray=array();
1007 
1008  $sql = "SELECT a.id";
1009  $sql.= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1010  $sql.= " WHERE a.entity IN (".getEntity('agenda').")";
1011  if (! empty($socid)) $sql.= " AND a.fk_soc = ".$socid;
1012  if (! empty($elementtype))
1013  {
1014  if ($elementtype == 'project') $sql.= ' AND a.fk_project = '.$fk_element;
1015  else $sql.= " AND a.fk_element = ".(int) $fk_element." AND a.elementtype = '".$elementtype."'";
1016  }
1017  if (! empty($filter)) $sql.= $filter;
1018  if ($sortorder && $sortfield) $sql.=$db->order($sortfield, $sortorder);
1019  $sql.=$db->plimit($limit, 0);
1020 
1021  dol_syslog(get_class()."::getActions", LOG_DEBUG);
1022  $resql=$db->query($sql);
1023  if ($resql)
1024  {
1025  $num = $db->num_rows($resql);
1026 
1027  if ($num)
1028  {
1029  for($i=0;$i<$num;$i++)
1030  {
1031  $obj = $db->fetch_object($resql);
1032  $actioncommstatic = new ActionComm($db);
1033  $actioncommstatic->fetch($obj->id);
1034  $resarray[$i] = $actioncommstatic;
1035  }
1036  }
1037  $db->free($resql);
1038  return $resarray;
1039  }
1040  else
1041  {
1042  return $db->lasterror();
1043  }
1044  }
1045 
1046  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1054  function load_board($user, $load_state_board=0)
1055  {
1056  // phpcs:enable
1057  global $conf, $langs;
1058 
1059  if(empty($load_state_board)) $sql = "SELECT a.id, a.datep as dp";
1060  else {
1061  $this->nb=array();
1062  $sql = "SELECT count(a.id) as nb";
1063  }
1064  $sql.= " FROM (".MAIN_DB_PREFIX."actioncomm as a";
1065  $sql.= ")";
1066  if (! $user->rights->societe->client->voir && ! $user->societe_id) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON a.fk_soc = sc.fk_soc";
1067  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON a.fk_soc = s.rowid";
1068  $sql.= " WHERE 1 = 1";
1069  if(empty($load_state_board)) $sql.= " AND a.percent >= 0 AND a.percent < 100";
1070  $sql.= " AND a.entity IN (".getEntity('agenda').")";
1071  if (! $user->rights->societe->client->voir && ! $user->societe_id) $sql.= " AND (a.fk_soc IS NULL OR sc.fk_user = " .$user->id . ")";
1072  if ($user->societe_id) $sql.=" AND a.fk_soc = ".$user->societe_id;
1073  if (! $user->rights->agenda->allactions->read) $sql.= " AND (a.fk_user_author = ".$user->id . " OR a.fk_user_action = ".$user->id . " OR a.fk_user_done = ".$user->id . ")";
1074 
1075  $resql=$this->db->query($sql);
1076  if ($resql)
1077  {
1078  if(empty($load_state_board)) {
1079  $agenda_static = new ActionComm($this->db);
1080  $response = new WorkboardResponse();
1081  $response->warning_delay = $conf->agenda->warning_delay/60/60/24;
1082  $response->label = $langs->trans("ActionsToDo");
1083  $response->url = DOL_URL_ROOT.'/comm/action/list.php?actioncode=0&amp;status=todo&amp;mainmenu=agenda';
1084  if ($user->rights->agenda->allactions->read) $response->url.='&amp;filtert=-1';
1085  $response->img = img_object('',"action",'class="inline-block valigntextmiddle"');
1086  }
1087  // This assignment in condition is not a bug. It allows walking the results.
1088  while ($obj=$this->db->fetch_object($resql))
1089  {
1090  if(empty($load_state_board)) {
1091  $response->nbtodo++;
1092  $agenda_static->datep = $this->db->jdate($obj->dp);
1093  if ($agenda_static->hasDelay()) $response->nbtodolate++;
1094  } else $this->nb["actionscomm"]=$obj->nb;
1095  }
1096 
1097  $this->db->free($resql);
1098  if(empty($load_state_board)) return $response;
1099  else return 1;
1100  }
1101  else
1102  {
1103  dol_print_error($this->db);
1104  $this->error=$this->db->error();
1105  return -1;
1106  }
1107  }
1108 
1109 
1116  function info($id)
1117  {
1118  $sql = 'SELECT ';
1119  $sql.= ' a.id,';
1120  $sql.= ' datec,';
1121  $sql.= ' tms as datem,';
1122  $sql.= ' fk_user_author,';
1123  $sql.= ' fk_user_mod';
1124  $sql.= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a';
1125  $sql.= ' WHERE a.id = '.$id;
1126 
1127  dol_syslog(get_class($this)."::info", LOG_DEBUG);
1128  $result=$this->db->query($sql);
1129  if ($result)
1130  {
1131  if ($this->db->num_rows($result))
1132  {
1133  $obj = $this->db->fetch_object($result);
1134  $this->id = $obj->id;
1135  if ($obj->fk_user_author)
1136  {
1137  $cuser = new User($this->db);
1138  $cuser->fetch($obj->fk_user_author);
1139  $this->user_creation = $cuser;
1140  }
1141  if ($obj->fk_user_mod)
1142  {
1143  $muser = new User($this->db);
1144  $muser->fetch($obj->fk_user_mod);
1145  $this->user_modification = $muser;
1146  }
1147 
1148  $this->date_creation = $this->db->jdate($obj->datec);
1149  if (! empty($obj->fk_user_mod)) $this->date_modification = $this->db->jdate($obj->datem);
1150  }
1151  $this->db->free($result);
1152  }
1153  else
1154  {
1155  dol_print_error($this->db);
1156  }
1157  }
1158 
1159 
1167  function getLibStatut($mode,$hidenastatus=0)
1168  {
1169  return $this->LibStatut($this->percentage,$mode,$hidenastatus,$this->datep);
1170  }
1171 
1172  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1182  function LibStatut($percent,$mode,$hidenastatus=0,$datestart='')
1183  {
1184  // phpcs:enable
1185  global $langs;
1186 
1187  if ($mode == 0)
1188  {
1189  if ($percent==-1 && ! $hidenastatus) return $langs->trans('StatusNotApplicable');
1190  elseif ($percent==0) return $langs->trans('StatusActionToDo').' (0%)';
1191  elseif ($percent > 0 && $percent < 100) return $langs->trans('StatusActionInProcess').' ('.$percent.'%)';
1192  elseif ($percent >= 100) return $langs->trans('StatusActionDone').' (100%)';
1193  }
1194  elseif ($mode == 1)
1195  {
1196  if ($percent==-1 && ! $hidenastatus) return $langs->trans('StatusNotApplicable');
1197  elseif ($percent==0) return $langs->trans('StatusActionToDo');
1198  elseif ($percent > 0 && $percent < 100) return $percent.'%';
1199  elseif ($percent >= 100) return $langs->trans('StatusActionDone');
1200  }
1201  elseif ($mode == 2)
1202  {
1203  if ($percent==-1 && ! $hidenastatus) return img_picto($langs->trans('StatusNotApplicable'),'statut9').' '.$langs->trans('StatusNotApplicable');
1204  elseif ($percent==0) return img_picto($langs->trans('StatusActionToDo'),'statut1').' '.$langs->trans('StatusActionToDo');
1205  elseif ($percent > 0 && $percent < 100) return img_picto($langs->trans('StatusActionInProcess'),'statut3').' '. $percent.'%';
1206  elseif ($percent >= 100) return img_picto($langs->trans('StatusActionDone'),'statut6').' '.$langs->trans('StatusActionDone');
1207  }
1208  elseif ($mode == 3)
1209  {
1210  if ($percent==-1 && ! $hidenastatus) return img_picto($langs->trans("Status").': '.$langs->trans('StatusNotApplicable'),'statut9');
1211  elseif ($percent==0) return img_picto($langs->trans("Status").': '.$langs->trans('StatusActionToDo').' (0%)','statut1');
1212  elseif ($percent > 0 && $percent < 100) return img_picto($langs->trans("Status").': '.$langs->trans('StatusActionInProcess').' ('.$percent.'%)','statut3');
1213  elseif ($percent >= 100) return img_picto($langs->trans("Status").': '.$langs->trans('StatusActionDone').' (100%)','statut6');
1214  }
1215  elseif ($mode == 4)
1216  {
1217  if ($percent==-1 && ! $hidenastatus) return img_picto($langs->trans('StatusNotApplicable'),'statut9').' '.$langs->trans('StatusNotApplicable');
1218  elseif ($percent==0) return img_picto($langs->trans('StatusActionToDo'),'statut1').' '.$langs->trans('StatusActionToDo').' (0%)';
1219  elseif ($percent > 0 && $percent < 100) return img_picto($langs->trans('StatusActionInProcess'),'statut3').' '.$langs->trans('StatusActionInProcess').' ('.$percent.'%)';
1220  elseif ($percent >= 100) return img_picto($langs->trans('StatusActionDone'),'statut6').' '.$langs->trans('StatusActionDone').' (100%)';
1221  }
1222  elseif ($mode == 5)
1223  {
1224  if ($percent==-1 && ! $hidenastatus) return img_picto($langs->trans('StatusNotApplicable'),'statut9');
1225  elseif ($percent==0) return '0% '.img_picto($langs->trans('StatusActionToDo'),'statut1');
1226  elseif ($percent > 0 && $percent < 100) return $percent.'% '.img_picto($langs->trans('StatusActionInProcess').' - '.$percent.'%','statut3');
1227  elseif ($percent >= 100) return $langs->trans('StatusActionDone').' '.img_picto($langs->trans('StatusActionDone'),'statut6');
1228  }
1229  elseif ($mode == 6)
1230  {
1231  if ($percent==-1 && ! $hidenastatus) return $langs->trans('StatusNotApplicable').' '.img_picto($langs->trans('StatusNotApplicable'),'statut9');
1232  elseif ($percent==0) return $langs->trans('StatusActionToDo').' (0%) '.img_picto($langs->trans('StatusActionToDo'),'statut1');
1233  elseif ($percent > 0 && $percent < 100) return $langs->trans('StatusActionInProcess').' ('.$percent.'%) '.img_picto($langs->trans('StatusActionInProcess').' - '.$percent.'%','statut3');
1234  elseif ($percent >= 100) return $langs->trans('StatusActionDone').' (100%) '.img_picto($langs->trans('StatusActionDone'),'statut6');
1235  }
1236  elseif ($mode == 7)
1237  {
1238  if ($percent==-1 && ! $hidenastatus) return img_picto($langs->trans('StatusNotApplicable'),'statut9');
1239  elseif ($percent==0) return '0% '.img_picto($langs->trans('StatusActionToDo'),'statut1');
1240  elseif ($percent > 0 && $percent < 100) return $percent.'% '.img_picto($langs->trans('StatusActionInProcess').' - '.$percent.'%','statut3');
1241  elseif ($percent >= 100) return img_picto($langs->trans('StatusActionDone'),'statut6');
1242  }
1243 
1244  return '';
1245  }
1246 
1260  function getNomUrl($withpicto=0, $maxlength=0, $classname='', $option='', $overwritepicto=0, $notooltip=0, $save_lastsearch_value=-1)
1261  {
1262  global $conf, $langs, $user, $hookmanager, $action;
1263 
1264  if (! empty($conf->dol_no_mouse_hover)) $notooltip=1; // Force disable tooltips
1265 
1266  if ((!$user->rights->agenda->allactions->read && $this->author->id != $user->id) || (!$user->rights->agenda->myactions->read && $this->author->id == $user->id))
1267  $option = 'nolink';
1268 
1269  $label = $this->label;
1270  if (empty($label)) $label=$this->libelle; // For backward compatibility
1271 
1272  $result='';
1273 
1274  // Set label of type
1275  $labeltype = '';
1276  if ($this->type_code)
1277  {
1278  $labeltype = ($langs->transnoentities("Action".$this->type_code) != "Action".$this->type_code)?$langs->transnoentities("Action".$this->type_code):$this->type_label;
1279  }
1280  if (empty($conf->global->AGENDA_USE_EVENT_TYPE))
1281  {
1282  if ($this->type_code != 'AC_OTH_AUTO') $labeltype = $langs->trans('ActionAC_MANUAL');
1283  }
1284 
1285  $tooltip = '<u>' . $langs->trans('ShowAction') . '</u>';
1286  if (! empty($this->ref))
1287  $tooltip .= '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
1288  if (! empty($label))
1289  $tooltip .= '<br><b>' . $langs->trans('Title') . ':</b> ' . $label;
1290  if (! empty($labeltype))
1291  $tooltip .= '<br><b>' . $langs->trans('Type') . ':</b> ' . $labeltype;
1292  if (! empty($this->location))
1293  $tooltip .= '<br><b>' . $langs->trans('Location') . ':</b> ' . $this->location;
1294 
1295  $linkclose='';
1296  if (! empty($conf->global->AGENDA_USE_EVENT_TYPE) && $this->type_color)
1297  $linkclose = ' style="background-color:#'.$this->type_color.'"';
1298 
1299  if (empty($notooltip))
1300  {
1301  if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1302  {
1303  $label=$langs->trans("ShowAction");
1304  $linkclose.=' alt="'.dol_escape_htmltag($tooltip, 1).'"';
1305  }
1306  $linkclose.=' title="'.dol_escape_htmltag($tooltip, 1).'"';
1307  $linkclose.=' class="'.$classname.' classfortooltip"';
1308 
1309  /*
1310  $hookmanager->initHooks(array('actiondao'));
1311  $parameters=array('id'=>$this->id);
1312  $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
1313  $linkclose = ($hookmanager->resPrint ? $hookmanager->resPrint : $linkclose);
1314  */
1315  }
1316  else $linkclose.=' class="'.$classname.'"';
1317 
1318  $url='';
1319  if ($option=='birthday')
1320  $url = DOL_URL_ROOT.'/contact/perso.php?id='.$this->id;
1321  else
1322  $url = DOL_URL_ROOT.'/comm/action/card.php?id='.$this->id;
1323  if ($option !== 'nolink')
1324  {
1325  // Add param to save lastsearch_values or not
1326  $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
1327  if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
1328  if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
1329  }
1330 
1331  $linkstart = '<a href="'.$url.'"';
1332  $linkstart.=$linkclose.'>';
1333  $linkend='</a>';
1334 
1335  if ($option == 'nolink') {
1336  $linkstart = '';
1337  $linkend = '';
1338  }
1339  //print 'rrr'.$this->libelle.'rrr'.$this->label.'rrr'.$withpicto;
1340 
1341  if ($withpicto == 2)
1342  {
1343  $libelle=$label;
1344  if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) $libelle=$labeltype;
1345  $libelleshort='';
1346  }
1347  else
1348  {
1349  $libelle=(empty($this->libelle)?$label:$this->libelle.(($label && $label != $this->libelle)?' '.$label:''));
1350  if (! empty($conf->global->AGENDA_USE_EVENT_TYPE) && empty($libelle)) $libelle=$labeltype;
1351  if ($maxlength < 0) $libelleshort=$this->ref;
1352  else $libelleshort=dol_trunc($libelle,$maxlength);
1353  }
1354 
1355  if ($withpicto)
1356  {
1357  if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) // Add code into ()
1358  {
1359  if ($labeltype)
1360  {
1361  $libelle.=(preg_match('/'.preg_quote($labeltype,'/').'/', $libelle)?'':' ('.$langs->transnoentities("Action".$this->type_code).')');
1362  }
1363  }
1364  }
1365 
1366  $result.=$linkstart;
1367  if ($withpicto) $result.=img_object(($notooltip?'':$langs->trans("ShowAction").': '.$libelle), ($overwritepicto?$overwritepicto:'action'), ($notooltip?'class="'.(($withpicto != 2) ? 'paddingright ' : '').'valigntextbottom"':'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip valigntextbottom"'), 0, 0, $notooltip?0:1);
1368  $result.=$libelleshort;
1369  $result.=$linkend;
1370 
1371  global $action;
1372  $hookmanager->initHooks(array('actiondao'));
1373  $parameters=array('id'=>$this->id, 'getnomurl'=>$result);
1374  $reshook=$hookmanager->executeHooks('getNomUrl',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
1375  if ($reshook > 0) $result = $hookmanager->resPrint;
1376  else $result .= $hookmanager->resPrint;
1377 
1378  return $result;
1379  }
1380 
1381 
1382  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1393  function build_exportfile($format,$type,$cachedelay,$filename,$filters)
1394  {
1395  // phpcs:enable
1396  global $conf,$langs,$dolibarr_main_url_root,$mysoc;
1397 
1398  require_once DOL_DOCUMENT_ROOT ."/core/lib/xcal.lib.php";
1399  require_once DOL_DOCUMENT_ROOT ."/core/lib/date.lib.php";
1400  require_once DOL_DOCUMENT_ROOT ."/core/lib/files.lib.php";
1401 
1402  dol_syslog(get_class($this)."::build_exportfile Build export file format=".$format.", type=".$type.", cachedelay=".$cachedelay.", filename=".$filename.", filters size=".count($filters), LOG_DEBUG);
1403 
1404  // Check parameters
1405  if (empty($format)) return -1;
1406 
1407  // Clean parameters
1408  if (! $filename)
1409  {
1410  $extension='vcs';
1411  if ($format == 'ical') $extension='ics';
1412  $filename=$format.'.'.$extension;
1413  }
1414 
1415  // Create dir and define output file (definitive and temporary)
1416  $result=dol_mkdir($conf->agenda->dir_temp);
1417  $outputfile=$conf->agenda->dir_temp.'/'.$filename;
1418 
1419  $result=0;
1420 
1421  $buildfile=true;
1422  $login='';$logina='';$logind='';$logint='';
1423 
1424  $now = dol_now();
1425 
1426  if ($cachedelay)
1427  {
1428  $nowgmt = dol_now();
1429  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1430  if (dol_filemtime($outputfile) > ($nowgmt - $cachedelay))
1431  {
1432  dol_syslog(get_class($this)."::build_exportfile file ".$outputfile." is not older than now - cachedelay (".$nowgmt." - ".$cachedelay."). Build is canceled");
1433  $buildfile = false;
1434  }
1435  }
1436 
1437  if ($buildfile)
1438  {
1439  // Build event array
1440  $eventarray=array();
1441 
1442  $sql = "SELECT a.id,";
1443  $sql.= " a.datep,"; // Start
1444  $sql.= " a.datep2,"; // End
1445  $sql.= " a.durationp,"; // deprecated
1446  $sql.= " a.datec, a.tms as datem,";
1447  $sql.= " a.label, a.code, a.note, a.fk_action as type_id,";
1448  $sql.= " a.fk_soc,";
1449  $sql.= " a.fk_user_author, a.fk_user_mod,";
1450  $sql.= " a.fk_user_action,";
1451  $sql.= " a.fk_contact, a.percent as percentage,";
1452  $sql.= " a.fk_element, a.elementtype,";
1453  $sql.= " a.priority, a.fulldayevent, a.location, a.punctual, a.transparency,";
1454  $sql.= " u.firstname, u.lastname,";
1455  $sql.= " s.nom as socname,";
1456  $sql.= " c.id as type_id, c.code as type_code, c.libelle";
1457  $sql.= " FROM (".MAIN_DB_PREFIX."c_actioncomm as c, ".MAIN_DB_PREFIX."actioncomm as a)";
1458  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author"; // Link to get author of event for export
1459  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
1460  // We must filter on assignement table
1461  if ($filters['logint']) $sql.=", ".MAIN_DB_PREFIX."actioncomm_resources as ar";
1462  $sql.= " WHERE a.fk_action=c.id";
1463  $sql.= " AND a.entity IN (".getEntity('agenda').")";
1464  foreach ($filters as $key => $value)
1465  {
1466  if ($key == 'notolderthan' && $value != '') $sql.=" AND a.datep >= '".$this->db->idate($now-($value*24*60*60))."'";
1467  if ($key == 'year') $sql.=" AND a.datep BETWEEN '".$this->db->idate(dol_get_first_day($value,1))."' AND '".$this->db->idate(dol_get_last_day($value,12))."'";
1468  if ($key == 'id') $sql.=" AND a.id=".(is_numeric($value)?$value:0);
1469  if ($key == 'idfrom') $sql.=" AND a.id >= ".(is_numeric($value)?$value:0);
1470  if ($key == 'idto') $sql.=" AND a.id <= ".(is_numeric($value)?$value:0);
1471  if ($key == 'project') $sql.=" AND a.fk_project=".(is_numeric($value)?$value:0);
1472  if ($key == 'actiontype') $sql.=" AND c.type = '".$this->db->escape($value)."'";
1473  if ($key == 'notactiontype') $sql.=" AND c.type <> '".$this->db->escape($value)."'";
1474  // We must filter on assignement table
1475  if ($key == 'logint') $sql.= " AND ar.fk_actioncomm = a.id AND ar.element_type='user'";
1476  if ($key == 'logina')
1477  {
1478  $logina=$value;
1479  $condition='=';
1480  if (preg_match('/^!/',$logina))
1481  {
1482  $logina=preg_replace('/^!/','',$logina);
1483  $condition='<>';
1484  }
1485  $userforfilter=new User($this->db);
1486  $result=$userforfilter->fetch('',$logina);
1487  if ($result > 0) $sql.= " AND a.fk_user_author ".$condition." ".$userforfilter->id;
1488  elseif ($result < 0 || $condition == '=') $sql.= " AND a.fk_user_author = 0";
1489  }
1490  if ($key == 'logint')
1491  {
1492  $logint=$value;
1493  $condition='=';
1494  if (preg_match('/^!/',$logint))
1495  {
1496  $logint=preg_replace('/^!/','',$logint);
1497  $condition='<>';
1498  }
1499  $userforfilter=new User($this->db);
1500  $result=$userforfilter->fetch('',$logint);
1501  if ($result > 0) $sql.= " AND ar.fk_element = ".$userforfilter->id;
1502  elseif ($result < 0 || $condition == '=') $sql.= " AND ar.fk_element = 0";
1503  }
1504  }
1505  $sql.= " AND a.datep IS NOT NULL"; // To exclude corrupted events and avoid errors in lightning/sunbird import
1506  $sql.= " ORDER by datep";
1507  //print $sql;exit;
1508 
1509  dol_syslog(get_class($this)."::build_exportfile select events", LOG_DEBUG);
1510  $resql=$this->db->query($sql);
1511  if ($resql)
1512  {
1513  // Note: Output of sql request is encoded in $conf->file->character_set_client
1514  // This assignment in condition is not a bug. It allows walking the results.
1515  $diff = 0;
1516  while ($obj=$this->db->fetch_object($resql))
1517  {
1518  $qualified=true;
1519 
1520  // 'eid','startdate','duration','enddate','title','summary','category','email','url','desc','author'
1521  $event=array();
1522  $event['uid']='dolibarragenda-'.$this->db->database_name.'-'.$obj->id."@".$_SERVER["SERVER_NAME"];
1523  $event['type']=$type;
1524  $datestart=$this->db->jdate($obj->datep)-(empty($conf->global->AGENDA_EXPORT_FIX_TZ)?0:($conf->global->AGENDA_EXPORT_FIX_TZ*3600));
1525  $dateend=$this->db->jdate($obj->datep2)-(empty($conf->global->AGENDA_EXPORT_FIX_TZ)?0:($conf->global->AGENDA_EXPORT_FIX_TZ*3600));
1526  $duration=($datestart && $dateend)?($dateend - $datestart):0;
1527  $event['summary']=$obj->label.($obj->socname?" (".$obj->socname.")":"");
1528  $event['desc']=$obj->note;
1529  $event['startdate']=$datestart;
1530  $event['enddate']=$dateend; // Not required with type 'journal'
1531  $event['duration']=$duration; // Not required with type 'journal'
1532  $event['author']=dolGetFirstLastname($obj->firstname, $obj->lastname);
1533  $event['priority']=$obj->priority;
1534  $event['fulldayevent']=$obj->fulldayevent;
1535  $event['location']=$obj->location;
1536  $event['transparency']=(($obj->transparency > 0)?'OPAQUE':'TRANSPARENT'); // OPAQUE (busy) or TRANSPARENT (not busy)
1537  $event['punctual']=$obj->punctual;
1538  $event['category']=$obj->libelle; // libelle type action
1539  // Define $urlwithroot
1540  $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
1541  $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
1542  //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
1543  $url=$urlwithroot.'/comm/action/card.php?id='.$obj->id;
1544  $event['url']=$url;
1545  $event['created']=$this->db->jdate($obj->datec)-(empty($conf->global->AGENDA_EXPORT_FIX_TZ)?0:($conf->global->AGENDA_EXPORT_FIX_TZ*3600));
1546  $event['modified']=$this->db->jdate($obj->datem)-(empty($conf->global->AGENDA_EXPORT_FIX_TZ)?0:($conf->global->AGENDA_EXPORT_FIX_TZ*3600));
1547 
1548  if ($qualified && $datestart)
1549  {
1550  $eventarray[]=$event;
1551  }
1552  $diff++;
1553  }
1554  }
1555  else
1556  {
1557  $this->error=$this->db->lasterror();
1558  return -1;
1559  }
1560 
1561  $langs->load("agenda");
1562 
1563  // Define title and desc
1564  $more='';
1565  if ($login) $more=$langs->transnoentities("User").' '.$login;
1566  if ($logina) $more=$langs->transnoentities("ActionsAskedBy").' '.$logina;
1567  if ($logint) $more=$langs->transnoentities("ActionsToDoBy").' '.$logint;
1568  if ($logind) $more=$langs->transnoentities("ActionsDoneBy").' '.$logind;
1569  if ($more)
1570  {
1571  $title='Dolibarr actions '.$mysoc->name.' - '.$more;
1572  $desc=$more;
1573  $desc.=' ('.$mysoc->name.' - built by Dolibarr)';
1574  }
1575  else
1576  {
1577  $title='Dolibarr actions '.$mysoc->name;
1578  $desc=$langs->transnoentities('ListOfActions');
1579  $desc.=' ('.$mysoc->name.' - built by Dolibarr)';
1580  }
1581 
1582  // Create temp file
1583  $outputfiletmp=tempnam($conf->agenda->dir_temp,'tmp'); // Temporary file (allow call of function by different threads
1584  @chmod($outputfiletmp, octdec($conf->global->MAIN_UMASK));
1585 
1586  // Write file
1587  if ($format == 'vcal') $result=build_calfile($format,$title,$desc,$eventarray,$outputfiletmp);
1588  elseif ($format == 'ical') $result=build_calfile($format,$title,$desc,$eventarray,$outputfiletmp);
1589  elseif ($format == 'rss') $result=build_rssfile($format,$title,$desc,$eventarray,$outputfiletmp);
1590 
1591  if ($result >= 0)
1592  {
1593  if (dol_move($outputfiletmp,$outputfile,0,1)) $result=1;
1594  else
1595  {
1596  $this->error='Failed to rename '.$outputfiletmp.' into '.$outputfile;
1597  dol_syslog(get_class($this)."::build_exportfile ".$this->error, LOG_ERR);
1598  dol_delete_file($outputfiletmp,0,1);
1599  $result=-1;
1600  }
1601  }
1602  else
1603  {
1604  dol_syslog(get_class($this)."::build_exportfile build_xxxfile function fails to for format=".$format." outputfiletmp=".$outputfile, LOG_ERR);
1605  dol_delete_file($outputfiletmp,0,1);
1606  $langs->load("errors");
1607  $this->error=$langs->trans("ErrorFailToCreateFile",$outputfile);
1608  }
1609  }
1610 
1611  return $result;
1612  }
1613 
1621  function initAsSpecimen()
1622  {
1623  global $user;
1624 
1625  $now=dol_now();
1626 
1627  // Initialise parametres
1628  $this->id=0;
1629  $this->specimen=1;
1630 
1631  $this->type_code='AC_OTH';
1632  $this->code='AC_SPECIMEN_CODE';
1633  $this->label='Label of event Specimen';
1634  $this->datec=$now;
1635  $this->datem=$now;
1636  $this->datep=$now;
1637  $this->datef=$now;
1638  $this->author=$user;
1639  $this->usermod=$user;
1640  $this->usertodo=$user;
1641  $this->fulldayevent=0;
1642  $this->punctual=0;
1643  $this->percentage=0;
1644  $this->location='Location';
1645  $this->transparency=1; // 1 means opaque
1646  $this->priority=1;
1647  $this->note = 'Note';
1648 
1649  $this->userownerid=$user->id;
1650  $this->userassigned[$user->id]=array('id'=>$user->id, 'transparency'=> 1);
1651  }
1652 
1661  public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
1662  {
1663  $tables = array(
1664  'actioncomm'
1665  );
1666 
1667  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
1668  }
1669 
1675  public function hasDelay()
1676  {
1677  global $conf;
1678 
1679  $now = dol_now();
1680 
1681  return $this->datep && ($this->datep < ($now - $conf->agenda->warning_delay));
1682  }
1683 
1684 
1691  public function sendEmailsReminder()
1692  {
1693  global $conf, $langs;
1694 
1695  $error = 0;
1696  $this->output = '';
1697  $this->error='';
1698 
1699  if (empty($conf->agenda->enabled)) // Should not happen. If module disabled, cron job should not be visible.
1700  {
1701  $langs->load("agenda");
1702  $this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
1703  return 0;
1704  }
1705  if (empty($conf->global->AGENDA_REMINDER_EMAIL))
1706  {
1707  $langs->load("agenda");
1708  $this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
1709  return 0;
1710  }
1711 
1712  $now = dol_now();
1713 
1714  dol_syslog(__METHOD__, LOG_DEBUG);
1715 
1716  $this->db->begin();
1717 
1718  // TODO Scan events of type 'email' into table llx_actioncomm_reminder with status todo, send email, then set status to done
1719 
1720  // Delete also very old past events (we do not keep more than 1 month record in past)
1721  $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder WHERE dateremind < '".$this->db->jdate($now - (3600 * 24 * 32))."'";
1722  $this->db->query($sql);
1723 
1724  $this->db->commit();
1725 
1726  return $error;
1727  }
1728 }
Class to manage different types of events.
print $object label
hash of file content (md5_file(dol_osencode($destfull))
Definition: edit.php:153
fetch_userassigned()
Initialize this->userassigned array with list of id of user assigned to event.
fetch($id, $ref='', $ref_ext='')
Load object from database.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;...&#39; if string larger than length.
if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) if(! empty($conf->don->enabled) && $user->rights->societe->lire) if(! empty($conf->tax->enabled) && $user->rights->tax->charges->lire) if(! empty($conf->facture->enabled) &&! empty($conf->commande->enabled) && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1053
Class to manage agenda events (actions)
createFromClone($fuser, $socid)
Load an object from its id and create a new one in database.
build_rssfile($format, $title, $desc, $events_array, $outputfile, $filter='')
Build a file from an array of events.
Definition: xcal.lib.php:295
if(! empty($search_group)) natural_search(array("g.nom" g note
Definition: list.php:123
create(User $user, $notrigger=0)
Add an action/event into database.
fetchResources()
Initialize $this->userassigned & this->socpeopleassigned array with list of id of user and contact as...
Class to manage Dolibarr users.
Definition: user.class.php:41
Class to manage Dolibarr database access.
info($id)
Charge les informations d&#39;ordre info dans l&#39;objet facture.
load_board($user, $load_state_board=0)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition: date.lib.php:453
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
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
LibStatut($percent, $mode, $hidenastatus=0, $datestart='')
Return label of action status.
__construct(DoliDB $db)
Constructor.
sendEmailsReminder()
Send reminders by emails CAN BE A CRON TASK.
dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=1)
Move a file into another name.
Definition: files.lib.php:814
initAsSpecimen()
Initialise an instance with random values.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
type
Definition: viewcat.php:284
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
update($user, $notrigger=0)
Update action into database If percentage = 100, on met a jour date 100%.
static commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1)
Remove a file or several files with a mask.
Definition: files.lib.php:1139
deleteExtraFields()
Delete all extra fields values for the current object.
if(GETPOST('cancel', 'alpha')) if(! GETPOST( 'confirmmassaction', 'alpha') &&$massaction !='presend' &&$massaction !='confirm_presend')
Draft customers invoices.
Definition: list.php:156
dol_now($mode='gmt')
Return date for now.
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...
hasDelay()
Is the action delayed?
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition: date.lib.php:467
static getActions($db, $socid=0, $fk_element=0, $elementtype='', $filter='', $sortfield='a.datep', $sortorder='DESC', $limit=0)
Load all objects with filters.
add(User $user, $notrigger=0)
Add an action/event into database.
dol_filemtime($pathoffile)
Return time of a file.
Definition: files.lib.php:564
dol_mkdir($dir, $dataroot='', $newmask=null)
Creation of a directory (this can create recursive subdir)
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
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.
getLibStatut($mode, $hidenastatus=0)
Return label of status.
call_trigger($trigger_name, $user)
Call trigger based on this instance.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='')
Show picto whatever it&#39;s its name (generic function)
build_exportfile($format, $type, $cachedelay, $filename, $filters)
Export events from database into a cal file.
Parent class of all other business classes (invoices, contracts, proposals, orders, ...)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
static replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.