Passed
Branch develop (59f205)
by
unknown
29:12
created

ActionComm::getActions()   B

Complexity

Conditions 11

Size

Total Lines 49
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 35
nop 8
dl 0
loc 49
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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

1067
			/** @scrutinizer ignore-deprecated */ $this->durationp = ($this->datef - $this->datep); // deprecated
Loading history...
1068
		}
1069
		//if ($this->date  && $this->dateend) $this->durationa=($this->dateend - $this->date);
1070
		if ($this->datep && $this->datef && $this->datep > $this->datef) {
1071
			$this->datef = $this->datep;
1072
		}
1073
		//if ($this->date  && $this->dateend && $this->date > $this->dateend) $this->dateend=$this->date;
1074
		if ($this->fk_project < 0) {
1075
			$this->fk_project = 0;
1076
		}
1077
1078
		// Check parameters
1079
		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

1079
		if ($this->percentage == 0 && /** @scrutinizer ignore-deprecated */ $this->userdoneid > 0) {
Loading history...
1080
			$this->error = "ErrorCantSaveADoneUserWithZeroPercentage";
1081
			return -1;
1082
		}
1083
1084
		$socid = (($this->socid > 0) ? $this->socid : 0);
1085
		$contactid = (($this->contact_id > 0) ? $this->contact_id : 0);
1086
		$userownerid = ($this->userownerid ? $this->userownerid : 0);
1087
		$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

1087
		$userdoneid = ($this->userdoneid ? /** @scrutinizer ignore-deprecated */ $this->userdoneid : 0);
Loading history...
1088
1089
		$this->db->begin();
1090
1091
		$sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm ";
1092
		$sql .= " SET percent = '".$this->db->escape($this->percentage)."'";
1093
		if ($this->type_id > 0) {
1094
			$sql .= ", fk_action = '".$this->db->escape($this->type_id)."'";
1095
		}
1096
		$sql .= ", label = ".($this->label ? "'".$this->db->escape($this->label)."'" : "null");
1097
		$sql .= ", datep = ".(strval($this->datep) != '' ? "'".$this->db->idate($this->datep)."'" : 'null');
1098
		$sql .= ", datep2 = ".(strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : 'null');
1099
		$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

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