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

ActionComm::update()   F

Complexity

Conditions 61

Size

Total Lines 159
Code Lines 103

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 61
eloc 103
nop 2
dl 0
loc 159
rs 3.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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:

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