Passed
Branch develop (7b8a20)
by
unknown
32:48
created

ActionComm::loadReminders()   B

Complexity

Conditions 7

Size

Total Lines 43
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 29
nop 2
dl 0
loc 43
rs 8.5226
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2002-2004  Rodolphe Quiedeville    <[email protected]>
3
 * Copyright (C) 2004-2011  Laurent Destailleur     <[email protected]>
4
 * Copyright (C) 2005-2012  Regis Houssin           <[email protected]>
5
 * Copyright (C) 2011-2017  Juanjo Menent           <[email protected]>
6
 * Copyright (C) 2015	    Marcos García		    <[email protected]>
7
 * Copyright (C) 2018	    Nicolas ZABOURI	        <[email protected]>
8
 * Copyright (C) 2018-2020  Frédéric France         <[email protected]>
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 <https://www.gnu.org/licenses/>.
22
 */
23
24
/**
25
 *       \file       htdocs/comm/action/class/actioncomm.class.php
26
 *       \ingroup    agenda
27
 *       \brief      File of class to manage agenda events (actions)
28
 */
29
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php';
30
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
31
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
32
require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
33
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncommreminder.class.php';
34
35
36
/**
37
 *		Class to manage agenda events (actions)
38
 */
39
class ActionComm extends CommonObject
40
{
41
	/**
42
	 * @var string ID to identify managed object
43
	 */
44
	public $element = 'action';
45
46
	/**
47
	 * @var string Name of table without prefix where object is stored
48
	 */
49
	public $table_element = 'actioncomm';
50
51
	/**
52
	 * @var string Name of id column
53
	 */
54
	public $table_rowid = 'id';
55
56
	/**
57
	 * @var string Name of icon for actioncomm object. Filename of icon is object_action.png
58
	 */
59
	public $picto = 'action';
60
61
	/**
62
	 * @var int 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
63
	 */
64
	public $ismultientitymanaged = 1;
65
66
	/**
67
	 * @var integer 0=Default
68
	 *              1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
69
	 *              2=Same than 1 but accept record if fksoc is empty
70
	 */
71
	public $restrictiononfksoc = 2;
72
73
	/**
74
	 * @var int Id of the event
75
	 */
76
	public $id;
77
78
	/**
79
	 * @var int Id of the event. Use $id as possible
80
	 */
81
	public $ref;
82
83
	/**
84
	 * @var int Id into parent table llx_c_actioncomm (used only if option to use type is set)
85
	 */
86
	public $type_id;
87
88
	/**
89
	 * @var string 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.
90
	 */
91
	public $type_code;
92
93
	/**
94
	 * @var string Type label
95
	 */
96
	public $type_label;
97
98
	/**
99
	 * @var string Label into parent table llx_c_actioncomm (used only if option to use type is set)
100
	 */
101
	public $type;
102
103
	/**
104
	 * @var string Color into parent table llx_c_actioncomm (used only if option to use type is set)
105
	 */
106
	public $type_color;
107
108
	/**
109
	 * @var string Free code to identify action. Ie: Agenda trigger add here AC_TRIGGERNAME ('AC_COMPANY_CREATE', 'AC_PROPAL_VALIDATE', ...)
110
	 */
111
	public $code;
112
113
	/**
114
	 * @var string Agenda event label
115
	 */
116
	public $label;
117
118
	/**
119
	 * @var integer Date creation record (datec)
120
	 */
121
	public $datec;
122
123
	/**
124
	 * @var integer Date end record (datef)
125
	 */
126
	public $datef;
127
128
	/**
129
	 * @var integer Duration (duree)
130
	 */
131
	public $duree;
132
133
	/**
134
	 * @var integer Date modification record (tms)
135
	 */
136
	public $datem;
137
138
	/**
139
	 * @var User Object user that create action
140
	 * @deprecated
141
	 * @see $authorid
142
	 */
143
	public $author;
144
145
	/**
146
	 * @var User Object user that modified action
147
	 * @deprecated
148
	 * @see $usermodid
149
	 */
150
	public $usermod;
151
152
	/**
153
	 * @var int Id user that create action
154
	 */
155
	public $authorid;
156
157
	/**
158
	 * @var int Id user that modified action
159
	 */
160
	public $usermodid;
161
162
	/**
163
	 * @var integer Date action start (datep)
164
	 */
165
	public $datep;
166
167
	/**
168
	 * @var integer Date action end (datep2)
169
	 */
170
	public $datep2;
171
172
	/**
173
	 * @var int -1=Unkown duration
174
	 * @deprecated
175
	 */
176
	public $durationp = -1;
177
178
	/**
179
	 * @var int 1=Event on full day
180
	 */
181
	public $fulldayevent = 0;
182
183
	/**
184
	 * @var integer Percentage
185
	 */
186
	public $percentage;
187
188
	/**
189
	 * @var string Location
190
	 */
191
	public $location;
192
193
	/**
194
	 * @var int 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)
195
	 */
196
	public $transparency;
197
198
	/**
199
	 * @var int (0 By default)
200
	 */
201
	public $priority;
202
203
	/**
204
	 * @var int[] Array of user ids
205
	 */
206
	public $userassigned = array();
207
208
	/**
209
	 * @var int Id of user owner = fk_user_action into table
210
	 */
211
	public $userownerid;
212
213
	/**
214
	 * @var int Id of user done (deprecated)
215
	 * @deprecated
216
	 */
217
	public $userdoneid;
218
219
	/**
220
	 * @var int[] Array of contact ids
221
	 */
222
	public $socpeopleassigned = array();
223
224
	/**
225
	 * @var int[] Array of other contact emails (not user, not contact)
226
	 */
227
	public $otherassigned = array();
228
229
	/**
230
	 * @var array	Array of reminders
231
	 */
232
	public $reminders = array();
233
234
	/**
235
	 * @var User Object user of owner
236
	 * @deprecated
237
	 * @see $userownerid
238
	 */
239
	public $usertodo;
240
241
	/**
242
	 * @var User Object user that did action
243
	 * @deprecated
244
	 * @see $userdoneid
245
	 */
246
	public $userdone;
247
248
	/**
249
	 * @var int thirdparty id linked to action
250
	 */
251
	public $socid;
252
253
	/**
254
	 * @var int socpeople id linked to action
255
	 */
256
	public $contactid;
257
258
	/**
259
	 * @var Societe|null Company linked to action (optional)
260
	 * @deprecated
261
	 * @see $socid
262
	 */
263
	public $societe;
264
265
	/**
266
	 * @var Contact|null Contact linked to action (optional)
267
	 * @deprecated
268
	 * @see $contactid
269
	 */
270
	public $contact;
271
272
	// Properties for links to other objects
273
	/**
274
	 * @var int Id of linked object
275
	 */
276
	public $fk_element; // Id of record
277
278
	/**
279
	 * @var int Id of record alternative for API
280
	 */
281
	public $elementid;
282
283
	/**
284
	 * @var string Type of record. This if property ->element of object linked to.
285
	 */
286
	public $elementtype;
287
288
	/**
289
	 * @var string Ical name
290
	 */
291
	public $icalname;
292
293
	/**
294
	 * @var string Ical color
295
	 */
296
	public $icalcolor;
297
298
	/**
299
	 * @var string Extraparam
300
	 */
301
	public $extraparams;
302
303
	/**
304
	 * @var array Actions
305
	 */
306
	public $actions = array();
307
308
	/**
309
	 * @var string Email msgid
310
	 */
311
	public $email_msgid;
312
313
	/**
314
	 * @var string Email from
315
	 */
316
	public $email_from;
317
318
	/**
319
	 * @var string Email sender
320
	 */
321
	public $email_sender;
322
323
	/**
324
	 * @var string Email to
325
	 */
326
	public $email_to;
327
328
	/**
329
	 * @var string Email tocc
330
	 */
331
	public $email_tocc;
332
	/**
333
	 * @var string Email tobcc
334
	 */
335
	public $email_tobcc;
336
337
	/**
338
	 * @var string Email subject
339
	 */
340
	public $email_subject;
341
342
	/**
343
	 * @var string Email errors to
344
	 */
345
	public $errors_to;
346
347
	/**
348
	 * Typical value for a event that is in a todo state
349
	 */
350
	const EVENT_TODO = 0;
351
352
	/**
353
	 * Typical value for a event that is in a progress state
354
	 */
355
	const EVENT_IN_PROGRESS = 50;
356
357
	/**
358
	 * Typical value for a event that is in a finished state
359
	 */
360
	const EVENT_FINISHED = 100;
361
362
	/**
363
	 *      Constructor
364
	 *
365
	 *      @param      DoliDB		$db      Database handler
366
	 */
367
	public function __construct(DoliDB $db)
368
	{
369
		$this->db = $db;
370
	}
371
372
	/**
373
	 *    Add an action/event into database.
374
	 *    $this->type_id OR $this->type_code must be set.
375
	 *
376
	 *    @param	User	$user      		Object user making action
377
	 *    @param    int		$notrigger		1 = disable triggers, 0 = enable triggers
378
	 *    @return   int 		        	Id of created event, < 0 if KO
379
	 */
380
	public function create(User $user, $notrigger = 0)
381
	{
382
		global $langs, $conf, $hookmanager;
383
384
		$error = 0;
385
		$now = dol_now();
386
387
		// Check parameters
388
		if (!isset($this->userownerid) || $this->userownerid === '')	// $this->userownerid may be 0 (anonymous event) of > 0
389
		{
390
			dol_syslog("You tried to create an event but mandatory property ownerid was not defined", LOG_WARNING);
391
			$this->errors[] = 'ErrorPropertyUserowneridNotDefined';
392
			return -1;
393
		}
394
395
		// Clean parameters
396
		$this->label = dol_trunc(trim($this->label), 128);
397
		$this->location = dol_trunc(trim($this->location), 128);
398
		$this->note_private = dol_htmlcleanlastbr(trim(empty($this->note_private) ? $this->note : $this->note_private));
399
		if (empty($this->percentage))   $this->percentage = 0;
400
		if (empty($this->priority) || !is_numeric($this->priority)) $this->priority = 0;
401
		if (empty($this->fulldayevent)) $this->fulldayevent = 0;
402
		if (empty($this->transparency)) $this->transparency = 0;
403
		if ($this->percentage > 100) $this->percentage = 100;
404
		//if ($this->percentage == 100 && ! $this->dateend) $this->dateend = $this->date;
405
		if (!empty($this->datep) && !empty($this->datef))   $this->durationp = ($this->datef - $this->datep); // deprecated
406
		//if (! empty($this->date)  && ! empty($this->dateend)) $this->durationa=($this->dateend - $this->date);
407
		if (!empty($this->datep) && !empty($this->datef) && $this->datep > $this->datef) $this->datef = $this->datep;
408
		//if (! empty($this->date)  && ! empty($this->dateend) && $this->date > $this->dateend) $this->dateend=$this->date;
409
		if (!isset($this->fk_project) || $this->fk_project < 0) $this->fk_project = 0;
410
		// For backward compatibility
411
		if ($this->elementtype == 'facture')  $this->elementtype = 'invoice';
412
		if ($this->elementtype == 'commande') $this->elementtype = 'order';
413
		if ($this->elementtype == 'contrat')  $this->elementtype = 'contract';
414
415
		if (!is_array($this->userassigned) && !empty($this->userassigned))	// For backward compatibility when userassigned was an int instead fo array
416
		{
417
			$tmpid = $this->userassigned;
418
			$this->userassigned = array();
419
			$this->userassigned[$tmpid] = array('id'=>$tmpid, 'transparency'=>$this->transparency);
420
		}
421
422
		$userownerid = $this->userownerid;
423
		$userdoneid = $this->userdoneid;
424
425
		// Be sure assigned user is defined as an array of array('id'=>,'mandatory'=>,...).
426
		if (empty($this->userassigned) || count($this->userassigned) == 0 || !is_array($this->userassigned))
427
			$this->userassigned = array($userownerid=>array('id'=>$userownerid, 'transparency'=>$this->transparency));
428
429
		if (!$this->type_id || !$this->type_code)
430
		{
431
			$key = empty($this->type_id) ? $this->type_code : $this->type_id;
432
433
			// Get id from code
434
			$cactioncomm = new CActionComm($this->db);
435
			$result = $cactioncomm->fetch($key);
436
437
			if ($result > 0)
438
			{
439
				$this->type_id = $cactioncomm->id;
440
				$this->type_code = $cactioncomm->code;
441
			} elseif ($result == 0)
442
			{
443
				$this->error = 'Failed to get record with id '.$this->type_id.' code '.$this->type_code.' from dictionary "type of events"';
444
				return -1;
445
			} else {
446
				$this->error = $cactioncomm->error;
447
				return -1;
448
			}
449
		}
450
		$code = empty($this->code) ? $this->type_code : $this->code;
451
452
		// Check parameters
453
		if (!$this->type_id)
454
		{
455
			$this->error = "ErrorWrongParameters";
456
			return -1;
457
		}
458
459
		$this->db->begin();
460
461
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm";
462
		$sql .= "(datec,";
463
		$sql .= "datep,";
464
		$sql .= "datep2,";
465
		$sql .= "durationp,"; // deprecated
466
		$sql .= "fk_action,";
467
		$sql .= "code,";
468
	 	$sql .= "ref_ext,";
469
		$sql .= "fk_soc,";
470
		$sql .= "fk_project,";
471
		$sql .= "note,";
472
		$sql .= "fk_contact,";
473
		$sql .= "fk_user_author,";
474
		$sql .= "fk_user_action,";
475
		$sql .= "fk_user_done,";
476
		$sql .= "label,percent,priority,fulldayevent,location,";
477
		$sql .= "transparency,";
478
		$sql .= "fk_element,";
479
		$sql .= "elementtype,";
480
		$sql .= "entity,";
481
		$sql .= "extraparams,";
482
		// Fields emails
483
		$sql .= "email_msgid,";
484
		$sql .= "email_from,";
485
		$sql .= "email_sender,";
486
		$sql .= "email_to,";
487
		$sql .= "email_tocc,";
488
		$sql .= "email_tobcc,";
489
		$sql .= "email_subject,";
490
		$sql .= "errors_to";
491
		$sql .= ") VALUES (";
492
		$sql .= "'".$this->db->idate($now)."', ";
493
		$sql .= (strval($this->datep) != '' ? "'".$this->db->idate($this->datep)."'" : "null").", ";
494
		$sql .= (strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : "null").", ";
495
		$sql .= ((isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '') ? "'".$this->db->escape($this->durationp)."'" : "null").", "; // deprecated
496
		$sql .= (isset($this->type_id) ? $this->type_id : "null").",";
497
		$sql .= ($code ? ("'".$this->db->escape($code)."'") : "null").", ";
498
		$sql .= ($this->ref_ext ? ("'".$this->db->idate($this->ref_ext)."'") : "null").", ";
499
		$sql .= ((isset($this->socid) && $this->socid > 0) ? $this->socid : "null").", ";
500
		$sql .= ((isset($this->fk_project) && $this->fk_project > 0) ? $this->fk_project : "null").", ";
501
		$sql .= " '".$this->db->escape($this->note_private)."', ";
502
		$sql .= ((isset($this->contact_id) && $this->contact_id > 0) ? $this->contact_id : "null").", "; // deprecated, use ->socpeopleassigned
503
		$sql .= (isset($user->id) && $user->id > 0 ? $user->id : "null").", ";
504
		$sql .= ($userownerid > 0 ? $userownerid : "null").", ";
505
		$sql .= ($userdoneid > 0 ? $userdoneid : "null").", ";
506
		$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)."', ";
507
		$sql .= "'".$this->db->escape($this->transparency)."', ";
508
		$sql .= (!empty($this->fk_element) ? $this->fk_element : "null").", ";
509
		$sql .= (!empty($this->elementtype) ? "'".$this->db->escape($this->elementtype)."'" : "null").", ";
510
		$sql .= $conf->entity.",";
511
		$sql .= (!empty($this->extraparams) ? "'".$this->db->escape($this->extraparams)."'" : "null").", ";
512
		// Fields emails
513
		$sql .= (!empty($this->email_msgid) ? "'".$this->db->escape($this->email_msgid)."'" : "null").", ";
514
		$sql .= (!empty($this->email_from) ? "'".$this->db->escape($this->email_from)."'" : "null").", ";
515
		$sql .= (!empty($this->email_sender) ? "'".$this->db->escape($this->email_sender)."'" : "null").", ";
516
		$sql .= (!empty($this->email_to) ? "'".$this->db->escape($this->email_to)."'" : "null").", ";
517
		$sql .= (!empty($this->email_tocc) ? "'".$this->db->escape($this->email_tocc)."'" : "null").", ";
518
		$sql .= (!empty($this->email_tobcc) ? "'".$this->db->escape($this->email_tobcc)."'" : "null").", ";
519
		$sql .= (!empty($this->email_subject) ? "'".$this->db->escape($this->email_subject)."'" : "null").", ";
520
		$sql .= (!empty($this->errors_to) ? "'".$this->db->escape($this->errors_to)."'" : "null");
521
		$sql .= ")";
522
523
		dol_syslog(get_class($this)."::add", LOG_DEBUG);
524
		$resql = $this->db->query($sql);
525
		if ($resql)
526
		{
527
			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."actioncomm", "id");
528
529
			// Now insert assigned users
530
			if (!$error)
531
			{
532
				//dol_syslog(var_export($this->userassigned, true));
533
				foreach ($this->userassigned as $key => $val)
534
				{
535
					if (!is_array($val))	// For backward compatibility when val=id
536
					{
537
						$val = array('id'=>$val);
538
					}
539
540
					if ($val['id'] > 0)
541
					{
542
						$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
543
						$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']).")";
544
545
						$resql = $this->db->query($sql);
546
						if (!$resql)
547
						{
548
							$error++;
549
							dol_syslog('Error to process userassigned: '.$this->db->lasterror(), LOG_ERR);
550
					   		$this->errors[] = $this->db->lasterror();
551
						}
552
						//var_dump($sql);exit;
553
					}
554
				}
555
			}
556
557
			if (!$error)
558
			{
559
				if (!empty($this->socpeopleassigned))
560
				{
561
					foreach ($this->socpeopleassigned as $id => $val)
562
					{
563
						$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
564
						$sql .= " VALUES(".$this->id.", 'socpeople', ".$id.", 0, 0, 0)";
565
566
						$resql = $this->db->query($sql);
567
						if (!$resql)
568
						{
569
							$error++;
570
							dol_syslog('Error to process socpeopleassigned: '.$this->db->lasterror(), LOG_ERR);
571
							$this->errors[] = $this->db->lasterror();
572
						}
573
					}
574
				}
575
			}
576
577
			if (!$error)
578
			{
579
				// Actions on extra fields
580
		   		$result = $this->insertExtraFields();
581
		   		if ($result < 0)
582
		   		{
583
		   			$error++;
584
		   		}
585
			}
586
587
			if (!$error && !$notrigger)
588
			{
589
				// Call trigger
590
				$result = $this->call_trigger('ACTION_CREATE', $user);
591
				if ($result < 0) { $error++; }
592
				// End call triggers
593
			}
594
595
			if (!$error)
596
			{
597
				$this->db->commit();
598
				return $this->id;
599
			} else {
600
				$this->db->rollback();
601
				return -1;
602
			}
603
		} else {
604
			$this->db->rollback();
605
			$this->error = $this->db->lasterror();
606
			return -1;
607
		}
608
	}
609
610
	/**
611
	 *  Load an object from its id and create a new one in database
612
	 *
613
	 *  @param	    User	        $fuser      	Object user making action
614
	 *  @param		int				$socid			Id of thirdparty
615
	 *  @return		int								New id of clone
616
	 */
617
	public function createFromClone(User $fuser, $socid)
618
	{
619
		global $db, $conf, $hookmanager;
620
621
		$error = 0;
622
		$now = dol_now();
623
624
		$this->db->begin();
625
626
		// Load source object
627
		$objFrom = clone $this;
628
629
		// Retreive all extrafield
630
		// fetch optionals attributes and labels
631
		$this->fetch_optionals();
632
633
		//$this->fetch_userassigned();
634
		$this->fetchResources();
635
636
		$this->id = 0;
637
638
		// Create clone
639
		$this->context['createfromclone'] = 'createfromclone';
640
		$result = $this->create($fuser);
641
		if ($result < 0) $error++;
642
643
		if (!$error)
644
		{
645
			// Hook of thirdparty module
646
			if (is_object($hookmanager))
647
			{
648
				$parameters = array('objFrom'=>$objFrom);
649
				$action = '';
650
				$reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
651
				if ($reshook < 0) $error++;
652
			}
653
654
			// Call trigger
655
			$result = $this->call_trigger('ACTION_CLONE', $fuser);
656
			if ($result < 0) { $error++; }
657
			// End call triggers
658
		}
659
660
		unset($this->context['createfromclone']);
661
662
		// End
663
		if (!$error)
664
		{
665
			$this->db->commit();
666
			return $this->id;
667
		} else {
668
			$this->db->rollback();
669
			return -1;
670
		}
671
	}
672
673
	/**
674
	 *  Load object from database
675
	 *
676
	 *  @param  int		$id     		Id of action to get
677
	 *  @param  string	$ref    		Ref of action to get
678
	 *  @param  string	$ref_ext		Ref ext to get
679
	 *  @param	string	$email_msgid	Email msgid
680
	 *  @return	int						<0 if KO, >0 if OK
681
	 */
682
	public function fetch($id, $ref = '', $ref_ext = '', $email_msgid = '')
683
	{
684
		global $langs;
685
686
		$sql = "SELECT a.id,";
687
		$sql .= " a.id as ref,";
688
		$sql .= " a.entity,";
689
		$sql .= " a.ref_ext,";
690
		$sql .= " a.datep,";
691
		$sql .= " a.datep2,";
692
		$sql .= " a.durationp,"; // deprecated
693
		$sql .= " a.datec,";
694
		$sql .= " a.tms as datem,";
695
		$sql .= " a.code, a.label, a.note,";
696
		$sql .= " a.fk_soc,";
697
		$sql .= " a.fk_project,";
698
		$sql .= " a.fk_user_author, a.fk_user_mod,";
699
		$sql .= " a.fk_user_action, a.fk_user_done,";
700
		$sql .= " a.fk_contact, a.percent as percentage,";
701
		$sql .= " a.fk_element as elementid, a.elementtype,";
702
		$sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
703
		$sql .= " a.email_msgid, a.email_subject, a.email_from, a.email_to, a.email_tocc, a.email_tobcc, a.errors_to,";
704
		$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,";
705
		$sql .= " s.nom as socname,";
706
		$sql .= " u.firstname, u.lastname as lastname";
707
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a ";
708
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action=c.id ";
709
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author";
710
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
711
		$sql .= " WHERE ";
712
		if ($ref) $sql .= " a.id = ".((int) $ref); // No field ref, we use id
713
		elseif ($ref_ext) $sql .= " a.ref_ext = '".$this->db->escape($ref_ext)."'";
714
		elseif ($email_msgid) $sql .= " a.email_msgid = '".$this->db->escape($email_msgid)."'";
715
		else $sql .= " a.id = ".((int) $id);
716
717
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
718
		$resql = $this->db->query($sql);
719
		if ($resql)
720
		{
721
			$num = $this->db->num_rows($resql);
722
			if ($num)
723
			{
724
				$obj = $this->db->fetch_object($resql);
725
726
				$this->id         = $obj->id;
727
				$this->entity = $obj->entity;
728
				$this->ref        = $obj->ref;
729
				$this->ref_ext    = $obj->ref_ext;
730
731
				// Properties of parent table llx_c_actioncomm
732
				$this->type_id    = $obj->type_id;
733
				$this->type_code  = $obj->type_code;
734
				$this->type_color = $obj->type_color;
735
				$this->type_picto = $obj->type_picto;
736
				$transcode = $langs->trans("Action".$obj->type_code);
737
				$this->type       = (($transcode != "Action".$obj->type_code) ? $transcode : $obj->type_label);
738
				$transcode = $langs->trans("Action".$obj->type_code.'Short');
739
				$this->type_short = (($transcode != "Action".$obj->type_code.'Short') ? $transcode : '');
740
741
				$this->code = $obj->code;
742
				$this->label = $obj->label;
743
				$this->datep = $this->db->jdate($obj->datep);
744
				$this->datef = $this->db->jdate($obj->datep2);
745
746
				$this->datec = $this->db->jdate($obj->datec);
747
				$this->datem = $this->db->jdate($obj->datem);
748
749
				$this->note = $obj->note; // deprecated
750
				$this->note_private = $obj->note;
751
				$this->percentage = $obj->percentage;
752
753
				$this->authorid = $obj->fk_user_author;
754
				$this->usermodid = $obj->fk_user_mod;
755
756
				if (!is_object($this->author)) $this->author = new stdClass(); // To avoid warning
757
				$this->author->id = $obj->fk_user_author; // deprecated
758
				$this->author->firstname = $obj->firstname; // deprecated
759
				$this->author->lastname = $obj->lastname; // deprecated
760
				if (!is_object($this->usermod)) $this->usermod = new stdClass(); // To avoid warning
761
				$this->usermod->id = $obj->fk_user_mod; // deprecated
762
763
				$this->userownerid = $obj->fk_user_action;
764
				$this->userdoneid = $obj->fk_user_done;
765
				$this->priority				= $obj->priority;
766
				$this->fulldayevent			= $obj->fulldayevent;
767
				$this->location				= $obj->location;
768
				$this->transparency			= $obj->transparency;
769
770
				$this->socid = $obj->fk_soc; // To have fetch_thirdparty method working
771
				$this->contact_id = $obj->fk_contact; // To have fetch_contact method working
772
				$this->fk_project = $obj->fk_project; // To have fetch_projet method working
773
774
				//$this->societe->id			= $obj->fk_soc;			// deprecated
775
				//$this->contact->id			= $obj->fk_contact;		// deprecated
776
777
				$this->fk_element = $obj->elementid;
778
				$this->elementid = $obj->elementid;
779
				$this->elementtype = $obj->elementtype;
780
781
				$this->fetchResources();
782
			}
783
			$this->db->free($resql);
784
		} else {
785
			$this->error = $this->db->lasterror();
786
			return -1;
787
		}
788
789
		return $num;
790
	}
791
792
	/**
793
	 *    Initialize $this->userassigned & this->socpeopleassigned array with list of id of user and contact assigned to event
794
	 *
795
	 *    @return   int				<0 if KO, >0 if OK
796
	 */
797
	public function fetchResources()
798
	{
799
		$this->userassigned = array();
800
		$this->socpeopleassigned = array();
801
802
		$sql = 'SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency';
803
		$sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm_resources';
804
		$sql .= ' WHERE fk_actioncomm = '.$this->id;
805
		$sql .= " AND element_type IN ('user', 'socpeople')";
806
		$resql = $this->db->query($sql);
807
		if ($resql)
808
		{
809
			// If owner is known, we must but id first into list
810
			if ($this->userownerid > 0) $this->userassigned[$this->userownerid] = array('id'=>$this->userownerid); // Set first so will be first into list.
811
812
			while ($obj = $this->db->fetch_object($resql))
813
			{
814
				if ($obj->fk_element > 0)
815
				{
816
					switch ($obj->element_type) {
817
						case 'user':
818
							$this->userassigned[$obj->fk_element] = array('id'=>$obj->fk_element, 'mandatory'=>$obj->mandatory, 'answer_status'=>$obj->answer_status, 'transparency'=>$obj->transparency);
819
							if (empty($this->userownerid)) $this->userownerid = $obj->fk_element; // If not defined (should not happened, we fix this)
820
							break;
821
						case 'socpeople':
822
							$this->socpeopleassigned[$obj->fk_element] = array('id'=>$obj->fk_element, 'mandatory'=>$obj->mandatory, 'answer_status'=>$obj->answer_status, 'transparency'=>$obj->transparency);
823
							break;
824
					}
825
				}
826
			}
827
828
			return 1;
829
		} else {
830
			dol_print_error($this->db);
831
			return -1;
832
		}
833
	}
834
835
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
836
	/**
837
	 *    Initialize this->userassigned array with list of id of user assigned to event
838
	 *
839
	 *    @param    bool    $override   Override $this->userownerid when empty. TODO This should be false by default. True is here to fix corrupted data.
840
	 *    @return   int                 <0 if KO, >0 if OK
841
	 */
842
	public function fetch_userassigned($override = true)
843
	{
844
		// phpcs:enable
845
		$sql = "SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency";
846
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm_resources";
847
		$sql .= " WHERE element_type = 'user' AND fk_actioncomm = ".$this->id;
848
849
		$resql2 = $this->db->query($sql);
850
		if ($resql2)
851
		{
852
			$this->userassigned = array();
853
854
			// If owner is known, we must but id first into list
855
			if ($this->userownerid > 0)
856
			{
857
				// Set first so will be first into list.
858
				$this->userassigned[$this->userownerid] = array('id'=>$this->userownerid);
859
			}
860
861
			while ($obj = $this->db->fetch_object($resql2))
862
			{
863
				if ($obj->fk_element > 0)
864
				{
865
					$this->userassigned[$obj->fk_element] = array('id'=>$obj->fk_element,
866
																  'mandatory'=>$obj->mandatory,
867
																  'answer_status'=>$obj->answer_status,
868
																  'transparency'=>$obj->transparency);
869
				}
870
871
				if ($override === true)
872
				{
873
					// If not defined (should not happened, we fix this)
874
					if (empty($this->userownerid))
875
					{
876
						$this->userownerid = $obj->fk_element;
877
					}
878
				}
879
			}
880
881
			return 1;
882
		} else {
883
			dol_print_error($this->db);
884
			return -1;
885
		}
886
	}
887
888
	/**
889
	 *    Delete event from database
890
	 *
891
	 *    @param    int		$notrigger		1 = disable triggers, 0 = enable triggers
892
	 *    @return   int 					<0 if KO, >0 if OK
893
	 */
894
	public function delete($notrigger = 0)
895
	{
896
		global $user;
897
898
		$error = 0;
899
900
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
901
902
		$this->db->begin();
903
904
		// remove categorie association
905
		if (!$error) {
906
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_actioncomm";
907
			$sql .= " WHERE fk_actioncomm=".$this->id;
908
909
			$res = $this->db->query($sql);
910
			if (!$res) {
911
				$this->error = $this->db->lasterror();
912
				$error++;
913
			}
914
		}
915
916
		// remove actioncomm_resources
917
		if (!$error) {
918
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources";
919
			$sql .= " WHERE fk_actioncomm=".$this->id;
920
921
			$res = $this->db->query($sql);
922
			if (!$res) {
923
				$this->error = $this->db->lasterror();
924
				$error++;
925
			}
926
		}
927
928
		// Removed extrafields
929
		if (!$error) {
930
			  $result = $this->deleteExtraFields();
931
		  	if ($result < 0)
932
		   	{
933
		   		$error++;
934
		   		dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
935
		   	}
936
		}
937
938
		// remove actioncomm
939
		if (!$error) {
940
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm";
941
			$sql .= " WHERE id=".$this->id;
942
943
			$res = $this->db->query($sql);
944
			if (!$res) {
945
				$this->error = $this->db->lasterror();
946
				$error++;
947
			}
948
		}
949
950
		if (!$error)
951
		{
952
			if (!$notrigger)
953
			{
954
				// Call trigger
955
				$result = $this->call_trigger('ACTION_DELETE', $user);
956
				if ($result < 0) { $error++; }
957
				// End call triggers
958
			}
959
960
			if (!$error)
961
			{
962
				$this->db->commit();
963
				return 1;
964
			} else {
965
				$this->db->rollback();
966
				return -2;
967
			}
968
		} else {
969
			$this->db->rollback();
970
			$this->error = $this->db->lasterror();
971
			return -1;
972
		}
973
	}
974
975
	/**
976
	 *    Update action into database
977
	 *	  If percentage = 100, on met a jour date 100%
978
	 *
979
	 *    @param    User	$user			Object user making change
980
	 *    @param    int		$notrigger		1 = disable triggers, 0 = enable triggers
981
	 *    @return   int     				<0 if KO, >0 if OK
982
	 */
983
	public function update($user, $notrigger = 0)
984
	{
985
		global $langs, $conf, $hookmanager;
986
987
		$error = 0;
988
989
		// Clean parameters
990
		$this->label = trim($this->label);
991
		$this->note_private = dol_htmlcleanlastbr(trim(empty($this->note_private) ? $this->note : $this->note_private));
992
		if (empty($this->percentage))    $this->percentage = 0;
993
		if (empty($this->priority) || !is_numeric($this->priority)) $this->priority = 0;
994
		if (empty($this->transparency))  $this->transparency = 0;
995
		if (empty($this->fulldayevent))  $this->fulldayevent = 0;
996
		if ($this->percentage > 100) $this->percentage = 100;
997
		//if ($this->percentage == 100 && ! $this->dateend) $this->dateend = $this->date;
998
		if ($this->datep && $this->datef)   $this->durationp = ($this->datef - $this->datep); // deprecated
1 ignored issue
show
Deprecated Code introduced by
The property ActionComm::$durationp has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

998
		if ($this->datep && $this->datef)   /** @scrutinizer ignore-deprecated */ $this->durationp = ($this->datef - $this->datep); // deprecated
Loading history...
999
		//if ($this->date  && $this->dateend) $this->durationa=($this->dateend - $this->date);
1000
		if ($this->datep && $this->datef && $this->datep > $this->datef) $this->datef = $this->datep;
1001
		//if ($this->date  && $this->dateend && $this->date > $this->dateend) $this->dateend=$this->date;
1002
		if ($this->fk_project < 0) $this->fk_project = 0;
1003
1004
		// Check parameters
1005
		if ($this->percentage == 0 && $this->userdoneid > 0)
1 ignored issue
show
Deprecated Code introduced by
The property ActionComm::$userdoneid has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1005
		if ($this->percentage == 0 && /** @scrutinizer ignore-deprecated */ $this->userdoneid > 0)
Loading history...
1006
		{
1007
			$this->error = "ErrorCantSaveADoneUserWithZeroPercentage";
1008
			return -1;
1009
		}
1010
1011
		$socid = (($this->socid > 0) ? $this->socid : 0);
1012
		$contactid = (($this->contact_id > 0) ? $this->contact_id : 0);
1013
		$userownerid = ($this->userownerid ? $this->userownerid : 0);
1014
		$userdoneid = ($this->userdoneid ? $this->userdoneid : 0);
1 ignored issue
show
Deprecated Code introduced by
The property ActionComm::$userdoneid has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1014
		$userdoneid = ($this->userdoneid ? /** @scrutinizer ignore-deprecated */ $this->userdoneid : 0);
Loading history...
1015
1016
		$this->db->begin();
1017
1018
		$sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm ";
1019
		$sql .= " SET percent = '".$this->db->escape($this->percentage)."'";
1020
		if ($this->type_id > 0) $sql .= ", fk_action = '".$this->db->escape($this->type_id)."'";
1021
		$sql .= ", label = ".($this->label ? "'".$this->db->escape($this->label)."'" : "null");
1022
		$sql .= ", datep = ".(strval($this->datep) != '' ? "'".$this->db->idate($this->datep)."'" : 'null');
1023
		$sql .= ", datep2 = ".(strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : 'null');
1024
		$sql .= ", durationp = ".(isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '' ? "'".$this->db->escape($this->durationp)."'" : "null"); // deprecated
1 ignored issue
show
Deprecated Code introduced by
The property ActionComm::$durationp has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1024
		$sql .= ", durationp = ".(isset(/** @scrutinizer ignore-deprecated */ $this->durationp) && $this->durationp >= 0 && $this->durationp != '' ? "'".$this->db->escape($this->durationp)."'" : "null"); // deprecated
Loading history...
1025
		$sql .= ", note = '".$this->db->escape($this->note_private)."'";
1026
		$sql .= ", fk_project =".($this->fk_project > 0 ? $this->fk_project : "null");
1027
		$sql .= ", fk_soc =".($socid > 0 ? $socid : "null");
1028
		$sql .= ", fk_contact =".($contactid > 0 ? $contactid : "null");
1029
		$sql .= ", priority = '".$this->db->escape($this->priority)."'";
1030
		$sql .= ", fulldayevent = '".$this->db->escape($this->fulldayevent)."'";
1031
		$sql .= ", location = ".($this->location ? "'".$this->db->escape($this->location)."'" : "null");
1032
		$sql .= ", transparency = '".$this->db->escape($this->transparency)."'";
1033
		$sql .= ", fk_user_mod = ".$user->id;
1034
		$sql .= ", fk_user_action=".($userownerid > 0 ? "'".$userownerid."'" : "null");
1035
		$sql .= ", fk_user_done=".($userdoneid > 0 ? "'".$userdoneid."'" : "null");
1036
		if (!empty($this->fk_element)) $sql .= ", fk_element=".($this->fk_element ? $this->db->escape($this->fk_element) : "null");
1037
		if (!empty($this->elementtype)) $sql .= ", elementtype=".($this->elementtype ? "'".$this->db->escape($this->elementtype)."'" : "null");
1038
		$sql .= " WHERE id=".$this->id;
1039
1040
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
1041
		if ($this->db->query($sql))
1042
		{
1043
			$action = 'update';
1044
1045
			// Actions on extra fields
1046
	   		if (!$error)
1047
	   		{
1048
	   			$result = $this->insertExtraFields();
1049
	   			if ($result < 0)
1050
	   			{
1051
	   				$error++;
1052
	   			}
1053
			}
1054
1055
			// Now insert assignedusers
1056
			if (!$error)
1057
			{
1058
				$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".$this->id." AND element_type = 'user'";
1059
				$resql = $this->db->query($sql);
1060
1061
				foreach ($this->userassigned as $key => $val)
1062
				{
1063
					if (!is_array($val))	// For backward compatibility when val=id
1064
					{
1065
						$val = array('id'=>$val);
1066
					}
1067
					$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1068
					$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']).")";
1069
1070
					$resql = $this->db->query($sql);
1071
					if (!$resql)
1072
					{
1073
						$error++;
1074
				   		$this->errors[] = $this->db->lasterror();
1075
					}
1076
					//var_dump($sql);exit;
1077
				}
1078
			}
1079
1080
			if (!$error)
1081
			{
1082
				$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".$this->id." AND element_type = 'socpeople'";
1083
				$resql = $this->db->query($sql);
1084
1085
				if (!empty($this->socpeopleassigned))
1086
				{
1087
					foreach (array_keys($this->socpeopleassigned) as $id)
1088
					{
1089
						$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1090
						$sql .= " VALUES(".$this->id.", 'socpeople', ".$id.", 0, 0, 0)";
1091
1092
						$resql = $this->db->query($sql);
1093
						if (!$resql)
1094
						{
1095
							$error++;
1096
							$this->errors[] = $this->db->lasterror();
1097
						}
1098
					}
1099
				}
1100
			}
1101
1102
			if (!$error && !$notrigger)
1103
			{
1104
				// Call trigger
1105
				$result = $this->call_trigger('ACTION_MODIFY', $user);
1106
				if ($result < 0) { $error++; }
1107
				// End call triggers
1108
			}
1109
1110
			if (!$error)
1111
			{
1112
				$this->db->commit();
1113
				return 1;
1114
			} else {
1115
				$this->db->rollback();
1116
				dol_syslog(get_class($this)."::update ".join(',', $this->errors), LOG_ERR);
1117
				return -2;
1118
			}
1119
		} else {
1120
			$this->db->rollback();
1121
			$this->error = $this->db->lasterror();
1122
			return -1;
1123
		}
1124
	}
1125
1126
	/**
1127
	 *  Load all objects with filters.
1128
	 *  @todo WARNING: This make a fetch on all records instead of making one request with a join.
1129
	 *
1130
	 *  @param		DoliDb	$db				Database handler
1131
	 *  @param		int		$socid			Filter by thirdparty
1132
	 *  @param		int		$fk_element		Id of element action is linked to
1133
	 *  @param		string	$elementtype	Type of element action is linked to
1134
	 *  @param		string	$filter			Other filter
1135
	 *  @param		string	$sortfield		Sort on this field
1136
	 *  @param		string	$sortorder		ASC or DESC
1137
	 *  @param		string	$limit			Limit number of answers
1138
	 *  @return		array|string			Error string if KO, array with actions if OK
1139
	 */
1140
	public static function getActions($db, $socid = 0, $fk_element = 0, $elementtype = '', $filter = '', $sortfield = 'a.datep', $sortorder = 'DESC', $limit = 0)
1141
	{
1142
		global $conf, $langs;
1143
1144
		$resarray = array();
1145
1146
		dol_syslog(get_class()."::getActions", LOG_DEBUG);
1147
1148
		$sql = "SELECT a.id";
1149
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1150
		$sql .= " WHERE a.entity IN (".getEntity('agenda').")";
1151
		if (!empty($socid)) $sql .= " AND a.fk_soc = ".$socid;
1152
		if (!empty($elementtype))
1153
		{
1154
			if ($elementtype == 'project') {
1155
				$sql .= ' AND a.fk_project = '.$fk_element;
1156
			}
1157
			elseif ($elementtype == 'contact') {
1158
				$sql .= ' AND a.id IN';
1159
				$sql .= " (SELECT fk_actioncomm FROM ".MAIN_DB_PREFIX."actioncomm_resources WHERE";
1160
				$sql .= " element_type = 'socpeople' AND fk_element = ".$fk_element.')';
1161
			}
1162
			else {
1163
				$sql .= " AND a.fk_element = ".(int) $fk_element." AND a.elementtype = '".$elementtype."'";
1164
			}
1165
		}
1166
		if (!empty($filter)) $sql .= $filter;
1167
		if ($sortorder && $sortfield) $sql .= $db->order($sortfield, $sortorder);
1168
		$sql .= $db->plimit($limit, 0);
1169
1170
		$resql = $db->query($sql);
1171
		if ($resql)
1172
		{
1173
			$num = $db->num_rows($resql);
1174
1175
			if ($num)
1176
			{
1177
				for ($i = 0; $i < $num; $i++)
1178
				{
1179
					$obj = $db->fetch_object($resql);
1180
					$actioncommstatic = new ActionComm($db);
1181
					$actioncommstatic->fetch($obj->id);
1182
					$resarray[$i] = $actioncommstatic;
1183
				}
1184
			}
1185
			$db->free($resql);
1186
			return $resarray;
1187
		} else {
1188
			return $db->lasterror();
1189
		}
1190
	}
1191
1192
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1193
	/**
1194
	 * Load indicators for dashboard (this->nbtodo and this->nbtodolate)
1195
	 *
1196
	 * @param	User	$user   			Objet user
1197
	 * @param	int		$load_state_board	Charge indicateurs this->nb de tableau de bord
1198
	 * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK
1199
	 */
1200
	public function load_board($user, $load_state_board = 0)
1201
	{
1202
		// phpcs:enable
1203
		global $conf, $langs;
1204
1205
		if (empty($load_state_board)) $sql = "SELECT a.id, a.datep as dp";
1206
		else {
1207
			$this->nb = array();
1208
			$sql = "SELECT count(a.id) as nb";
1209
		}
1210
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1211
		if (!$user->rights->societe->client->voir && !$user->socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON a.fk_soc = sc.fk_soc";
1212
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON a.fk_soc = s.rowid";
1213
		$sql .= " WHERE 1 = 1";
1214
		if (empty($load_state_board)) $sql .= " AND a.percent >= 0 AND a.percent < 100";
1215
		$sql .= " AND a.entity IN (".getEntity('agenda').")";
1216
		if (!$user->rights->societe->client->voir && !$user->socid) $sql .= " AND (a.fk_soc IS NULL OR sc.fk_user = ".$user->id.")";
1217
		if ($user->socid) $sql .= " AND a.fk_soc = ".$user->socid;
1218
		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.")";
1219
1220
		$resql = $this->db->query($sql);
1221
		if ($resql)
1222
		{
1223
			if (empty($load_state_board)) {
1224
				$agenda_static = new ActionComm($this->db);
1225
				$response = new WorkboardResponse();
1226
				$response->warning_delay = $conf->agenda->warning_delay / 60 / 60 / 24;
1227
				$response->label = $langs->trans("ActionsToDo");
1228
				$response->labelShort = $langs->trans("ActionsToDoShort");
1229
				$response->url = DOL_URL_ROOT.'/comm/action/list.php?action=show_list&actioncode=0&status=todo&mainmenu=agenda';
1230
				if ($user->rights->agenda->allactions->read) $response->url .= '&filtert=-1';
1231
				$response->img = img_object('', "action", 'class="inline-block valigntextmiddle"');
1232
			}
1233
			// This assignment in condition is not a bug. It allows walking the results.
1234
			while ($obj = $this->db->fetch_object($resql))
1235
			{
1236
				if (empty($load_state_board)) {
1237
					$response->nbtodo++;
1 ignored issue
show
Comprehensibility Best Practice introduced by
The variable $response does not seem to be defined for all execution paths leading up to this point.
Loading history...
1238
					$agenda_static->datep = $this->db->jdate($obj->dp);
1 ignored issue
show
Comprehensibility Best Practice introduced by
The variable $agenda_static does not seem to be defined for all execution paths leading up to this point.
Loading history...
1239
					if ($agenda_static->hasDelay()) $response->nbtodolate++;
1240
				} else $this->nb["actionscomm"] = $obj->nb;
1241
			}
1242
1243
			$this->db->free($resql);
1244
			if (empty($load_state_board)) return $response;
1245
			else return 1;
1246
		} else {
1247
			dol_print_error($this->db);
1248
			$this->error = $this->db->error();
1249
			return -1;
1250
		}
1251
	}
1252
1253
1254
	/**
1255
	 *  Charge les informations d'ordre info dans l'objet facture
1256
	 *
1257
	 *  @param	int		$id       	Id de la facture a charger
1258
	 *  @return	void
1259
	 */
1260
	public function info($id)
1261
	{
1262
		$sql = 'SELECT ';
1263
		$sql .= ' a.id,';
1264
		$sql .= ' datec,';
1265
		$sql .= ' tms as datem,';
1266
		$sql .= ' fk_user_author,';
1267
		$sql .= ' fk_user_mod';
1268
		$sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a';
1269
		$sql .= ' WHERE a.id = '.$id;
1270
1271
		dol_syslog(get_class($this)."::info", LOG_DEBUG);
1272
		$result = $this->db->query($sql);
1273
		if ($result)
1274
		{
1275
			if ($this->db->num_rows($result))
1276
			{
1277
				$obj = $this->db->fetch_object($result);
1278
				$this->id = $obj->id;
1279
				if ($obj->fk_user_author)
1280
				{
1281
					$cuser = new User($this->db);
1282
					$cuser->fetch($obj->fk_user_author);
1283
					$this->user_creation = $cuser;
1284
				}
1285
				if ($obj->fk_user_mod)
1286
				{
1287
					$muser = new User($this->db);
1288
					$muser->fetch($obj->fk_user_mod);
1289
					$this->user_modification = $muser;
1290
				}
1291
1292
				$this->date_creation = $this->db->jdate($obj->datec);
1293
				if (!empty($obj->fk_user_mod)) $this->date_modification = $this->db->jdate($obj->datem);
1294
			}
1295
			$this->db->free($result);
1296
		} else {
1297
			dol_print_error($this->db);
1298
		}
1299
	}
1300
1301
1302
	/**
1303
	 *  Return label of status
1304
	 *
1305
	 *  @param	int		$mode           0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
1306
	 *  @param  int		$hidenastatus   1=Show nothing if status is "Not applicable"
1307
	 *  @return string          		String with status
1308
	 */
1309
	public function getLibStatut($mode, $hidenastatus = 0)
1310
	{
1311
		return $this->LibStatut($this->percentage, $mode, $hidenastatus, $this->datep);
1312
	}
1313
1314
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1315
	/**
1316
	 *  Return label of action status
1317
	 *
1318
	 *  @param  int     $percent        Percent
1319
	 *  @param  int		$mode           0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto
1320
	 *  @param  int		$hidenastatus   1=Show nothing if status is "Not applicable"
1321
	 *  @param  int     $datestart      Date start of event
1322
	 *  @return string		    		Label
1323
	 */
1324
	public function LibStatut($percent, $mode, $hidenastatus = 0, $datestart = '')
1325
	{
1326
		// phpcs:enable
1327
		global $langs;
1328
1329
		$labelStatus = $langs->trans('StatusNotApplicable');
1330
	   	if ($percent == -1 && !$hidenastatus) $labelStatus = $langs->trans('StatusNotApplicable');
1331
	   	elseif ($percent == 0) $labelStatus = $langs->trans('StatusActionToDo').' (0%)';
1332
	   	elseif ($percent > 0 && $percent < 100) $labelStatus = $langs->trans('StatusActionInProcess').' ('.$percent.'%)';
1333
	   	elseif ($percent >= 100) $labelStatus = $langs->trans('StatusActionDone').' (100%)';
1334
1335
		$labelStatusShort = $langs->trans('StatusNotApplicable');
1336
		if ($percent == -1 && !$hidenastatus) $labelStatusShort = $langs->trans('NA');
1337
		elseif ($percent == 0) $labelStatusShort = '0%';
1338
		elseif ($percent > 0 && $percent < 100) $labelStatusShort = $percent.'%';
1339
		elseif ($percent >= 100) $labelStatusShort = '100%';
1340
1341
		$statusType = 'status9';
1342
		if ($percent == -1 && !$hidenastatus) $statusType = 'status9';
1343
		if ($percent == 0) $statusType = 'status1';
1344
		if ($percent > 0 && $percent < 100) $statusType = 'status3';
1345
		if ($percent >= 100) $statusType = 'status6';
1346
1347
		return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1348
	}
1349
1350
	/**
1351
	 *  Return URL of event
1352
	 *  Use $this->id, $this->type_code, $this->label and $this->type_label
1353
	 *
1354
	 *  @param	int		$withpicto				0 = No picto, 1 = Include picto into link, 2 = Only picto
1355
	 *  @param	int		$maxlength				Max number of charaters into label. If negative, use the ref as label.
1356
	 *  @param	string	$classname				Force style class on a link
1357
	 *  @param	string	$option					'' = Link to action, 'birthday'= Link to contact, 'holiday' = Link to leave
1358
	 *  @param	int		$overwritepicto			1 = Overwrite picto
1359
	 *  @param	int   	$notooltip		    	1 = Disable tooltip
1360
	 *  @param  int     $save_lastsearch_value  -1 = Auto, 0 = No save of lastsearch_values when clicking, 1 = Save lastsearch_values whenclicking
1361
	 *  @return	string							Chaine avec URL
1362
	 */
1363
	public function getNomUrl($withpicto = 0, $maxlength = 0, $classname = '', $option = '', $overwritepicto = 0, $notooltip = 0, $save_lastsearch_value = -1)
1364
	{
1365
		global $conf, $langs, $user, $hookmanager, $action;
1366
1367
		if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
1368
1369
		$canread = 0;
1370
		if ($user->rights->agenda->myactions->read && $this->authorid == $user->id) $canread = 1; // Can read my event
1371
		if ($user->rights->agenda->myactions->read && array_key_exists($user->id, $this->userassigned)) $canread = 1; // Can read my event i am assigned
1372
		if ($user->rights->agenda->allactions->read) $canread = 1; // Can read all event of other
1373
		if (!$canread)
1374
		{
1375
			$option = 'nolink';
1376
		}
1377
1378
		$label = $this->label;
1379
		if (empty($label)) $label = $this->libelle; // For backward compatibility
1 ignored issue
show
Bug Best Practice introduced by
The property libelle does not exist on ActionComm. Did you maybe forget to declare it?
Loading history...
1380
1381
		$result = '';
1382
1383
		// Set label of type
1384
		$labeltype = '';
1385
		if ($this->type_code)
1386
		{
1387
			$labeltype = ($langs->transnoentities("Action".$this->type_code) != "Action".$this->type_code) ? $langs->transnoentities("Action".$this->type_code) : $this->type_label;
1388
		}
1389
		if (empty($conf->global->AGENDA_USE_EVENT_TYPE))
1390
		{
1391
			if ($this->type_code != 'AC_OTH_AUTO') $labeltype = $langs->trans('ActionAC_MANUAL');
1392
		}
1393
1394
		$tooltip = img_picto('', $this->picto).' <u>'.$langs->trans('Action').'</u>';
1395
		if (!empty($this->ref))
1396
			$tooltip .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1397
		if (!empty($label))
1398
			$tooltip .= '<br><b>'.$langs->trans('Title').':</b> '.$label;
1399
		if (!empty($labeltype))
1400
			$tooltip .= '<br><b>'.$langs->trans('Type').':</b> '.$labeltype;
1401
		if (!empty($this->location))
1402
			$tooltip .= '<br><b>'.$langs->trans('Location').':</b> '.$this->location;
1403
		if (isset($this->transparency))
1404
			$tooltip .= '<br><b>'.$langs->trans('Busy').':</b> '.yn($this->transparency);
1405
		if (!empty($this->note_private))
1406
			$tooltip .= '<br><b>'.$langs->trans('Note').':</b> '.(dol_textishtml($this->note_private) ? str_replace(array("\r", "\n"), "", $this->note_private) : str_replace(array("\r", "\n"), '<br>', $this->note_private));
1407
		$linkclose = '';
1408
		if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && $this->type_color)
1409
			$linkclose = ' style="background-color:#'.$this->type_color.'"';
1410
1411
		if (empty($notooltip))
1412
		{
1413
			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1414
			{
1415
				$label = $langs->trans("ShowAction");
1416
				$linkclose .= ' alt="'.dol_escape_htmltag($tooltip, 1).'"';
1417
			}
1418
			$linkclose .= ' title="'.dol_escape_htmltag($tooltip, 1).'"';
1419
			$linkclose .= ' class="'.$classname.' classfortooltip"';
1420
1421
			/*
1422
		    $hookmanager->initHooks(array('actiondao'));
1423
		    $parameters=array('id'=>$this->id);
1424
		    $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
1425
		    $linkclose = ($hookmanager->resPrint ? $hookmanager->resPrint : $linkclose);
1426
		    */
1427
		} else $linkclose .= ' class="'.$classname.'"';
1428
1429
		$url = '';
1430
		if ($option == 'birthday')
1431
			$url = DOL_URL_ROOT.'/contact/perso.php?id='.$this->id;
1432
		elseif ($option == 'holiday')
1433
			$url = DOL_URL_ROOT.'/holiday/card.php?id='.$this->id;
1434
		else $url = DOL_URL_ROOT.'/comm/action/card.php?id='.$this->id;
1435
		if ($option !== 'nolink')
1436
		{
1437
			// Add param to save lastsearch_values or not
1438
			$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1439
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
1440
			if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
1441
		}
1442
1443
		$linkstart = '<a href="'.$url.'"';
1444
		$linkstart .= $linkclose.'>';
1445
		$linkend = '</a>';
1446
1447
		if ($option == 'nolink') {
1448
			$linkstart = '';
1449
			$linkend = '';
1450
		}
1451
1452
		if ($withpicto == 2)
1453
		{
1454
			$libelle = $label;
1455
			if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) $libelle = $labeltype;
1456
			$libelleshort = '';
1457
		} else {
1458
			$libelle = (empty($this->libelle) ? $label : $this->libelle.(($label && $label != $this->libelle) ? ' '.$label : ''));
1459
			if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && empty($libelle)) $libelle = $labeltype;
1460
			if ($maxlength < 0) $libelleshort = $this->ref;
1461
			else $libelleshort = dol_trunc($libelle, $maxlength);
1462
		}
1463
1464
		if ($withpicto)
1465
		{
1466
			if (!empty($conf->global->AGENDA_USE_EVENT_TYPE))	// Add code into ()
1467
			{
1468
				if ($labeltype)
1469
				{
1470
					$libelle .= (preg_match('/'.preg_quote($labeltype, '/').'/', $libelle) ? '' : ' ('.$langs->transnoentities("Action".$this->type_code).')');
1471
				}
1472
			}
1473
		}
1474
1475
		$result .= $linkstart;
1476
		if ($withpicto)	$result .= img_object(($notooltip ? '' : $langs->trans("ShowAction").': '.$libelle), ($overwritepicto ? $overwritepicto : 'action'), ($notooltip ? 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"' : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
1477
		$result .= $libelleshort;
1478
		$result .= $linkend;
1479
1480
		global $action;
1481
		$hookmanager->initHooks(array('actiondao'));
1482
		$parameters = array('id'=>$this->id, 'getnomurl'=>$result);
1483
		$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1484
		if ($reshook > 0) $result = $hookmanager->resPrint;
1485
		else $result .= $hookmanager->resPrint;
1486
1487
		return $result;
1488
	}
1489
1490
	/**
1491
	 * Sets object to supplied categories.
1492
	 *
1493
	 * Deletes object from existing categories not supplied.
1494
	 * Adds it to non existing supplied categories.
1495
	 * Existing categories are left untouch.
1496
	 *
1497
	 * @param  int[]|int $categories Category or categories IDs
1498
	 * @return void
1499
	 */
1500
	public function setCategories($categories)
1501
	{
1502
		// Handle single category
1503
		if (!is_array($categories)) {
1504
			$categories = array($categories);
1505
		}
1506
1507
		// Get current categories
1508
		include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1509
		$c = new Categorie($this->db);
1510
		$existing = $c->containing($this->id, Categorie::TYPE_ACTIONCOMM, 'id');
1511
1512
		// Diff
1513
		if (is_array($existing)) {
0 ignored issues
show
introduced by
The condition is_array($existing) is always false.
Loading history...
1514
			$to_del = array_diff($existing, $categories);
1515
			$to_add = array_diff($categories, $existing);
1516
		} else {
1517
			$to_del = array(); // Nothing to delete
1518
			$to_add = $categories;
1519
		}
1520
1521
		// Process
1522
		foreach ($to_del as $del) {
1523
			if ($c->fetch($del) > 0) {
1524
				$c->del_type($this, Categorie::TYPE_ACTIONCOMM);
1525
			}
1526
		}
1527
		foreach ($to_add as $add) {
1528
			if ($c->fetch($add) > 0) {
1529
				$c->add_type($this, Categorie::TYPE_ACTIONCOMM);
1530
			}
1531
		}
1532
		return;
1533
	}
1534
1535
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1536
	/**
1537
	 * Export events from database into a cal file.
1538
	 *
1539
	 * @param string    $format         The format of the export 'vcal', 'ical/ics' or 'rss'
1540
	 * @param string    $type           The type of the export 'event' or 'journal'
1541
	 * @param integer   $cachedelay     Do not rebuild file if date older than cachedelay seconds
1542
	 * @param string    $filename       The name for the exported file.
1543
	 * @param array     $filters        Array of filters. Example array('notolderthan'=>99, 'year'=>..., 'idfrom'=>..., 'notactiontype'=>'systemauto', 'project'=>123, ...)
1544
	 * @param integer   $exportholiday  0 = don't integrate holidays into the export, 1 = integrate holidays into the export
1545
	 * @return integer                  -1 = error on build export file, 0 = export okay
1546
	 */
1547
	public function build_exportfile($format, $type, $cachedelay, $filename, $filters, $exportholiday = 0)
1548
	{
1549
		global $hookmanager;
1550
1551
		// phpcs:enable
1552
		global $conf, $langs, $dolibarr_main_url_root, $mysoc;
1553
1554
		require_once DOL_DOCUMENT_ROOT."/core/lib/xcal.lib.php";
1555
		require_once DOL_DOCUMENT_ROOT."/core/lib/date.lib.php";
1556
		require_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php";
1557
1558
		dol_syslog(get_class($this)."::build_exportfile Build export file format=".$format.", type=".$type.", cachedelay=".$cachedelay.", filename=".$filename.", filters size=".count($filters), LOG_DEBUG);
1559
1560
		// Check parameters
1561
		if (empty($format)) return -1;
1562
1563
		// Clean parameters
1564
		if (!$filename)
1565
		{
1566
			$extension = 'vcs';
1567
			if ($format == 'ical') $extension = 'ics';
1568
			$filename = $format.'.'.$extension;
1569
		}
1570
1571
		// Create dir and define output file (definitive and temporary)
1572
		$result = dol_mkdir($conf->agenda->dir_temp);
1573
		$outputfile = $conf->agenda->dir_temp.'/'.$filename;
1574
1575
		$result = 0;
1576
1577
		$buildfile = true;
1578
		$login = ''; $logina = ''; $logind = ''; $logint = '';
1579
1580
		$now = dol_now();
1581
1582
		if ($cachedelay)
1583
		{
1584
			$nowgmt = dol_now();
1585
			include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1586
			if (dol_filemtime($outputfile) > ($nowgmt - $cachedelay))
1587
			{
1588
				dol_syslog(get_class($this)."::build_exportfile file ".$outputfile." is not older than now - cachedelay (".$nowgmt." - ".$cachedelay."). Build is canceled");
1589
				$buildfile = false;
1590
			}
1591
		}
1592
1593
		if ($buildfile)
1594
		{
1595
			// Build event array
1596
			$eventarray = array();
1597
1598
			$sql = "SELECT a.id,";
1599
			$sql .= " a.datep,"; // Start
1600
			$sql .= " a.datep2,"; // End
1601
			$sql .= " a.durationp,"; // deprecated
1602
			$sql .= " a.datec, a.tms as datem,";
1603
			$sql .= " a.label, a.code, a.note, a.fk_action as type_id,";
1604
			$sql .= " a.fk_soc,";
1605
			$sql .= " a.fk_user_author, a.fk_user_mod,";
1606
			$sql .= " a.fk_user_action,";
1607
			$sql .= " a.fk_contact, a.percent as percentage,";
1608
			$sql .= " a.fk_element, a.elementtype,";
1609
			$sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
1610
			$sql .= " u.firstname, u.lastname, u.email,";
1611
			$sql .= " s.nom as socname,";
1612
			$sql .= " c.id as type_id, c.code as type_code, c.libelle as type_label";
1613
			$sql .= " FROM (".MAIN_DB_PREFIX."c_actioncomm as c, ".MAIN_DB_PREFIX."actioncomm as a)";
1614
			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author"; // Link to get author of event for export
1615
			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
1616
1617
			$parameters = array('filters' => $filters);
1618
			$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
1619
			$sql .= $hookmanager->resPrint;
1620
1621
			// We must filter on assignement table
1622
			if ($filters['logint']) $sql .= ", ".MAIN_DB_PREFIX."actioncomm_resources as ar";
1623
			$sql .= " WHERE a.fk_action=c.id";
1624
			$sql .= " AND a.entity IN (".getEntity('agenda').")";
1625
			foreach ($filters as $key => $value)
1626
			{
1627
				if ($key == 'notolderthan' && $value != '') $sql .= " AND a.datep >= '".$this->db->idate($now - ($value * 24 * 60 * 60))."'";
1628
				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))."'";
1629
				if ($key == 'id')           $sql .= " AND a.id=".(is_numeric($value) ? $value : 0);
1630
				if ($key == 'idfrom')       $sql .= " AND a.id >= ".(is_numeric($value) ? $value : 0);
1631
				if ($key == 'idto')         $sql .= " AND a.id <= ".(is_numeric($value) ? $value : 0);
1632
				if ($key == 'project')      $sql .= " AND a.fk_project=".(is_numeric($value) ? $value : 0);
1633
				if ($key == 'actiontype')    $sql .= " AND c.type = '".$this->db->escape($value)."'";
1634
				if ($key == 'notactiontype') $sql .= " AND c.type <> '".$this->db->escape($value)."'";
1635
				// We must filter on assignement table
1636
				if ($key == 'logint')       $sql .= " AND ar.fk_actioncomm = a.id AND ar.element_type='user'";
1637
				if ($key == 'logina')
1638
				{
1639
					$logina = $value;
1640
					$condition = '=';
1641
					if (preg_match('/^!/', $logina))
1642
					{
1643
						$logina = preg_replace('/^!/', '', $logina);
1644
						$condition = '<>';
1645
					}
1646
					$userforfilter = new User($this->db);
1647
					$result = $userforfilter->fetch('', $logina);
1648
					if ($result > 0) $sql .= " AND a.fk_user_author ".$condition." ".$userforfilter->id;
1649
					elseif ($result < 0 || $condition == '=') $sql .= " AND a.fk_user_author = 0";
1650
				}
1651
				if ($key == 'logint')
1652
				{
1653
					$logint = $value;
1654
					$condition = '=';
1655
					if (preg_match('/^!/', $logint))
1656
					{
1657
						$logint = preg_replace('/^!/', '', $logint);
1658
						$condition = '<>';
1659
					}
1660
					$userforfilter = new User($this->db);
1661
					$result = $userforfilter->fetch('', $logint);
1662
					if ($result > 0) $sql .= " AND ar.fk_element = ".$userforfilter->id;
1663
					elseif ($result < 0 || $condition == '=') $sql .= " AND ar.fk_element = 0";
1664
				}
1665
			}
1666
1667
			$sql .= " AND a.datep IS NOT NULL"; // To exclude corrupted events and avoid errors in lightning/sunbird import
1668
1669
			$parameters = array('filters' => $filters);
1670
			$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
1671
			$sql .= $hookmanager->resPrint;
1672
1673
			$sql .= " ORDER by datep";
1674
			//print $sql;exit;
1675
1676
			dol_syslog(get_class($this)."::build_exportfile select events", LOG_DEBUG);
1677
			$resql = $this->db->query($sql);
1678
			if ($resql)
1679
			{
1680
				// Note: Output of sql request is encoded in $conf->file->character_set_client
1681
				// This assignment in condition is not a bug. It allows walking the results.
1682
				$diff = 0;
1683
				while ($obj = $this->db->fetch_object($resql))
1684
				{
1685
					$qualified = true;
1686
1687
					// 'eid','startdate','duration','enddate','title','summary','category','email','url','desc','author'
1688
					$event = array();
1689
					$event['uid'] = 'dolibarragenda-'.$this->db->database_name.'-'.$obj->id."@".$_SERVER["SERVER_NAME"];
1690
					$event['type'] = $type;
1691
					$datestart = $this->db->jdate($obj->datep) - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
1692
1693
					// fix for -> Warning: A non-numeric value encountered
1694
					if (is_numeric($this->db->jdate($obj->datep2)))
1695
					{
1696
						$dateend = $this->db->jdate($obj->datep2)
1697
								 - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
1698
					} else {
1699
						// use start date as fall-back to avoid import erros on empty end date
1700
						$dateend = $datestart;
1701
					}
1702
1703
					$duration = ($datestart && $dateend) ? ($dateend - $datestart) : 0;
1704
					$event['summary'] = $obj->label.($obj->socname ? " (".$obj->socname.")" : "");
1705
					$event['desc'] = $obj->note;
1706
					$event['startdate'] = $datestart;
1707
					$event['enddate'] = $dateend; // Not required with type 'journal'
1708
					$event['duration'] = $duration; // Not required with type 'journal'
1709
					$event['author'] = dolGetFirstLastname($obj->firstname, $obj->lastname);
1710
					$event['priority'] = $obj->priority;
1711
					$event['fulldayevent'] = $obj->fulldayevent;
1712
					$event['location'] = $obj->location;
1713
					$event['transparency'] = (($obj->transparency > 0) ? 'OPAQUE' : 'TRANSPARENT'); // OPAQUE (busy) or TRANSPARENT (not busy)
1714
					$event['category'] = $obj->type_label;
1715
					$event['email'] = $obj->email;
1716
					// Define $urlwithroot
1717
					$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
1718
					$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
1719
					//$urlwithroot=DOL_MAIN_URL_ROOT;						// This is to use same domain name than current
1720
					$url = $urlwithroot.'/comm/action/card.php?id='.$obj->id;
1721
					$event['url'] = $url;
1722
					$event['created'] = $this->db->jdate($obj->datec) - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
1723
					$event['modified'] = $this->db->jdate($obj->datem) - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
1724
1725
					// TODO: find a way to call "$this->fetch_userassigned();" without override "$this" properties
1726
					$this->id = $obj->id;
1727
					$this->fetch_userassigned(false);
1728
1729
					$assignedUserArray = array();
1730
1731
					foreach ($this->userassigned as $key => $value)
1732
					{
1733
						$assignedUser = new User($this->db);
1734
						$assignedUser->fetch($value['id']);
1735
1736
						$assignedUserArray[$key] = $assignedUser;
1737
					}
1738
1739
					$event['assignedUsers'] = $assignedUserArray;
1740
1741
					if ($qualified && $datestart)
1742
					{
1743
						$eventarray[] = $event;
1744
					}
1745
					$diff++;
1746
				}
1747
1748
				$parameters = array('filters' => $filters, 'eventarray' => &$eventarray);
1749
				$reshook = $hookmanager->executeHooks('addMoreEventsExport', $parameters); // Note that $action and $object may have been modified by hook
1750
				if ($reshook > 0)
1751
				{
1752
					$eventarray = $hookmanager->resArray;
1753
				}
1754
			} else {
1755
				$this->error = $this->db->lasterror();
1756
				return -1;
1757
			}
1758
1759
			if ($exportholiday == 1)
1760
			{
1761
				$langs->load("holidays");
1762
				$title = $langs->trans("Holidays");
1763
1764
				$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";
1765
				$sql .= " FROM ".MAIN_DB_PREFIX."holiday as x, ".MAIN_DB_PREFIX."user as u";
1766
				$sql .= " WHERE u.rowid = x.fk_user";
1767
				$sql .= " AND u.statut = '1'"; // Show only active users  (0 = inactive user, 1 = active user)
1768
				$sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
1769
1770
				$resql = $this->db->query($sql);
1771
				if ($resql)
1772
				{
1773
					$num = $this->db->num_rows($resql);
1774
					$i   = 0;
1775
1776
					while ($i < $num)
1777
					{
1778
						$obj   = $this->db->fetch_object($resql);
1779
						$event = array();
1780
1781
						if ($obj->halfday == -1)
1782
						{
1783
							$event['fulldayevent'] = false;
1784
1785
							$timestampStart = dol_stringtotime($obj->date_start." 00:00:00", 0);
1786
							$timestampEnd   = dol_stringtotime($obj->date_end." 12:00:00", 0);
1787
						} elseif ($obj->halfday == 1)
1788
						{
1789
							$event['fulldayevent'] = false;
1790
1791
							$timestampStart = dol_stringtotime($obj->date_start." 12:00:00", 0);
1792
							$timestampEnd   = dol_stringtotime($obj->date_end." 23:59:59", 0);
1793
						} else {
1794
							$event['fulldayevent'] = true;
1795
1796
							$timestampStart = dol_stringtotime($obj->date_start." 00:00:00", 0);
1797
							$timestampEnd   = dol_stringtotime($obj->date_end." 23:59:59", 0);
1798
						}
1799
1800
						if (!empty($conf->global->AGENDA_EXPORT_FIX_TZ))
1801
						{
1802
							$timestampStart = - ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
1803
							$timestampEnd   = - ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
1804
						}
1805
1806
						$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
1807
						$urlwithroot       = $urlwithouturlroot.DOL_URL_ROOT;
1808
						$url               = $urlwithroot.'/holiday/card.php?id='.$obj->rowid;
1809
1810
						$event['uid']          = 'dolibarrholiday-'.$this->db->database_name.'-'.$obj->rowid."@".$_SERVER["SERVER_NAME"];
1811
						$event['author']       = dolGetFirstLastname($obj->firstname, $obj->lastname);
1812
						$event['type']         = 'event';
1813
						$event['category']     = "Holiday";
1814
						$event['transparency'] = 'OPAQUE';
1815
						$event['email']        = $obj->email;
1816
						$event['created']      = $timestampStart;
1817
						$event['modified']     = $timestampStart;
1818
						$event['startdate']    = $timestampStart;
1819
						$event['enddate']      = $timestampEnd;
1820
						$event['duration']     = $timestampEnd - $timestampStart;
1821
						$event['url']          = $url;
1822
1823
						if ($obj->status == 2)
1824
						{
1825
							// 2 = leave wait for approval
1826
							$event['summary'] = $title." - ".$obj->lastname." (wait for approval)";
1827
						} else {
1828
							// 3 = leave approved
1829
							$event['summary'] = $title." - ".$obj->lastname;
1830
						}
1831
1832
						$eventarray[] = $event;
1833
1834
						$i++;
1835
					}
1836
				}
1837
			}
1838
1839
			$langs->load("agenda");
1840
1841
			// Define title and desc
1842
			$more = '';
1843
			if ($login)  $more = $langs->transnoentities("User").' '.$login;
1844
			if ($logina) $more = $langs->transnoentities("ActionsAskedBy").' '.$logina;
1845
			if ($logint) $more = $langs->transnoentities("ActionsToDoBy").' '.$logint;
1846
			if ($logind) $more = $langs->transnoentities("ActionsDoneBy").' '.$logind;
1847
			if ($more)
1848
			{
1849
				$title = 'Dolibarr actions '.$mysoc->name.' - '.$more;
1850
				$desc = $more;
1851
				$desc .= ' ('.$mysoc->name.' - built by Dolibarr)';
1852
			} else {
1853
				$title = 'Dolibarr actions '.$mysoc->name;
1854
				$desc = $langs->transnoentities('ListOfActions');
1855
				$desc .= ' ('.$mysoc->name.' - built by Dolibarr)';
1856
			}
1857
1858
			// Create temp file
1859
			$outputfiletmp = tempnam($conf->agenda->dir_temp, 'tmp'); // Temporary file (allow call of function by different threads
1860
			@chmod($outputfiletmp, octdec($conf->global->MAIN_UMASK));
1861
1862
			// Write file
1863
			if ($format == 'vcal') $result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
1864
			elseif ($format == 'ical') $result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
1865
			elseif ($format == 'rss')  $result = build_rssfile($format, $title, $desc, $eventarray, $outputfiletmp);
1866
1867
			if ($result >= 0)
1868
			{
1869
				if (dol_move($outputfiletmp, $outputfile, 0, 1)) $result = 1;
1870
				else {
1871
					$this->error = 'Failed to rename '.$outputfiletmp.' into '.$outputfile;
1872
					dol_syslog(get_class($this)."::build_exportfile ".$this->error, LOG_ERR);
1873
					dol_delete_file($outputfiletmp, 0, 1);
1874
					$result = -1;
1875
				}
1876
			} else {
1877
				dol_syslog(get_class($this)."::build_exportfile build_xxxfile function fails to for format=".$format." outputfiletmp=".$outputfile, LOG_ERR);
1878
				dol_delete_file($outputfiletmp, 0, 1);
1879
				$langs->load("errors");
1880
				$this->error = $langs->trans("ErrorFailToCreateFile", $outputfile);
1881
			}
1882
		}
1883
1884
		return $result;
1885
	}
1886
1887
	/**
1888
	 *  Initialise an instance with random values.
1889
	 *  Used to build previews or test instances.
1890
	 *  id must be 0 if object instance is a specimen.
1891
	 *
1892
	 *  @return	int >0 if ok
1893
	 */
1894
	public function initAsSpecimen()
1895
	{
1896
		global $user;
1897
1898
		$now = dol_now();
1899
1900
		// Initialise parametres
1901
		$this->id = 0;
1902
		$this->specimen = 1;
1903
1904
		$this->type_code = 'AC_OTH';
1905
		$this->code = 'AC_SPECIMEN_CODE';
1906
		$this->label = 'Label of event Specimen';
1907
		$this->datec = $now;
1908
		$this->datem = $now;
1909
		$this->datep = $now;
1910
		$this->datef = $now;
1911
		$this->fulldayevent = 0;
1912
		$this->percentage = 0;
1913
		$this->location = 'Location';
1914
		$this->transparency = 1; // 1 means opaque
1915
		$this->priority = 1;
1916
		//$this->note_public = "This is a 'public' note.";
1917
		$this->note_private = "This is a 'private' note.";
1918
1919
		$this->userownerid = $user->id;
1920
		$this->userassigned[$user->id] = array('id'=>$user->id, 'transparency'=> 1);
1921
		return 1;
1922
	}
1923
1924
	/**
1925
	 *  Function used to replace a thirdparty id with another one.
1926
	 *
1927
	 *  @param DoliDB $db Database handler
1928
	 *  @param int $origin_id Old thirdparty id
1929
	 *  @param int $dest_id New thirdparty id
1930
	 *  @return bool
1931
	 */
1932
	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
1933
	{
1934
		$tables = array(
1935
			'actioncomm'
1936
		);
1937
1938
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
1939
	}
1940
1941
	/**
1942
	 *  Is the action delayed?
1943
	 *
1944
	 *  @return bool
1945
	 */
1946
	public function hasDelay()
1947
	{
1948
		global $conf;
1949
1950
		$now = dol_now();
1951
1952
		return $this->datep && ($this->datep < ($now - $conf->agenda->warning_delay));
1953
	}
1954
1955
1956
	/**
1957
	 *  Load event reminder of events
1958
	 *
1959
	 *  @param	string	$type		Type of reminder 'browser' or 'email'
1960
	 *  @param	int		$fk_user	Id of user
1961
	 *  @return int         		0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
1962
	 */
1963
	public function loadReminders($type = '', $fk_user = 0)
1964
	{
1965
		global $conf, $langs, $user;
1966
1967
		$error = 0;
1968
1969
		$this->reminders = array();
1970
1971
		//Select all action comm reminders for event
1972
		$sql = "SELECT rowid as id, typeremind, dateremind, status, offsetvalue, offsetunit, fk_user";
1973
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
1974
		$sql .= " WHERE fk_actioncomm = ".$this->id." AND dateremind <= '".$this->db->idate(dol_now())."'";
1975
		if ($type) {
1976
			$sql .= " AND typeremind ='".$this->db->escape($type)."'";
1977
		}
1978
		if ($fk_user > 0) {
1979
			$sql .= " AND fk_user = ".((int) $fk_user);
1980
		}
1981
		if (empty($conf->global->AGENDA_REMINDER_EMAIL)) $sql .= " AND typeremind != 'email'";
1982
		if (empty($conf->global->AGENDA_REMINDER_BROWSER)) $sql .= " AND typeremind != 'browser'";
1983
1984
		$sql .= $this->db->order("dateremind", "ASC");
1985
		$resql = $this->db->query($sql);
1986
1987
		if ($resql) {
1988
			while ($obj = $this->db->fetch_object($resql)) {
1989
				$tmpactioncommreminder = new ActionCommReminder($this->db);
1990
				$tmpactioncommreminder->id = $obj->id;
1991
				$tmpactioncommreminder->typeremind = $obj->typeremind;
1992
				$tmpactioncommreminder->dateremind = $obj->dateremind;
1993
				$tmpactioncommreminder->offsetvalue = $obj->offsetvalue;
1994
				$tmpactioncommreminder->offsetunit = $obj->offsetunit;
1995
				$tmpactioncommreminder->status = $obj->status;
1996
				$tmpactioncommreminder->fk_user = $obj->fk_user;
1997
1998
				$this->reminders[$obj->id] = $tmpactioncommreminder;
1999
			}
2000
		} else {
2001
			$this->error = $this->db->lasterror();
2002
			$error++;
2003
		}
2004
2005
		return count($this->reminders);
2006
	}
2007
2008
2009
	/**
2010
	 *  Send reminders by emails
2011
	 *  CAN BE A CRON TASK
2012
	 *
2013
	 *  @return int         0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
2014
	 */
2015
	public function sendEmailsReminder()
2016
	{
2017
		global $conf, $langs, $user;
2018
2019
		$error = 0;
2020
		$this->output = '';
2021
		$this->error = '';
2022
		$nbMailSend = 0;
2023
		$errorsMsg = array();
2024
2025
		if (empty($conf->agenda->enabled))	// Should not happen. If module disabled, cron job should not be visible.
2026
		{
2027
			$langs->load("agenda");
2028
			$this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2029
			return 0;
2030
		}
2031
		if (empty($conf->global->AGENDA_REMINDER_EMAIL))
2032
		{
2033
			$langs->load("agenda");
2034
			$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2035
			return 0;
2036
		}
2037
2038
		$now = dol_now();
2039
2040
		dol_syslog(__METHOD__, LOG_DEBUG);
2041
2042
		$this->db->begin();
2043
2044
		//Select all action comm reminder
2045
		$sql = "SELECT rowid as id FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2046
		$sql .= " WHERE typeremind = 'email' AND status = 0";
2047
		$sql .= " AND dateremind <= '".$this->db->idate(dol_now())."'";
2048
		$sql .= $this->db->order("dateremind", "ASC");
2049
		$resql = $this->db->query($sql);
2050
2051
		if ($resql) {
2052
			$formmail = new FormMail($this->db);
2053
			$actionCommReminder = new ActionCommReminder($this->db);
2054
2055
			while ($obj = $this->db->fetch_object($resql)) {
2056
				$res = $actionCommReminder->fetch($obj->id);
2057
				if ($res < 0) {
2058
					$error++;
2059
					$errorsMsg[] = "Failed to load invoice ActionComm Reminder";
2060
				}
2061
2062
				if (!$error)
2063
				{
2064
					//Select email template
2065
					$arraymessage = $formmail->getEMailTemplate($this->db, 'actioncomm_send', $user, $langs, (!empty($actionCommReminder->fk_email_template)) ? $actionCommReminder->fk_email_template : -1, 1);
2066
2067
					// Load event
2068
					$res = $this->fetch($actionCommReminder->fk_actioncomm);
2069
					if ($res > 0)
2070
					{
2071
						// PREPARE EMAIL
2072
2073
						// Make substitution in email content
2074
						$substitutionarray = getCommonSubstitutionArray($langs, 0, '', $this);
2075
2076
						complete_substitutions_array($substitutionarray, $langs, $this);
2077
2078
						// Content
2079
						$sendContent = make_substitutions($langs->trans($arraymessage->content), $substitutionarray);
2080
2081
						//Topic
2082
						$sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->trans('EventReminder'));
2083
2084
						// Recipient
2085
						$recipient = new User($this->db);
2086
						$res = $recipient->fetch($actionCommReminder->fk_user);
2087
						if ($res > 0 && !empty($recipient->email)) $to = $recipient->email;
2088
						else {
2089
							$errorsMsg[] = "Failed to load recipient";
2090
							$error++;
2091
						}
2092
2093
						// Sender
2094
						$from = $conf->global->MAIN_MAIL_EMAIL_FROM;
2095
						if (empty($from)) {
2096
							$errorsMsg[] = "Failed to load recipient";
2097
							$error++;
2098
						}
2099
2100
						// Errors Recipient
2101
						$errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
2102
2103
						// Mail Creation
2104
						$cMailFile = new CMailFile($sendTopic, $to, $from, $sendContent, array(), array(), array(), '', "", 0, 1, $errors_to, '', '', '', '', '');
2105
2106
						// Sending Mail
2107
						if ($cMailFile->sendfile())
2108
						{
2109
							$actionCommReminder->status = $actionCommReminder::STATUS_DONE;
2110
							$res = $actionCommReminder->update($user);
2111
							if ($res < 0)
2112
							{
2113
								$errorsMsg[] = "Failed to update status of ActionComm Reminder";
2114
								$error++;
2115
								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.
2116
							} else {
2117
								$nbMailSend++;
2118
							}
2119
						} else {
2120
							$errorsMsg[] = $cMailFile->error.' : '.$to;
2121
							$error++;
2122
						}
2123
					} else {
2124
						$error++;
2125
					}
2126
				}
2127
			}
2128
		} else {
2129
			$error++;
2130
		}
2131
2132
		if (!$error)
2133
		{
2134
			// Delete also very old past events (we do not keep more than 1 month record in past)
2135
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2136
			$sql .= " WHERE dateremind < '".$this->db->idate($now - (3600 * 24 * 32))."'";
2137
			$resql = $this->db->query($sql);
2138
2139
			if (!$resql) {
2140
				$errorsMsg[] = 'Failed to delete old reminders';
2141
				//$error++;		// If this fails, we must not rollback other SQL requests already done. Never mind.
2142
			}
2143
		}
2144
2145
		if (!$error) {
2146
			$this->output = 'Nb of emails sent : '.$nbMailSend;
2147
			$this->db->commit();
2148
			return 0;
2149
		}
2150
		else {
2151
			$this->db->rollback();
2152
			$this->error = 'Nb of emails sent : '.$nbMailSend.', '.(!empty($errorsMsg)) ? join(', ', $errorsMsg) : $error;
2153
			return $error;
2154
		}
2155
	}
2156
2157
	/**
2158
	 * Udpate the percent value of a event with the given id
2159
	 *
2160
	 * @param int		$id			The id of the event
2161
	 * @param int		$percent	The new percent value for the event
2162
	 * @return int					1 when update of the event was suscessfull, otherwise -1
2163
	 */
2164
	public function updatePercent($id, $percent)
2165
	{
2166
		$this->db->begin();
2167
2168
		$sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm ";
2169
		$sql .= " SET percent = ".(int) $percent;
2170
		$sql .= " WHERE id=".$id;
2171
2172
		if ($this->db->query($sql))
2173
		{
2174
			$this->db->commit();
2175
			return 1;
2176
		} else {
2177
			$this->db->rollback();
2178
			$this->error = $this->db->lasterror();
2179
			return -1;
2180
		}
2181
	}
2182
}
2183