Passed
Branch develop (4d916f)
by
unknown
32:21
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/CMailFile.class.php';
32
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncommreminder.class.php';
33
34
35
/**
36
 *		Class to manage agenda events (actions)
37
 */
38
class ActionComm extends CommonObject
39
{
40
	/**
41
	 * @var string ID to identify managed object
42
	 */
43
	public $element = 'action';
44
45
	/**
46
	 * @var string Name of table without prefix where object is stored
47
	 */
48
	public $table_element = 'actioncomm';
49
50
	/**
51
	 * @var string Name of id column
52
	 */
53
	public $table_rowid = 'id';
54
55
	/**
56
	 * @var string Name of icon for actioncomm object. Filename of icon is object_action.png
57
	 */
58
	public $picto = 'action';
59
60
	/**
61
	 * @var int 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
62
	 */
63
	public $ismultientitymanaged = 1;
64
65
	/**
66
	 * @var integer 0=Default
67
	 *              1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
68
	 *              2=Same than 1 but accept record if fksoc is empty
69
	 */
70
	public $restrictiononfksoc = 2;
71
72
	/**
73
	 * @var int Id of the event
74
	 */
75
	public $id;
76
77
	/**
78
	 * @var int Id of the event. Use $id as possible
79
	 */
80
	public $ref;
81
82
	/**
83
	 * @var int Id into parent table llx_c_actioncomm (used only if option to use type is set)
84
	 * 			This field is stored info fk_action. It contains the id into table llx_ac_actioncomm.
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
	 *             This field contains the type into table llx_ac_actioncomm ('system', 'systemauto', ...). It should be named 'type_type'.
91
	 */
92
	public $type;
93
94
	/**
95
	 * @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.
96
	 *             This field contains the code into table llx_ac_actioncomm.
97
	 */
98
	public $type_code;
99
100
	/**
101
	 * @var string Type label
102
	 */
103
	public $type_label;
104
105
	/**
106
	 * @var string Color into parent table llx_c_actioncomm (used only if option to use type is set)
107
	 */
108
	public $type_color;
109
110
	/**
111
	 * @var string Picto for type of event (used only if option to use type is set)
112
	 */
113
	public $type_picto;
114
115
	/**
116
	 * @var string Free code to identify action. Ie: Agenda trigger add here AC_TRIGGERNAME ('AC_COMPANY_CREATE', 'AC_PROPAL_VALIDATE', ...)
117
	 * 			   This field is stored into field 'code' into llx_actioncomm.
118
	 */
119
	public $code;
120
121
	/**
122
	 * @var string Agenda event label
123
	 */
124
	public $label;
125
126
	/**
127
	 * @var integer Date creation record (datec)
128
	 */
129
	public $datec;
130
131
	/**
132
	 * @var integer Date end record (datef)
133
	 */
134
	public $datef;
135
136
	/**
137
	 * @var integer Duration (duree)
138
	 */
139
	public $duree;
140
141
	/**
142
	 * @var integer Date modification record (tms)
143
	 */
144
	public $datem;
145
146
	/**
147
	 * @var User Object user that create action
148
	 * @deprecated
149
	 * @see $authorid
150
	 */
151
	public $author;
152
153
	/**
154
	 * @var User Object user that modified action
155
	 * @deprecated
156
	 * @see $usermodid
157
	 */
158
	public $usermod;
159
160
	/**
161
	 * @var int Id user that create action
162
	 */
163
	public $authorid;
164
165
	/**
166
	 * @var int Id user that modified action
167
	 */
168
	public $usermodid;
169
170
	/**
171
	 * @var integer Date action start (datep)
172
	 */
173
	public $datep;
174
175
	/**
176
	 * @var integer Date action end (datep2)
177
	 */
178
	public $datep2;
179
180
	/**
181
	 * @var int -1=Unkown duration
182
	 * @deprecated
183
	 */
184
	public $durationp = -1;
185
186
	/**
187
	 * @var int 1=Event on full day
188
	 */
189
	public $fulldayevent = 0;
190
191
	/**
192
	 * @var integer Percentage
193
	 */
194
	public $percentage;
195
196
	/**
197
	 * @var string Location
198
	 */
199
	public $location;
200
201
	/**
202
	 * @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)
203
	 */
204
	public $transparency;
205
206
	/**
207
	 * @var int (0 By default)
208
	 */
209
	public $priority;
210
211
	/**
212
	 * @var int[] Array of user ids
213
	 */
214
	public $userassigned = array();
215
216
	/**
217
	 * @var int Id of user owner = fk_user_action into table
218
	 */
219
	public $userownerid;
220
221
	/**
222
	 * @var int Id of user done (deprecated)
223
	 * @deprecated
224
	 */
225
	public $userdoneid;
226
227
	/**
228
	 * @var int[] Array of contact ids
229
	 */
230
	public $socpeopleassigned = array();
231
232
	/**
233
	 * @var int[] Array of other contact emails (not user, not contact)
234
	 */
235
	public $otherassigned = array();
236
237
	/**
238
	 * @var array	Array of reminders
239
	 */
240
	public $reminders = array();
241
242
	/**
243
	 * @var User Object user of owner
244
	 * @deprecated
245
	 * @see $userownerid
246
	 */
247
	public $usertodo;
248
249
	/**
250
	 * @var User Object user that did action
251
	 * @deprecated
252
	 * @see $userdoneid
253
	 */
254
	public $userdone;
255
256
	/**
257
	 * @var int thirdparty id linked to action
258
	 */
259
	public $socid;
260
261
	/**
262
	 * @var int socpeople id linked to action
263
	 */
264
	public $contactid;
265
266
	/**
267
	 * @var Societe|null Company linked to action (optional)
268
	 * @deprecated
269
	 * @see $socid
270
	 */
271
	public $societe;
272
273
	/**
274
	 * @var Contact|null Contact linked to action (optional)
275
	 * @deprecated
276
	 * @see $contactid
277
	 */
278
	public $contact;
279
280
	// Properties for links to other objects
281
	/**
282
	 * @var int Id of linked object
283
	 */
284
	public $fk_element; // Id of record
285
286
	/**
287
	 * @var int Id of record alternative for API
288
	 */
289
	public $elementid;
290
291
	/**
292
	 * @var string Type of record. This if property ->element of object linked to.
293
	 */
294
	public $elementtype;
295
296
	/**
297
	 * @var string Ical name
298
	 */
299
	public $icalname;
300
301
	/**
302
	 * @var string Ical color
303
	 */
304
	public $icalcolor;
305
306
	/**
307
	 * @var string Extraparam
308
	 */
309
	public $extraparams;
310
311
	/**
312
	 * @var array Actions
313
	 */
314
	public $actions = array();
315
316
	/**
317
	 * @var string Email msgid
318
	 */
319
	public $email_msgid;
320
321
	/**
322
	 * @var string Email from
323
	 */
324
	public $email_from;
325
326
	/**
327
	 * @var string Email sender
328
	 */
329
	public $email_sender;
330
331
	/**
332
	 * @var string Email to
333
	 */
334
	public $email_to;
335
336
	/**
337
	 * @var string Email tocc
338
	 */
339
	public $email_tocc;
340
	/**
341
	 * @var string Email tobcc
342
	 */
343
	public $email_tobcc;
344
345
	/**
346
	 * @var string Email subject
347
	 */
348
	public $email_subject;
349
350
	/**
351
	 * @var string Email errors to
352
	 */
353
	public $errors_to;
354
355
	/**
356
	 * @var int number of vote for an event
357
	 */
358
	public $num_vote;
359
360
	/**
361
	 * @var int if event is paid
362
	 */
363
	public $event_paid;
364
365
	/**
366
	 * @var int status use but Event organisation module
367
	 */
368
	public $status;
369
370
	/**
371
	 * Typical value for a event that is in a todo state
372
	 */
373
	const EVENT_TODO = 0;
374
375
	/**
376
	 * Typical value for a event that is in a progress state
377
	 */
378
	const EVENT_IN_PROGRESS = 50;
379
380
	/**
381
	 * Typical value for a event that is in a finished state
382
	 */
383
	const EVENT_FINISHED = 100;
384
385
	/**
386
	 *      Constructor
387
	 *
388
	 *      @param      DoliDB		$db      Database handler
389
	 */
390
	public function __construct(DoliDB $db)
391
	{
392
		$this->db = $db;
393
	}
394
395
	/**
396
	 *    Add an action/event into database.
397
	 *    $this->type_id OR $this->type_code must be set.
398
	 *
399
	 *    @param	User	$user      		Object user making action
400
	 *    @param    int		$notrigger		1 = disable triggers, 0 = enable triggers
401
	 *    @return   int 		        	Id of created event, < 0 if KO
402
	 */
403
	public function create(User $user, $notrigger = 0)
404
	{
405
		global $langs, $conf, $hookmanager;
406
407
		$error = 0;
408
		$now = dol_now();
409
410
		// Check parameters
411
		if (!isset($this->userownerid) || $this->userownerid === '') {	// $this->userownerid may be 0 (anonymous event) of > 0
412
			dol_syslog("You tried to create an event but mandatory property ownerid was not defined", LOG_WARNING);
413
			$this->errors[] = 'ErrorActionCommPropertyUserowneridNotDefined';
414
			return -1;
415
		}
416
417
		// Clean parameters
418
		$this->label = dol_trunc(trim($this->label), 128);
419
		$this->location = dol_trunc(trim($this->location), 128);
420
		$this->note_private = dol_htmlcleanlastbr(trim(empty($this->note_private) ? $this->note : $this->note_private));
421
		if (empty($this->percentage)) {
422
			$this->percentage = 0;
423
		}
424
		if (empty($this->priority) || !is_numeric($this->priority)) {
425
			$this->priority = 0;
426
		}
427
		if (empty($this->fulldayevent)) {
428
			$this->fulldayevent = 0;
429
		}
430
		if (empty($this->transparency)) {
431
			$this->transparency = 0;
432
		}
433
		if ($this->percentage > 100) {
434
			$this->percentage = 100;
435
		}
436
		//if ($this->percentage == 100 && ! $this->dateend) $this->dateend = $this->date;
437
		if (!empty($this->datep) && !empty($this->datef)) {
438
			$this->durationp = ($this->datef - $this->datep); // deprecated
439
		}
440
		//if (! empty($this->date)  && ! empty($this->dateend)) $this->durationa=($this->dateend - $this->date);
441
		if (!empty($this->datep) && !empty($this->datef) && $this->datep > $this->datef) {
442
			$this->datef = $this->datep;
443
		}
444
		//if (! empty($this->date)  && ! empty($this->dateend) && $this->date > $this->dateend) $this->dateend=$this->date;
445
		if (!isset($this->fk_project) || $this->fk_project < 0) {
446
			$this->fk_project = 0;
447
		}
448
		// For backward compatibility
449
		if ($this->elementtype == 'facture') {
450
			$this->elementtype = 'invoice';
451
		}
452
		if ($this->elementtype == 'commande') {
453
			$this->elementtype = 'order';
454
		}
455
		if ($this->elementtype == 'contrat') {
456
			$this->elementtype = 'contract';
457
		}
458
459
		if (!is_array($this->userassigned) && !empty($this->userassigned)) {	// For backward compatibility when userassigned was an int instead fo array
460
			$tmpid = $this->userassigned;
461
			$this->userassigned = array();
462
			$this->userassigned[$tmpid] = array('id'=>$tmpid, 'transparency'=>$this->transparency);
463
		}
464
465
		$userownerid = $this->userownerid;
466
		$userdoneid = $this->userdoneid;
467
468
		// Be sure assigned user is defined as an array of array('id'=>,'mandatory'=>,...).
469
		if (empty($this->userassigned) || count($this->userassigned) == 0 || !is_array($this->userassigned)) {
470
			$this->userassigned = array($userownerid=>array('id'=>$userownerid, 'transparency'=>$this->transparency));
471
		}
472
473
		if (!$this->type_id || !$this->type_code) {
474
			$key = empty($this->type_id) ? $this->type_code : $this->type_id;
475
476
			// Get id from code
477
			$cactioncomm = new CActionComm($this->db);
478
			$result = $cactioncomm->fetch($key);
479
480
			if ($result > 0) {
481
				$this->type_id = $cactioncomm->id;
482
				$this->type_code = $cactioncomm->code;
483
			} elseif ($result == 0) {
484
				$this->error = $langs->trans('ErrorActionCommBadType', $this->type_id, $this->type_code);
485
				return -1;
486
			} else {
487
				$this->error = $cactioncomm->error;
488
				return -1;
489
			}
490
		}
491
		$code = empty($this->code) ? $this->type_code : $this->code;
492
493
		// Check parameters
494
		if (!$this->type_id) {
495
			$this->error = "ErrorWrongParameters";
496
			return -1;
497
		}
498
499
		$this->db->begin();
500
501
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm";
502
		$sql .= "(ref,";
503
		$sql .= "datec,";
504
		$sql .= "datep,";
505
		$sql .= "datep2,";
506
		$sql .= "durationp,"; // deprecated
507
		$sql .= "fk_action,";
508
		$sql .= "code,";
509
		$sql .= "ref_ext,";
510
		$sql .= "fk_soc,";
511
		$sql .= "fk_project,";
512
		$sql .= "note,";
513
		$sql .= "fk_contact,";
514
		$sql .= "fk_user_author,";
515
		$sql .= "fk_user_action,";
516
		$sql .= "fk_user_done,";
517
		$sql .= "label,percent,priority,fulldayevent,location,";
518
		$sql .= "transparency,";
519
		$sql .= "fk_element,";
520
		$sql .= "elementtype,";
521
		$sql .= "entity,";
522
		$sql .= "extraparams,";
523
		// Fields emails
524
		$sql .= "email_msgid,";
525
		$sql .= "email_from,";
526
		$sql .= "email_sender,";
527
		$sql .= "email_to,";
528
		$sql .= "email_tocc,";
529
		$sql .= "email_tobcc,";
530
		$sql .= "email_subject,";
531
		$sql .= "errors_to,";
532
		$sql .= "num_vote,";
533
		$sql .= "event_paid,";
534
		$sql .= "status";
535
		$sql .= ") VALUES (";
536
		$sql .= "'(PROV)', ";
537
		$sql .= "'".$this->db->idate($now)."', ";
538
		$sql .= (strval($this->datep) != '' ? "'".$this->db->idate($this->datep)."'" : "null").", ";
539
		$sql .= (strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : "null").", ";
540
		$sql .= ((isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '') ? "'".$this->db->escape($this->durationp)."'" : "null").", "; // deprecated
541
		$sql .= (isset($this->type_id) ? $this->type_id : "null").",";
542
		$sql .= ($code ? ("'".$this->db->escape($code)."'") : "null").", ";
543
		$sql .= (!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : "null").", ";
544
		$sql .= ((isset($this->socid) && $this->socid > 0) ? $this->socid : "null").", ";
545
		$sql .= ((isset($this->fk_project) && $this->fk_project > 0) ? $this->fk_project : "null").", ";
546
		$sql .= " '".$this->db->escape($this->note_private)."', ";
547
		$sql .= ((isset($this->contact_id) && $this->contact_id > 0) ? $this->contact_id : "null").", "; // deprecated, use ->socpeopleassigned
548
		$sql .= (isset($user->id) && $user->id > 0 ? $user->id : "null").", ";
549
		$sql .= ($userownerid > 0 ? $userownerid : "null").", ";
550
		$sql .= ($userdoneid > 0 ? $userdoneid : "null").", ";
551
		$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)."', ";
552
		$sql .= "'".$this->db->escape($this->transparency)."', ";
553
		$sql .= (!empty($this->fk_element) ? $this->fk_element : "null").", ";
554
		$sql .= (!empty($this->elementtype) ? "'".$this->db->escape($this->elementtype)."'" : "null").", ";
555
		$sql .= $conf->entity.",";
556
		$sql .= (!empty($this->extraparams) ? "'".$this->db->escape($this->extraparams)."'" : "null").", ";
557
		// Fields emails
558
		$sql .= (!empty($this->email_msgid) ? "'".$this->db->escape($this->email_msgid)."'" : "null").", ";
559
		$sql .= (!empty($this->email_from) ? "'".$this->db->escape($this->email_from)."'" : "null").", ";
560
		$sql .= (!empty($this->email_sender) ? "'".$this->db->escape($this->email_sender)."'" : "null").", ";
561
		$sql .= (!empty($this->email_to) ? "'".$this->db->escape($this->email_to)."'" : "null").", ";
562
		$sql .= (!empty($this->email_tocc) ? "'".$this->db->escape($this->email_tocc)."'" : "null").", ";
563
		$sql .= (!empty($this->email_tobcc) ? "'".$this->db->escape($this->email_tobcc)."'" : "null").", ";
564
		$sql .= (!empty($this->email_subject) ? "'".$this->db->escape($this->email_subject)."'" : "null").", ";
565
		$sql .= (!empty($this->errors_to) ? "'".$this->db->escape($this->errors_to)."'" : "null").", ";
566
		$sql .= (!empty($this->num_vote) ? (int) $this->num_vote : "null").", ";
567
		$sql .= (!empty($this->event_paid) ? (int) $this->event_paid : 0).", ";
568
		$sql .= (!empty($this->status) ? (int) $this->status : "0");
569
		$sql .= ")";
570
571
		dol_syslog(get_class($this)."::add", LOG_DEBUG);
572
		$resql = $this->db->query($sql);
573
		if ($resql) {
574
			$this->ref = $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."actioncomm", "id");
575
			$sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm SET ref='".$this->db->escape($this->ref)."' WHERE id=".$this->id;
576
			$resql = $this->db->query($sql);
577
			if (!$resql) {
578
				$error++;
579
				dol_syslog('Error to process ref: '.$this->db->lasterror(), LOG_ERR);
580
				$this->errors[] = $this->db->lasterror();
581
			}
582
			// Now insert assigned users
583
			if (!$error) {
584
				//dol_syslog(var_export($this->userassigned, true));
585
				$already_inserted = array();
586
				foreach ($this->userassigned as $key => $val) {
587
					if (!is_array($val)) {	// For backward compatibility when val=id
588
						$val = array('id'=>$val);
589
					}
590
591
					if ($val['id'] > 0) {
592
						if (!empty($already_inserted[$val['id']])) continue;
593
594
						$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
595
						$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']).")";
596
597
						$resql = $this->db->query($sql);
598
						if (!$resql) {
599
							$error++;
600
							dol_syslog('Error to process userassigned: ' . $this->db->lasterror(), LOG_ERR);
601
							$this->errors[] = $this->db->lasterror();
602
						} else {
603
							$already_inserted[$val['id']] = true;
604
						}
605
						//var_dump($sql);exit;
606
					}
607
				}
608
			}
609
610
			if (!$error) {
611
				if (!empty($this->socpeopleassigned)) {
612
					$already_inserted = array();
613
					foreach ($this->socpeopleassigned as $id => $val) {
614
						if (!empty($already_inserted[$val['id']])) continue;
615
616
						$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
617
						$sql .= " VALUES(".$this->id.", 'socpeople', ".$id.", 0, 0, 0)";
618
619
						$resql = $this->db->query($sql);
620
						if (!$resql) {
621
							$error++;
622
							dol_syslog('Error to process socpeopleassigned: ' . $this->db->lasterror(), LOG_ERR);
623
							$this->errors[] = $this->db->lasterror();
624
						} else {
625
							$already_inserted[$val['id']] = true;
626
						}
627
					}
628
				}
629
			}
630
631
			if (!$error) {
632
				// Actions on extra fields
633
				$result = $this->insertExtraFields();
634
				if ($result < 0) {
635
					$error++;
636
				}
637
			}
638
639
			if (!$error && !$notrigger) {
640
				// Call trigger
641
				$result = $this->call_trigger('ACTION_CREATE', $user);
642
				if ($result < 0) {
643
					$error++;
644
				}
645
				// End call triggers
646
			}
647
648
			if (!$error) {
649
				$this->db->commit();
650
				return $this->id;
651
			} else {
652
				$this->db->rollback();
653
				return -1;
654
			}
655
		} else {
656
			$this->db->rollback();
657
			$this->error = $this->db->lasterror();
658
			return -1;
659
		}
660
	}
661
662
	/**
663
	 *  Load an object from its id and create a new one in database
664
	 *
665
	 *  @param	    User	        $fuser      	Object user making action
666
	 *  @param		int				$socid			Id of thirdparty
667
	 *  @return		int								New id of clone
668
	 */
669
	public function createFromClone(User $fuser, $socid)
670
	{
671
		global $db, $conf, $hookmanager;
672
673
		$error = 0;
674
		$now = dol_now();
675
676
		$this->db->begin();
677
678
		// Load source object
679
		$objFrom = clone $this;
680
681
		// Retrieve all extrafield
682
		// fetch optionals attributes and labels
683
		$this->fetch_optionals();
684
685
		//$this->fetch_userassigned();
686
		$this->fetchResources();
687
688
		$this->id = 0;
689
690
		// Create clone
691
		$this->context['createfromclone'] = 'createfromclone';
692
		$result = $this->create($fuser);
693
		if ($result < 0) {
694
			$error++;
695
		}
696
697
		if (!$error) {
698
			// Hook of thirdparty module
699
			if (is_object($hookmanager)) {
700
				$parameters = array('objFrom'=>$objFrom);
701
				$action = '';
702
				$reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
703
				if ($reshook < 0) {
704
					$error++;
705
				}
706
			}
707
708
			// Call trigger
709
			$result = $this->call_trigger('ACTION_CLONE', $fuser);
710
			if ($result < 0) {
711
				$error++;
712
			}
713
			// End call triggers
714
		}
715
716
		unset($this->context['createfromclone']);
717
718
		// End
719
		if (!$error) {
720
			$this->db->commit();
721
			return $this->id;
722
		} else {
723
			$this->db->rollback();
724
			return -1;
725
		}
726
	}
727
728
	/**
729
	 *  Load object from database
730
	 *
731
	 *  @param  int		$id     		Id of action to get
732
	 *  @param  string	$ref    		Ref of action to get
733
	 *  @param  string	$ref_ext		Ref ext to get
734
	 *  @param	string	$email_msgid	Email msgid
735
	 *  @return	int						<0 if KO, >0 if OK
736
	 */
737
	public function fetch($id, $ref = '', $ref_ext = '', $email_msgid = '')
738
	{
739
		global $langs;
740
741
		$sql = "SELECT a.id,";
742
		$sql .= " a.ref as ref,";
743
		$sql .= " a.entity,";
744
		$sql .= " a.ref_ext,";
745
		$sql .= " a.datep,";
746
		$sql .= " a.datep2,";
747
		$sql .= " a.durationp,"; // deprecated
748
		$sql .= " a.datec,";
749
		$sql .= " a.tms as datem,";
750
		$sql .= " a.code, a.label, a.note,";
751
		$sql .= " a.fk_soc,";
752
		$sql .= " a.fk_project,";
753
		$sql .= " a.fk_user_author, a.fk_user_mod,";
754
		$sql .= " a.fk_user_action, a.fk_user_done,";
755
		$sql .= " a.fk_contact, a.percent as percentage,";
756
		$sql .= " a.fk_element as elementid, a.elementtype,";
757
		$sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
758
		$sql .= " a.email_msgid, a.email_subject, a.email_from, a.email_to, a.email_tocc, a.email_tobcc, a.errors_to,";
759
		$sql .= " c.id as type_id, c.type as type_type, c.code as type_code, c.libelle as type_label, c.color as type_color, c.picto as type_picto,";
760
		$sql .= " s.nom as socname,";
761
		$sql .= " u.firstname, u.lastname as lastname,";
762
		$sql .= " num_vote, event_paid, a.status";
763
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a ";
764
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action=c.id ";
765
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author";
766
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
767
		$sql .= " WHERE ";
768
		if ($ref) {
769
			$sql .= " a.ref = '".$this->db->escape($ref)."'";
770
		} elseif ($ref_ext) {
771
			$sql .= " a.ref_ext = '".$this->db->escape($ref_ext)."'";
772
		} elseif ($email_msgid) {
773
			$sql .= " a.email_msgid = '".$this->db->escape($email_msgid)."'";
774
		} else {
775
			$sql .= " a.id = ".((int) $id);
776
		}
777
778
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
779
		$resql = $this->db->query($sql);
780
		if ($resql) {
781
			$num = $this->db->num_rows($resql);
782
			if ($num) {
783
				$obj = $this->db->fetch_object($resql);
784
785
				$this->id         = $obj->id;
786
				$this->entity = $obj->entity;
787
				$this->ref        = $obj->ref;
788
				$this->ref_ext    = $obj->ref_ext;
789
790
				// Properties of parent table llx_c_actioncomm
791
				$this->type_id    = $obj->type_id;
792
				$this->type_code  = $obj->type_code;
793
				$this->type_color = $obj->type_color;
794
				$this->type_picto = $obj->type_picto;
795
				$this->type       = $obj->type_type;
796
				/*$transcode = $langs->trans("Action".$obj->type_code);
797
				$this->type       = (($transcode != "Action".$obj->type_code) ? $transcode : $obj->type_label); */
798
				$transcode = $langs->trans("Action".$obj->type_code.'Short');
799
				$this->type_short = (($transcode != "Action".$obj->type_code.'Short') ? $transcode : '');
800
801
				$this->code = $obj->code;
802
				$this->label = $obj->label;
803
				$this->datep = $this->db->jdate($obj->datep);
804
				$this->datef = $this->db->jdate($obj->datep2);
805
806
				$this->datec = $this->db->jdate($obj->datec);
807
				$this->datem = $this->db->jdate($obj->datem);
808
809
				$this->note = $obj->note; // deprecated
810
				$this->note_private = $obj->note;
811
				$this->percentage = $obj->percentage;
812
813
				$this->authorid = $obj->fk_user_author;
814
				$this->usermodid = $obj->fk_user_mod;
815
816
				if (!is_object($this->author)) {
817
					$this->author = new stdClass(); // To avoid warning
818
				}
819
				$this->author->id = $obj->fk_user_author; // deprecated
820
				$this->author->firstname = $obj->firstname; // deprecated
821
				$this->author->lastname = $obj->lastname; // deprecated
822
				if (!is_object($this->usermod)) {
823
					$this->usermod = new stdClass(); // To avoid warning
824
				}
825
				$this->usermod->id = $obj->fk_user_mod; // deprecated
826
827
				$this->userownerid = $obj->fk_user_action;
828
				$this->userdoneid = $obj->fk_user_done;
829
				$this->priority				= $obj->priority;
830
				$this->fulldayevent			= $obj->fulldayevent;
831
				$this->location				= $obj->location;
832
				$this->transparency			= $obj->transparency;
833
834
				$this->socid = $obj->fk_soc; // To have fetch_thirdparty method working
835
				$this->contact_id = $obj->fk_contact; // To have fetch_contact method working
836
				$this->fk_project = $obj->fk_project; // To have fetch_projet method working
837
838
				//$this->societe->id			= $obj->fk_soc;			// deprecated
839
				//$this->contact->id			= $obj->fk_contact;		// deprecated
840
841
				$this->fk_element = $obj->elementid;
842
				$this->elementid = $obj->elementid;
843
				$this->elementtype = $obj->elementtype;
844
845
				$this->num_vote = $obj->num_vote;
846
				$this->event_paid = $obj->event_paid;
847
				$this->status = $obj->status;
848
849
				$this->fetchResources();
850
			}
851
			$this->db->free($resql);
852
		} else {
853
			$this->error = $this->db->lasterror();
854
			return -1;
855
		}
856
857
		return $num;
858
	}
859
860
	/**
861
	 *    Initialize $this->userassigned & this->socpeopleassigned array with list of id of user and contact assigned to event
862
	 *
863
	 *    @return   int				<0 if KO, >0 if OK
864
	 */
865
	public function fetchResources()
866
	{
867
		$this->userassigned = array();
868
		$this->socpeopleassigned = array();
869
870
		$sql = 'SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency';
871
		$sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm_resources';
872
		$sql .= ' WHERE fk_actioncomm = '.$this->id;
873
		$sql .= " AND element_type IN ('user', 'socpeople')";
874
		$resql = $this->db->query($sql);
875
		if ($resql) {
876
			// If owner is known, we must but id first into list
877
			if ($this->userownerid > 0) {
878
				$this->userassigned[$this->userownerid] = array('id'=>$this->userownerid); // Set first so will be first into list.
879
			}
880
881
			while ($obj = $this->db->fetch_object($resql)) {
882
				if ($obj->fk_element > 0) {
883
					switch ($obj->element_type) {
884
						case 'user':
885
							$this->userassigned[$obj->fk_element] = array('id'=>$obj->fk_element, 'mandatory'=>$obj->mandatory, 'answer_status'=>$obj->answer_status, 'transparency'=>$obj->transparency);
886
							if (empty($this->userownerid)) {
887
								$this->userownerid = $obj->fk_element; // If not defined (should not happened, we fix this)
888
							}
889
							break;
890
						case 'socpeople':
891
							$this->socpeopleassigned[$obj->fk_element] = array('id'=>$obj->fk_element, 'mandatory'=>$obj->mandatory, 'answer_status'=>$obj->answer_status, 'transparency'=>$obj->transparency);
892
							break;
893
					}
894
				}
895
			}
896
897
			return 1;
898
		} else {
899
			dol_print_error($this->db);
900
			return -1;
901
		}
902
	}
903
904
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
905
	/**
906
	 *    Initialize this->userassigned array with list of id of user assigned to event
907
	 *
908
	 *    @param    bool    $override   Override $this->userownerid when empty. TODO This should be false by default. True is here to fix corrupted data.
909
	 *    @return   int                 <0 if KO, >0 if OK
910
	 */
911
	public function fetch_userassigned($override = true)
912
	{
913
		// phpcs:enable
914
		$sql = "SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency";
915
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm_resources";
916
		$sql .= " WHERE element_type = 'user' AND fk_actioncomm = ".$this->id;
917
918
		$resql2 = $this->db->query($sql);
919
		if ($resql2) {
920
			$this->userassigned = array();
921
922
			// If owner is known, we must but id first into list
923
			if ($this->userownerid > 0) {
924
				// Set first so will be first into list.
925
				$this->userassigned[$this->userownerid] = array('id'=>$this->userownerid);
926
			}
927
928
			while ($obj = $this->db->fetch_object($resql2)) {
929
				if ($obj->fk_element > 0) {
930
					$this->userassigned[$obj->fk_element] = array('id'=>$obj->fk_element,
931
																  'mandatory'=>$obj->mandatory,
932
																  'answer_status'=>$obj->answer_status,
933
																  'transparency'=>$obj->transparency);
934
				}
935
936
				if ($override === true) {
937
					// If not defined (should not happened, we fix this)
938
					if (empty($this->userownerid)) {
939
						$this->userownerid = $obj->fk_element;
940
					}
941
				}
942
			}
943
944
			return 1;
945
		} else {
946
			dol_print_error($this->db);
947
			return -1;
948
		}
949
	}
950
951
	/**
952
	 *    Delete event from database
953
	 *
954
	 *    @param    int		$notrigger		1 = disable triggers, 0 = enable triggers
955
	 *    @return   int 					<0 if KO, >0 if OK
956
	 */
957
	public function delete($notrigger = 0)
958
	{
959
		global $user;
960
961
		$error = 0;
962
963
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
964
965
		$this->db->begin();
966
967
		// remove categorie association
968
		if (!$error) {
969
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_actioncomm";
970
			$sql .= " WHERE fk_actioncomm=".$this->id;
971
972
			$res = $this->db->query($sql);
973
			if (!$res) {
974
				$this->error = $this->db->lasterror();
975
				$error++;
976
			}
977
		}
978
979
		// remove actioncomm_resources
980
		if (!$error) {
981
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources";
982
			$sql .= " WHERE fk_actioncomm=".$this->id;
983
984
			$res = $this->db->query($sql);
985
			if (!$res) {
986
				$this->error = $this->db->lasterror();
987
				$error++;
988
			}
989
		}
990
991
		if (!$error) {
992
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
993
			$sql .= " WHERE fk_actioncomm = ".$this->id;
994
995
			$res = $this->db->query($sql);
996
			if (!$res) {
997
				$this->error = $this->db->lasterror();
998
				$error++;
999
			}
1000
		}
1001
1002
		// Removed extrafields
1003
		if (!$error) {
1004
			  $result = $this->deleteExtraFields();
1005
			if ($result < 0) {
1006
				$error++;
1007
				dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
1008
			}
1009
		}
1010
1011
		// remove actioncomm
1012
		if (!$error) {
1013
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm";
1014
			$sql .= " WHERE id=".$this->id;
1015
1016
			$res = $this->db->query($sql);
1017
			if (!$res) {
1018
				$this->error = $this->db->lasterror();
1019
				$error++;
1020
			}
1021
		}
1022
1023
		if (!$error) {
1024
			if (!$notrigger) {
1025
				// Call trigger
1026
				$result = $this->call_trigger('ACTION_DELETE', $user);
1027
				if ($result < 0) {
1028
					$error++;
1029
				}
1030
				// End call triggers
1031
			}
1032
1033
			if (!$error) {
1034
				$this->db->commit();
1035
				return 1;
1036
			} else {
1037
				$this->db->rollback();
1038
				return -2;
1039
			}
1040
		} else {
1041
			$this->db->rollback();
1042
			$this->error = $this->db->lasterror();
1043
			return -1;
1044
		}
1045
	}
1046
1047
	/**
1048
	 *    Update action into database
1049
	 *	  If percentage = 100, on met a jour date 100%
1050
	 *
1051
	 *    @param    User	$user			Object user making change
1052
	 *    @param    int		$notrigger		1 = disable triggers, 0 = enable triggers
1053
	 *    @return   int     				<0 if KO, >0 if OK
1054
	 */
1055
	public function update(User $user, $notrigger = 0)
1056
	{
1057
		global $langs, $conf, $hookmanager;
1058
1059
		$error = 0;
1060
1061
		// Clean parameters
1062
		$this->label = trim($this->label);
1063
		$this->note_private = dol_htmlcleanlastbr(trim(!isset($this->note_private) ? $this->note : $this->note_private));
1064
		if (empty($this->percentage)) {
1065
			$this->percentage = 0;
1066
		}
1067
		if (empty($this->priority) || !is_numeric($this->priority)) {
1068
			$this->priority = 0;
1069
		}
1070
		if (empty($this->transparency)) {
1071
			$this->transparency = 0;
1072
		}
1073
		if (empty($this->fulldayevent)) {
1074
			$this->fulldayevent = 0;
1075
		}
1076
		if ($this->percentage > 100) {
1077
			$this->percentage = 100;
1078
		}
1079
		//if ($this->percentage == 100 && ! $this->dateend) $this->dateend = $this->date;
1080
		if ($this->datep && $this->datef) {
1081
			$this->durationp = ($this->datef - $this->datep); // deprecated
1082
		}
1083
		//if ($this->date  && $this->dateend) $this->durationa=($this->dateend - $this->date);
1084
		if ($this->datep && $this->datef && $this->datep > $this->datef) {
1085
			$this->datef = $this->datep;
1086
		}
1087
		//if ($this->date  && $this->dateend && $this->date > $this->dateend) $this->dateend=$this->date;
1088
		if ($this->fk_project < 0) {
1089
			$this->fk_project = 0;
1090
		}
1091
1092
		// Check parameters
1093
		if ($this->percentage == 0 && $this->userdoneid > 0) {
1094
			$this->error = "ErrorCantSaveADoneUserWithZeroPercentage";
1095
			return -1;
1096
		}
1097
1098
		$socid = (($this->socid > 0) ? $this->socid : 0);
1099
		$contactid = (($this->contact_id > 0) ? $this->contact_id : 0);
1100
		$userownerid = ($this->userownerid ? $this->userownerid : 0);
1101
		$userdoneid = ($this->userdoneid ? $this->userdoneid : 0);
1102
1103
		$this->db->begin();
1104
1105
		$sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm ";
1106
		$sql .= " SET percent = '".$this->db->escape($this->percentage)."'";
1107
		if ($this->type_id > 0) {
1108
			$sql .= ", fk_action = '".$this->db->escape($this->type_id)."'";
1109
		}
1110
		$sql .= ", label = ".($this->label ? "'".$this->db->escape($this->label)."'" : "null");
1111
		$sql .= ", datep = ".(strval($this->datep) != '' ? "'".$this->db->idate($this->datep)."'" : 'null');
1112
		$sql .= ", datep2 = ".(strval($this->datef) != '' ? "'".$this->db->idate($this->datef)."'" : 'null');
1113
		$sql .= ", durationp = ".(isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '' ? "'".$this->db->escape($this->durationp)."'" : "null"); // deprecated
1114
		$sql .= ", note = '".$this->db->escape($this->note_private)."'";
1115
		$sql .= ", fk_project =".($this->fk_project > 0 ? $this->fk_project : "null");
1116
		$sql .= ", fk_soc =".($socid > 0 ? $socid : "null");
1117
		$sql .= ", fk_contact =".($contactid > 0 ? $contactid : "null");
1118
		$sql .= ", priority = '".$this->db->escape($this->priority)."'";
1119
		$sql .= ", fulldayevent = '".$this->db->escape($this->fulldayevent)."'";
1120
		$sql .= ", location = ".($this->location ? "'".$this->db->escape($this->location)."'" : "null");
1121
		$sql .= ", transparency = '".$this->db->escape($this->transparency)."'";
1122
		$sql .= ", fk_user_mod = ".$user->id;
1123
		$sql .= ", fk_user_action = ".($userownerid > 0 ? "'".$this->db->escape($userownerid)."'" : "null");
1124
		$sql .= ", fk_user_done = ".($userdoneid > 0 ? "'".$this->db->escape($userdoneid)."'" : "null");
1125
		if (!empty($this->fk_element)) {
1126
			$sql .= ", fk_element=".($this->fk_element ? $this->db->escape($this->fk_element) : "null");
1127
		}
1128
		if (!empty($this->elementtype)) {
1129
			$sql .= ", elementtype=".($this->elementtype ? "'".$this->db->escape($this->elementtype)."'" : "null");
1130
		}
1131
		if (!empty($this->num_vote)) {
1132
			$sql .= ", num_vote=".($this->num_vote ? (int) $this->num_vote : null);
1133
		}
1134
		if (!empty($this->event_paid)) {
1135
			$sql .= ", event_paid=".($this->event_paid ? (int) $this->event_paid : 0);
1136
		}
1137
		if (!empty($this->status)) {
1138
			$sql .= ", status=".($this->status ? (int) $this->status : 0);
1139
		}
1140
		$sql .= " WHERE id=".$this->id;
1141
1142
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
1143
		if ($this->db->query($sql)) {
1144
			$action = 'update';
1145
1146
			// Actions on extra fields
1147
			if (!$error) {
1148
				$result = $this->insertExtraFields();
1149
				if ($result < 0) {
1150
					$error++;
1151
				}
1152
			}
1153
1154
			// Now insert assignedusers
1155
			if (!$error) {
1156
				$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".$this->id." AND element_type = 'user'";
1157
				$resql = $this->db->query($sql);
1158
1159
				$already_inserted = array();
1160
				foreach ($this->userassigned as $key => $val) {
1161
					if (!is_array($val)) {	// For backward compatibility when val=id
1162
						$val = array('id'=>$val);
1163
					}
1164
					if (!empty($already_inserted[$val['id']])) continue;
1165
1166
					$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1167
					$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']).")";
1168
1169
					$resql = $this->db->query($sql);
1170
					if (!$resql) {
1171
						$error++;
1172
						$this->errors[] = $this->db->lasterror();
1173
					} else {
1174
						$already_inserted[$val['id']] = true;
1175
					}
1176
					//var_dump($sql);exit;
1177
				}
1178
			}
1179
1180
			if (!$error) {
1181
				$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_resources where fk_actioncomm = ".$this->id." AND element_type = 'socpeople'";
1182
				$resql = $this->db->query($sql);
1183
1184
				if (!empty($this->socpeopleassigned)) {
1185
					$already_inserted = array();
1186
					foreach (array_keys($this->socpeopleassigned) as $id) {
1187
						if (!empty($already_inserted[$val['id']])) continue;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $val does not seem to be defined for all execution paths leading up to this point.
Loading history...
1188
1189
						$sql = "INSERT INTO ".MAIN_DB_PREFIX."actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1190
						$sql .= " VALUES(".$this->id.", 'socpeople', ".$id.", 0, 0, 0)";
1191
1192
						$resql = $this->db->query($sql);
1193
						if (!$resql) {
1194
							$error++;
1195
							$this->errors[] = $this->db->lasterror();
1196
						} else {
1197
							$already_inserted[$val['id']] = true;
1198
						}
1199
					}
1200
				}
1201
			}
1202
1203
			if (!$error && !$notrigger) {
1204
				// Call trigger
1205
				$result = $this->call_trigger('ACTION_MODIFY', $user);
1206
				if ($result < 0) {
1207
					$error++;
1208
				}
1209
				// End call triggers
1210
			}
1211
1212
			if (!$error) {
1213
				$this->db->commit();
1214
				return 1;
1215
			} else {
1216
				$this->db->rollback();
1217
				dol_syslog(get_class($this)."::update ".join(',', $this->errors), LOG_ERR);
1218
				return -2;
1219
			}
1220
		} else {
1221
			$this->db->rollback();
1222
			$this->error = $this->db->lasterror();
1223
			return -1;
1224
		}
1225
	}
1226
1227
	/**
1228
	 *  Load all objects with filters.
1229
	 *  @todo WARNING: This make a fetch on all records instead of making one request with a join.
1230
	 *
1231
	 *  @param		DoliDb	$db				Not used
1232
	 *  @param		int		$socid			Filter by thirdparty
1233
	 *  @param		int		$fk_element		Id of element action is linked to
1234
	 *  @param		string	$elementtype	Type of element action is linked to
1235
	 *  @param		string	$filter			Other filter
1236
	 *  @param		string	$sortfield		Sort on this field
1237
	 *  @param		string	$sortorder		ASC or DESC
1238
	 *  @param		string	$limit			Limit number of answers
1239
	 *  @return		array|string			Error string if KO, array with actions if OK
1240
	 */
1241
	public static function getActions($db, $socid = 0, $fk_element = 0, $elementtype = '', $filter = '', $sortfield = 'a.datep', $sortorder = 'DESC', $limit = 0)
1242
	{
1243
		global $conf, $langs;
1244
1245
		$resarray = array();
1246
1247
		dol_syslog(get_class()."::getActions", LOG_DEBUG);
1248
1249
		$sql = "SELECT a.id";
1250
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1251
		$sql .= " WHERE a.entity IN (".getEntity('agenda').")";
1252
		if (!empty($socid)) {
1253
			$sql .= " AND a.fk_soc = ".((int) $socid);
1254
		}
1255
		if (!empty($elementtype)) {
1256
			if ($elementtype == 'project') {
1257
				$sql .= ' AND a.fk_project = '.((int) $fk_element);
1258
			} elseif ($elementtype == 'contact') {
1259
				$sql .= ' AND a.id IN';
1260
				$sql .= " (SELECT fk_actioncomm FROM ".MAIN_DB_PREFIX."actioncomm_resources WHERE";
1261
				$sql .= " element_type = 'socpeople' AND fk_element = ".((int) $fk_element).')';
1262
			} else {
1263
				$sql .= " AND a.fk_element = ".((int) $fk_element)." AND a.elementtype = '".$db->escape($elementtype)."'";
1264
			}
1265
		}
1266
		if (!empty($filter)) {
1267
			$sql .= $filter;
1268
		}
1269
		if ($sortorder && $sortfield) {
1270
			$sql .= $db->order($sortfield, $sortorder);
1271
		}
1272
		$sql .= $db->plimit($limit, 0);
1273
1274
		$resql = $db->query($sql);
1275
		if ($resql) {
1276
			$num = $db->num_rows($resql);
1277
1278
			if ($num) {
1279
				for ($i = 0; $i < $num; $i++) {
1280
					$obj = $db->fetch_object($resql);
1281
					$actioncommstatic = new ActionComm($db);
1282
					$actioncommstatic->fetch($obj->id);
1283
					$resarray[$i] = $actioncommstatic;
1284
				}
1285
			}
1286
			$db->free($resql);
1287
			return $resarray;
1288
		} else {
1289
			return $db->lasterror();
1290
		}
1291
	}
1292
1293
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1294
	/**
1295
	 * Load indicators for dashboard (this->nbtodo and this->nbtodolate)
1296
	 *
1297
	 * @param	User	$user   			Objet user
1298
	 * @param	int		$load_state_board	Load indicator array this->nb
1299
	 * @return WorkboardResponse|int 		<0 if KO, WorkboardResponse if OK
1300
	 */
1301
	public function load_board($user, $load_state_board = 0)
1302
	{
1303
		// phpcs:enable
1304
		global $conf, $langs;
1305
1306
		if (empty($load_state_board)) {
1307
			$sql = "SELECT a.id, a.datep as dp";
1308
		} else {
1309
			$this->nb = array();
1310
			$sql = "SELECT count(a.id) as nb";
1311
		}
1312
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
1313
		if (!$user->rights->societe->client->voir && !$user->socid) {
1314
			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON a.fk_soc = sc.fk_soc";
1315
		}
1316
		if (!$user->rights->agenda->allactions->read) {
1317
			$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;
1318
		}
1319
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON a.fk_soc = s.rowid";
1320
		$sql .= " WHERE 1 = 1";
1321
		if (empty($load_state_board)) {
1322
			$sql .= " AND a.percent >= 0 AND a.percent < 100";
1323
		}
1324
		$sql .= " AND a.entity IN (".getEntity('agenda').")";
1325
		if (!$user->rights->societe->client->voir && !$user->socid) {
1326
			$sql .= " AND (a.fk_soc IS NULL OR sc.fk_user = ".$user->id.")";
1327
		}
1328
		if ($user->socid) {
1329
			$sql .= " AND a.fk_soc = ".$user->socid;
1330
		}
1331
		if (!$user->rights->agenda->allactions->read) {
1332
			$sql .= " AND (a.fk_user_author = ".$user->id." OR a.fk_user_action = ".$user->id." OR a.fk_user_done = ".$user->id;
1333
			$sql .= " OR ar.fk_element = ".$user->id; // Added by PV
1334
			$sql .= ")";
1335
		}
1336
1337
		$resql = $this->db->query($sql);
1338
		if ($resql) {
1339
			if (empty($load_state_board)) {
1340
				$agenda_static = new ActionComm($this->db);
1341
				$response = new WorkboardResponse();
1342
				$response->warning_delay = $conf->agenda->warning_delay / 60 / 60 / 24;
1343
				$response->label = $langs->trans("ActionsToDo");
1344
				$response->labelShort = $langs->trans("ActionsToDoShort");
1345
				$response->url = DOL_URL_ROOT.'/comm/action/list.php?action=show_list&actioncode=0&status=todo&mainmenu=agenda';
1346
				if ($user->rights->agenda->allactions->read) {
1347
					$response->url .= '&filtert=-1';
1348
				}
1349
				$response->img = img_object('', "action", 'class="inline-block valigntextmiddle"');
1350
			}
1351
			// This assignment in condition is not a bug. It allows walking the results.
1352
			while ($obj = $this->db->fetch_object($resql)) {
1353
				if (empty($load_state_board)) {
1354
					$response->nbtodo++;
1355
					$agenda_static->datep = $this->db->jdate($obj->dp);
1356
					if ($agenda_static->hasDelay()) {
1357
						$response->nbtodolate++;
1358
					}
1359
				} else {
1360
					$this->nb["actionscomm"] = $obj->nb;
1361
				}
1362
			}
1363
1364
			$this->db->free($resql);
1365
			if (empty($load_state_board)) {
1366
				return $response;
1367
			} else {
1368
				return 1;
1369
			}
1370
		} else {
1371
			dol_print_error($this->db);
1372
			$this->error = $this->db->error();
1373
			return -1;
1374
		}
1375
	}
1376
1377
1378
	/**
1379
	 *  Charge les informations d'ordre info dans l'objet facture
1380
	 *
1381
	 *  @param	int		$id       	Id de la facture a charger
1382
	 *  @return	void
1383
	 */
1384
	public function info($id)
1385
	{
1386
		$sql = 'SELECT ';
1387
		$sql .= ' a.id,';
1388
		$sql .= ' datec,';
1389
		$sql .= ' tms as datem,';
1390
		$sql .= ' fk_user_author,';
1391
		$sql .= ' fk_user_mod';
1392
		$sql .= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a';
1393
		$sql .= ' WHERE a.id = '.((int) $id);
1394
1395
		dol_syslog(get_class($this)."::info", LOG_DEBUG);
1396
		$result = $this->db->query($sql);
1397
		if ($result) {
1398
			if ($this->db->num_rows($result)) {
1399
				$obj = $this->db->fetch_object($result);
1400
				$this->id = $obj->id;
1401
				if ($obj->fk_user_author) {
1402
					$cuser = new User($this->db);
1403
					$cuser->fetch($obj->fk_user_author);
1404
					$this->user_creation = $cuser;
1405
				}
1406
				if ($obj->fk_user_mod) {
1407
					$muser = new User($this->db);
1408
					$muser->fetch($obj->fk_user_mod);
1409
					$this->user_modification = $muser;
1410
				}
1411
1412
				$this->date_creation = $this->db->jdate($obj->datec);
1413
				if (!empty($obj->fk_user_mod)) {
1414
					$this->date_modification = $this->db->jdate($obj->datem);
1415
				}
1416
			}
1417
			$this->db->free($result);
1418
		} else {
1419
			dol_print_error($this->db);
1420
		}
1421
	}
1422
1423
1424
	/**
1425
	 *  Return label of status
1426
	 *
1427
	 *  @param	int		$mode           0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
1428
	 *  @param  int		$hidenastatus   1=Show nothing if status is "Not applicable"
1429
	 *  @return string          		String with status
1430
	 */
1431
	public function getLibStatut($mode, $hidenastatus = 0)
1432
	{
1433
		return $this->LibStatut($this->percentage, $mode, $hidenastatus, $this->datep);
1434
	}
1435
1436
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1437
	/**
1438
	 *  Return label of action status
1439
	 *
1440
	 *  @param  int     $percent        Percent
1441
	 *  @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
1442
	 *  @param  int		$hidenastatus   1=Show nothing if status is "Not applicable"
1443
	 *  @param  int     $datestart      Date start of event
1444
	 *  @return string		    		Label
1445
	 */
1446
	public function LibStatut($percent, $mode, $hidenastatus = 0, $datestart = '')
1447
	{
1448
		// phpcs:enable
1449
		global $langs;
1450
1451
		$labelStatus = $langs->trans('StatusNotApplicable');
1452
		if ($percent == -1 && !$hidenastatus) {
1453
			$labelStatus = $langs->trans('StatusNotApplicable');
1454
		} elseif ($percent == 0) {
1455
			$labelStatus = $langs->trans('StatusActionToDo').' (0%)';
1456
		} elseif ($percent > 0 && $percent < 100) {
1457
			$labelStatus = $langs->trans('StatusActionInProcess').' ('.$percent.'%)';
1458
		} elseif ($percent >= 100) {
1459
			$labelStatus = $langs->trans('StatusActionDone').' (100%)';
1460
		}
1461
1462
		$labelStatusShort = $langs->trans('StatusNotApplicable');
1463
		if ($percent == -1 && !$hidenastatus) {
1464
			$labelStatusShort = $langs->trans('NA');
1465
		} elseif ($percent == 0) {
1466
			$labelStatusShort = '0%';
1467
		} elseif ($percent > 0 && $percent < 100) {
1468
			$labelStatusShort = $percent.'%';
1469
		} elseif ($percent >= 100) {
1470
			$labelStatusShort = '100%';
1471
		}
1472
1473
		$statusType = 'status9';
1474
		if ($percent == -1 && !$hidenastatus) {
1475
			$statusType = 'status9';
1476
		}
1477
		if ($percent == 0) {
1478
			$statusType = 'status1';
1479
		}
1480
		if ($percent > 0 && $percent < 100) {
1481
			$statusType = 'status3';
1482
		}
1483
		if ($percent >= 100) {
1484
			$statusType = 'status6';
1485
		}
1486
1487
		return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1488
	}
1489
1490
	/**
1491
	 *  Return URL of event
1492
	 *  Use $this->id, $this->type_code, $this->label and $this->type_label
1493
	 *
1494
	 *  @param	int		$withpicto				0 = No picto, 1 = Include picto into link, 2 = Only picto
1495
	 *  @param	int		$maxlength				Max number of charaters into label. If negative, use the ref as label.
1496
	 *  @param	string	$classname				Force style class on a link
1497
	 *  @param	string	$option					'' = Link to action, 'birthday'= Link to contact, 'holiday' = Link to leave
1498
	 *  @param	int		$overwritepicto			1 = Overwrite picto with this one
1499
	 *  @param	int   	$notooltip		    	1 = Disable tooltip
1500
	 *  @param  int     $save_lastsearch_value  -1 = Auto, 0 = No save of lastsearch_values when clicking, 1 = Save lastsearch_values whenclicking
1501
	 *  @return	string							Chaine avec URL
1502
	 */
1503
	public function getNomUrl($withpicto = 0, $maxlength = 0, $classname = '', $option = '', $overwritepicto = 0, $notooltip = 0, $save_lastsearch_value = -1)
1504
	{
1505
		global $conf, $langs, $user, $hookmanager, $action;
1506
1507
		if (!empty($conf->dol_no_mouse_hover)) {
1508
			$notooltip = 1; // Force disable tooltips
1509
		}
1510
1511
		$canread = 0;
1512
		if ($user->rights->agenda->myactions->read && $this->authorid == $user->id) {
1513
			$canread = 1; // Can read my event
1514
		}
1515
		if ($user->rights->agenda->myactions->read && array_key_exists($user->id, $this->userassigned)) {
1516
			$canread = 1; // Can read my event i am assigned
1517
		}
1518
		if ($user->rights->agenda->allactions->read) {
1519
			$canread = 1; // Can read all event of other
1520
		}
1521
		if (!$canread) {
1522
			$option = 'nolink';
1523
		}
1524
1525
		$label = $this->label;
1526
		if (empty($label)) {
1527
			$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...
1528
		}
1529
1530
		$result = '';
1531
1532
		// Set label of type
1533
		$labeltype = '';
1534
		if ($this->type_code) {
1535
			$labeltype = ($langs->transnoentities("Action".$this->type_code) != "Action".$this->type_code) ? $langs->transnoentities("Action".$this->type_code) : $this->type_label;
1536
		}
1537
		if (empty($conf->global->AGENDA_USE_EVENT_TYPE)) {
1538
			if ($this->type_code != 'AC_OTH_AUTO') {
1539
				$labeltype = $langs->trans('ActionAC_MANUAL');
1540
			}
1541
		}
1542
1543
		$tooltip = img_picto('', $this->picto).' <u>'.$langs->trans('Action').'</u>';
1544
		if (!empty($this->ref)) {
1545
			$tooltip .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1546
		}
1547
		if (!empty($label)) {
1548
			$tooltip .= '<br><b>'.$langs->trans('Title').':</b> '.$label;
1549
		}
1550
		if (!empty($labeltype)) {
1551
			$tooltip .= '<br><b>'.$langs->trans('Type').':</b> '.$labeltype;
1552
		}
1553
		if (!empty($this->location)) {
1554
			$tooltip .= '<br><b>'.$langs->trans('Location').':</b> '.$this->location;
1555
		}
1556
		if (isset($this->transparency)) {
1557
			$tooltip .= '<br><b>'.$langs->trans('Busy').':</b> '.yn($this->transparency);
1558
		}
1559
		if (!empty($this->note_private)) {
1560
			$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));
1561
		}
1562
		$linkclose = '';
1563
		//if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && $this->type_color)
1564
		//	$linkclose = ' style="background-color:#'.$this->type_color.'"';
1565
1566
		if (empty($notooltip)) {
1567
			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1568
				$label = $langs->trans("ShowAction");
1569
				$linkclose .= ' alt="'.dol_escape_htmltag($tooltip, 1).'"';
1570
			}
1571
			$linkclose .= ' title="'.dol_escape_htmltag($tooltip, 1).'"';
1572
			$linkclose .= ' class="'.$classname.' classfortooltip"';
1573
1574
			/*
1575
			$hookmanager->initHooks(array('actiondao'));
1576
			$parameters=array('id'=>$this->id);
1577
			$reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action);    // Note that $action and $object may have been modified by some hooks
1578
			$linkclose = ($hookmanager->resPrint ? $hookmanager->resPrint : $linkclose);
1579
			*/
1580
		} else {
1581
			$linkclose .= ' class="'.$classname.'"';
1582
		}
1583
1584
		$url = '';
1585
		if ($option == 'birthday') {
1586
			$url = DOL_URL_ROOT.'/contact/perso.php?id='.$this->id;
1587
		} elseif ($option == 'holiday') {
1588
			$url = DOL_URL_ROOT.'/holiday/card.php?id='.$this->id;
1589
		} else {
1590
			$url = DOL_URL_ROOT.'/comm/action/card.php?id='.$this->id;
1591
		}
1592
1593
		if ($option !== 'nolink') {
1594
			// Add param to save lastsearch_values or not
1595
			$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1596
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1597
				$add_save_lastsearch_values = 1;
1598
			}
1599
			if ($add_save_lastsearch_values) {
1600
				$url .= '&save_lastsearch_values=1';
1601
			}
1602
		}
1603
1604
		$linkstart = '<a href="'.$url.'"';
1605
		$linkstart .= $linkclose.'>';
1606
		$linkend = '</a>';
1607
1608
		if ($option == 'nolink') {
1609
			$linkstart = '';
1610
			$linkend = '';
1611
		}
1612
1613
		if ($withpicto == 2) {
1614
			$libelle = $label;
1615
			if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) {
1616
				$libelle = $labeltype;
1617
			}
1618
			$libelleshort = '';
1619
		} else {
1620
			$libelle = (empty($this->libelle) ? $label : $this->libelle.(($label && $label != $this->libelle) ? ' '.$label : ''));
1621
			if (!empty($conf->global->AGENDA_USE_EVENT_TYPE) && empty($libelle)) {
1622
				$libelle = $labeltype;
1623
			}
1624
			if ($maxlength < 0) {
1625
				$libelleshort = $this->ref;
1626
			} else {
1627
				$libelleshort = dol_trunc($libelle, $maxlength);
1628
			}
1629
		}
1630
1631
		if ($withpicto) {
1632
			if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) {	// Add code into ()
1633
				if ($labeltype) {
1634
					$libelle .= (preg_match('/'.preg_quote($labeltype, '/').'/', $libelle) ? '' : ' ('.$langs->transnoentities("Action".$this->type_code).')');
1635
				}
1636
			}
1637
		}
1638
1639
		$result .= $linkstart;
1640
		if ($withpicto) {
1641
			$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);
1642
		}
1643
		$result .= $libelleshort;
1644
		$result .= $linkend;
1645
1646
		global $action;
1647
		$hookmanager->initHooks(array('actiondao'));
1648
		$parameters = array('id'=>$this->id, 'getnomurl'=>$result);
1649
		$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1650
		if ($reshook > 0) {
1651
			$result = $hookmanager->resPrint;
1652
		} else {
1653
			$result .= $hookmanager->resPrint;
1654
		}
1655
1656
		return $result;
1657
	}
1658
1659
	/**
1660
	 *  Return Picto of type of event
1661
	 *
1662
	 *  @return	string							HTML String
1663
	 */
1664
	public function getTypePicto()
1665
	{
1666
		global $conf;
1667
1668
		$imgpicto = '';
1669
		if (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) {
1670
			$color = '';
1671
			if ($this->type_color) {
1672
				$color = 'style="color: #'.$this->type_color.' !important;"';
1673
			}
1674
			if ($this->type_picto) {
1675
				$imgpicto = img_picto('', $this->type_picto, 'class="paddingright"');
1676
			} else {
1677
				if ($this->type_code == 'AC_RDV') {
1678
					$imgpicto = img_picto('', 'meeting', $color, false, 0, 0, '', 'paddingright');
1679
				} elseif ($this->type_code == 'AC_TEL') {
1680
					$imgpicto = img_picto('', 'object_phoning', $color, false, 0, 0, '', 'paddingright');
1681
				} elseif ($this->type_code == 'AC_FAX') {
1682
					$imgpicto = img_picto('', 'object_phoning_fax', $color, false, 0, 0, '', 'paddingright');
1683
				} elseif ($this->type_code == 'AC_EMAIL' || $this->type_code == 'AC_EMAIL_IN') {
1684
					$imgpicto = img_picto('', 'object_email', $color, false, 0, 0, '', 'paddingright');
1685
				} elseif ($this->type_code == 'AC_INT') {
1686
					$imgpicto = img_picto('', 'object_intervention', $color, false, 0, 0, '', 'paddingright');
1687
				} elseif ($this->type_code == 'AC_OTH' && $this->code == 'TICKET_MSG') {
1688
					$imgpicto = img_picto('', 'object_conversation', $color, false, 0, 0, '', 'paddingright');
1689
				} elseif ($this->type != 'systemauto') {
1690
					$imgpicto = img_picto('', 'user-cog', $color, false, 0, 0, '', 'paddingright');
1691
				} else {
1692
					$imgpicto = img_picto('', 'cog', $color, false, 0, 0, '', 'paddingright');
1693
				}
1694
			}
1695
		} else {
1696
			// 2 picto: 1 for auto, 1 for manual
1697
			if ($this->type != 'systemauto') {
1698
				$imgpicto = img_picto('', 'user-cog', '', false, 0, 0, '', 'paddingright');
1699
			} else {
1700
				$imgpicto = img_picto('', 'cog', '', false, 0, 0, '', 'paddingright');
1701
			}
1702
		}
1703
		return $imgpicto;
1704
	}
1705
1706
1707
	/**
1708
	 * Sets object to supplied categories.
1709
	 *
1710
	 * Deletes object from existing categories not supplied.
1711
	 * Adds it to non existing supplied categories.
1712
	 * Existing categories are left untouch.
1713
	 *
1714
	 * @param  int[]|int $categories Category or categories IDs
1715
	 * @return void
1716
	 */
1717
	public function setCategories($categories)
1718
	{
1719
		// Handle single category
1720
		if (!is_array($categories)) {
1721
			$categories = array($categories);
1722
		}
1723
1724
		// Get current categories
1725
		include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1726
		$c = new Categorie($this->db);
1727
		$existing = $c->containing($this->id, Categorie::TYPE_ACTIONCOMM, 'id');
1728
1729
		// Diff
1730
		if (is_array($existing)) {
0 ignored issues
show
introduced by
The condition is_array($existing) is always false.
Loading history...
1731
			$to_del = array_diff($existing, $categories);
1732
			$to_add = array_diff($categories, $existing);
1733
		} else {
1734
			$to_del = array(); // Nothing to delete
1735
			$to_add = $categories;
1736
		}
1737
1738
		// Process
1739
		foreach ($to_del as $del) {
1740
			if ($c->fetch($del) > 0) {
1741
				$c->del_type($this, Categorie::TYPE_ACTIONCOMM);
1742
			}
1743
		}
1744
		foreach ($to_add as $add) {
1745
			if ($c->fetch($add) > 0) {
1746
				$c->add_type($this, Categorie::TYPE_ACTIONCOMM);
1747
			}
1748
		}
1749
		return;
1750
	}
1751
1752
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1753
	/**
1754
	 * Export events from database into a cal file.
1755
	 *
1756
	 * @param string    $format         The format of the export 'vcal', 'ical/ics' or 'rss'
1757
	 * @param string    $type           The type of the export 'event' or 'journal'
1758
	 * @param integer   $cachedelay     Do not rebuild file if date older than cachedelay seconds
1759
	 * @param string    $filename       The name for the exported file.
1760
	 * @param array     $filters        Array of filters. Example array('notolderthan'=>99, 'year'=>..., 'idfrom'=>..., 'notactiontype'=>'systemauto', 'project'=>123, ...)
1761
	 * @param integer   $exportholiday  0 = don't integrate holidays into the export, 1 = integrate holidays into the export
1762
	 * @return integer                  -1 = error on build export file, 0 = export okay
1763
	 */
1764
	public function build_exportfile($format, $type, $cachedelay, $filename, $filters, $exportholiday = 0)
1765
	{
1766
		global $hookmanager;
1767
1768
		// phpcs:enable
1769
		global $conf, $langs, $dolibarr_main_url_root, $mysoc;
1770
1771
		require_once DOL_DOCUMENT_ROOT."/core/lib/xcal.lib.php";
1772
		require_once DOL_DOCUMENT_ROOT."/core/lib/date.lib.php";
1773
		require_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php";
1774
1775
		dol_syslog(get_class($this)."::build_exportfile Build export file format=".$format.", type=".$type.", cachedelay=".$cachedelay.", filename=".$filename.", filters size=".count($filters), LOG_DEBUG);
1776
1777
		// Check parameters
1778
		if (empty($format)) {
1779
			return -1;
1780
		}
1781
1782
		// Clean parameters
1783
		if (!$filename) {
1784
			$extension = 'vcs';
1785
			if ($format == 'ical') {
1786
				$extension = 'ics';
1787
			}
1788
			$filename = $format.'.'.$extension;
1789
		}
1790
1791
		// Create dir and define output file (definitive and temporary)
1792
		$result = dol_mkdir($conf->agenda->dir_temp);
1793
		$outputfile = $conf->agenda->dir_temp.'/'.$filename;
1794
1795
		$result = 0;
1796
1797
		$buildfile = true;
1798
		$login = ''; $logina = ''; $logind = ''; $logint = '';
1799
1800
		$now = dol_now();
1801
1802
		if ($cachedelay) {
1803
			$nowgmt = dol_now();
1804
			include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1805
			if (dol_filemtime($outputfile) > ($nowgmt - $cachedelay)) {
1806
				dol_syslog(get_class($this)."::build_exportfile file ".$outputfile." is not older than now - cachedelay (".$nowgmt." - ".$cachedelay."). Build is canceled");
1807
				$buildfile = false;
1808
			}
1809
		}
1810
1811
		if ($buildfile) {
1812
			// Build event array
1813
			$eventarray = array();
1814
1815
			$sql = "SELECT a.id,";
1816
			$sql .= " a.datep,"; // Start
1817
			$sql .= " a.datep2,"; // End
1818
			$sql .= " a.durationp,"; // deprecated
1819
			$sql .= " a.datec, a.tms as datem,";
1820
			$sql .= " a.label, a.code, a.note, a.fk_action as type_id,";
1821
			$sql .= " a.fk_soc,";
1822
			$sql .= " a.fk_user_author, a.fk_user_mod,";
1823
			$sql .= " a.fk_user_action,";
1824
			$sql .= " a.fk_contact, a.percent as percentage,";
1825
			$sql .= " a.fk_element, a.elementtype,";
1826
			$sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
1827
			$sql .= " u.firstname, u.lastname, u.email,";
1828
			$sql .= " s.nom as socname,";
1829
			$sql .= " c.id as type_id, c.code as type_code, c.libelle as type_label,";
1830
			$sql .= " num_vote, event_paid, a.status";
1831
			$sql .= " FROM (".MAIN_DB_PREFIX."c_actioncomm as c, ".MAIN_DB_PREFIX."actioncomm as a)";
1832
			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author"; // Link to get author of event for export
1833
			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc";
1834
1835
			$parameters = array('filters' => $filters);
1836
			$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
1837
			$sql .= $hookmanager->resPrint;
1838
1839
			// We must filter on assignement table
1840
			if ($filters['logint']) {
1841
				$sql .= ", ".MAIN_DB_PREFIX."actioncomm_resources as ar";
1842
			}
1843
			$sql .= " WHERE a.fk_action=c.id";
1844
			$sql .= " AND a.entity IN (".getEntity('agenda').")";
1845
			foreach ($filters as $key => $value) {
1846
				if ($key == 'notolderthan' && $value != '') {
1847
					$sql .= " AND a.datep >= '".$this->db->idate($now - ($value * 24 * 60 * 60))."'";
1848
				}
1849
				if ($key == 'year') {
1850
					$sql .= " AND a.datep BETWEEN '".$this->db->idate(dol_get_first_day($value, 1))."' AND '".$this->db->idate(dol_get_last_day($value, 12))."'";
1851
				}
1852
				if ($key == 'id') {
1853
					$sql .= " AND a.id=".(is_numeric($value) ? $value : 0);
1854
				}
1855
				if ($key == 'idfrom') {
1856
					$sql .= " AND a.id >= ".(is_numeric($value) ? $value : 0);
1857
				}
1858
				if ($key == 'idto') {
1859
					$sql .= " AND a.id <= ".(is_numeric($value) ? $value : 0);
1860
				}
1861
				if ($key == 'project') {
1862
					$sql .= " AND a.fk_project=".(is_numeric($value) ? $value : 0);
1863
				}
1864
				if ($key == 'actiontype') {
1865
					$sql .= " AND c.type = '".$this->db->escape($value)."'";
1866
				}
1867
				if ($key == 'notactiontype') {
1868
					$sql .= " AND c.type <> '".$this->db->escape($value)."'";
1869
				}
1870
				// We must filter on assignement table
1871
				if ($key == 'logint') {
1872
					$sql .= " AND ar.fk_actioncomm = a.id AND ar.element_type='user'";
1873
				}
1874
				if ($key == 'logina') {
1875
					$logina = $value;
1876
					$condition = '=';
1877
					if (preg_match('/^!/', $logina)) {
1878
						$logina = preg_replace('/^!/', '', $logina);
1879
						$condition = '<>';
1880
					}
1881
					$userforfilter = new User($this->db);
1882
					$result = $userforfilter->fetch('', $logina);
1883
					if ($result > 0) {
1884
						$sql .= " AND a.fk_user_author ".$condition." ".$userforfilter->id;
1885
					} elseif ($result < 0 || $condition == '=') {
1886
						$sql .= " AND a.fk_user_author = 0";
1887
					}
1888
				}
1889
				if ($key == 'logint') {
1890
					$logint = $value;
1891
					$condition = '=';
1892
					if (preg_match('/^!/', $logint)) {
1893
						$logint = preg_replace('/^!/', '', $logint);
1894
						$condition = '<>';
1895
					}
1896
					$userforfilter = new User($this->db);
1897
					$result = $userforfilter->fetch('', $logint);
1898
					if ($result > 0) {
1899
						$sql .= " AND ar.fk_element = ".$userforfilter->id;
1900
					} elseif ($result < 0 || $condition == '=') {
1901
						$sql .= " AND ar.fk_element = 0";
1902
					}
1903
				}
1904
			}
1905
1906
			$sql .= " AND a.datep IS NOT NULL"; // To exclude corrupted events and avoid errors in lightning/sunbird import
1907
1908
			$parameters = array('filters' => $filters);
1909
			$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
1910
			$sql .= $hookmanager->resPrint;
1911
1912
			$sql .= " ORDER by datep";
1913
			//print $sql;exit;
1914
1915
			dol_syslog(get_class($this)."::build_exportfile select events", LOG_DEBUG);
1916
			$resql = $this->db->query($sql);
1917
			if ($resql) {
1918
				// Note: Output of sql request is encoded in $conf->file->character_set_client
1919
				// This assignment in condition is not a bug. It allows walking the results.
1920
				$diff = 0;
1921
				while ($obj = $this->db->fetch_object($resql)) {
1922
					$qualified = true;
1923
1924
					// 'eid','startdate','duration','enddate','title','summary','category','email','url','desc','author'
1925
					$event = array();
1926
					$event['uid'] = 'dolibarragenda-'.$this->db->database_name.'-'.$obj->id."@".$_SERVER["SERVER_NAME"];
1927
					$event['type'] = $type;
1928
					$datestart = $this->db->jdate($obj->datep) - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
1929
1930
					// fix for -> Warning: A non-numeric value encountered
1931
					if (is_numeric($this->db->jdate($obj->datep2))) {
1932
						$dateend = $this->db->jdate($obj->datep2)
1933
								 - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
1934
					} else {
1935
						// use start date as fall-back to avoid import erros on empty end date
1936
						$dateend = $datestart;
1937
					}
1938
1939
					$duration = ($datestart && $dateend) ? ($dateend - $datestart) : 0;
1940
					$event['summary'] = $obj->label.($obj->socname ? " (".$obj->socname.")" : "");
1941
					$event['desc'] = $obj->note;
1942
					$event['startdate'] = $datestart;
1943
					$event['enddate'] = $dateend; // Not required with type 'journal'
1944
					$event['duration'] = $duration; // Not required with type 'journal'
1945
					$event['author'] = dolGetFirstLastname($obj->firstname, $obj->lastname);
1946
					$event['priority'] = $obj->priority;
1947
					$event['fulldayevent'] = $obj->fulldayevent;
1948
					$event['location'] = $obj->location;
1949
					$event['transparency'] = (($obj->transparency > 0) ? 'OPAQUE' : 'TRANSPARENT'); // OPAQUE (busy) or TRANSPARENT (not busy)
1950
					$event['category'] = $obj->type_label;
1951
					$event['email'] = $obj->email;
1952
					// Define $urlwithroot
1953
					$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
1954
					$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
1955
					//$urlwithroot=DOL_MAIN_URL_ROOT;						// This is to use same domain name than current
1956
					$url = $urlwithroot.'/comm/action/card.php?id='.$obj->id;
1957
					$event['url'] = $url;
1958
					$event['created'] = $this->db->jdate($obj->datec) - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
1959
					$event['modified'] = $this->db->jdate($obj->datem) - (empty($conf->global->AGENDA_EXPORT_FIX_TZ) ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
1960
					$event['num_vote'] = $this->num_vote;
1961
					$event['event_paid'] = $this->event_paid;
1962
					$event['status'] = $this->status;
1963
1964
					// TODO: find a way to call "$this->fetch_userassigned();" without override "$this" properties
1965
					$this->id = $obj->id;
1966
					$this->fetch_userassigned(false);
1967
1968
					$assignedUserArray = array();
1969
1970
					foreach ($this->userassigned as $key => $value) {
1971
						$assignedUser = new User($this->db);
1972
						$assignedUser->fetch($value['id']);
1973
1974
						$assignedUserArray[$key] = $assignedUser;
1975
					}
1976
1977
					$event['assignedUsers'] = $assignedUserArray;
1978
1979
					if ($qualified && $datestart) {
1980
						$eventarray[] = $event;
1981
					}
1982
					$diff++;
1983
				}
1984
1985
				$parameters = array('filters' => $filters, 'eventarray' => &$eventarray);
1986
				$reshook = $hookmanager->executeHooks('addMoreEventsExport', $parameters); // Note that $action and $object may have been modified by hook
1987
				if ($reshook > 0) {
1988
					$eventarray = $hookmanager->resArray;
1989
				}
1990
			} else {
1991
				$this->error = $this->db->lasterror();
1992
				return -1;
1993
			}
1994
1995
			if ($exportholiday == 1) {
1996
				$langs->load("holidays");
1997
				$title = $langs->trans("Holidays");
1998
1999
				$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";
2000
				$sql .= " FROM ".MAIN_DB_PREFIX."holiday as x, ".MAIN_DB_PREFIX."user as u";
2001
				$sql .= " WHERE u.rowid = x.fk_user";
2002
				$sql .= " AND u.statut = '1'"; // Show only active users  (0 = inactive user, 1 = active user)
2003
				$sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
2004
2005
				$resql = $this->db->query($sql);
2006
				if ($resql) {
2007
					$num = $this->db->num_rows($resql);
2008
					$i   = 0;
2009
2010
					while ($i < $num) {
2011
						$obj   = $this->db->fetch_object($resql);
2012
						$event = array();
2013
2014
						if ($obj->halfday == -1) {
2015
							$event['fulldayevent'] = false;
2016
2017
							$timestampStart = dol_stringtotime($obj->date_start." 00:00:00", 0);
2018
							$timestampEnd   = dol_stringtotime($obj->date_end." 12:00:00", 0);
2019
						} elseif ($obj->halfday == 1) {
2020
							$event['fulldayevent'] = false;
2021
2022
							$timestampStart = dol_stringtotime($obj->date_start." 12:00:00", 0);
2023
							$timestampEnd   = dol_stringtotime($obj->date_end." 23:59:59", 0);
2024
						} else {
2025
							$event['fulldayevent'] = true;
2026
2027
							$timestampStart = dol_stringtotime($obj->date_start." 00:00:00", 0);
2028
							$timestampEnd   = dol_stringtotime($obj->date_end." 23:59:59", 0);
2029
						}
2030
2031
						if (!empty($conf->global->AGENDA_EXPORT_FIX_TZ)) {
2032
							$timestampStart = - ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
2033
							$timestampEnd   = - ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
2034
						}
2035
2036
						$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
2037
						$urlwithroot       = $urlwithouturlroot.DOL_URL_ROOT;
2038
						$url               = $urlwithroot.'/holiday/card.php?id='.$obj->rowid;
2039
2040
						$event['uid']          = 'dolibarrholiday-'.$this->db->database_name.'-'.$obj->rowid."@".$_SERVER["SERVER_NAME"];
2041
						$event['author']       = dolGetFirstLastname($obj->firstname, $obj->lastname);
2042
						$event['type']         = 'event';
2043
						$event['category']     = "Holiday";
2044
						$event['transparency'] = 'OPAQUE';
2045
						$event['email']        = $obj->email;
2046
						$event['created']      = $timestampStart;
2047
						$event['modified']     = $timestampStart;
2048
						$event['startdate']    = $timestampStart;
2049
						$event['enddate']      = $timestampEnd;
2050
						$event['duration']     = $timestampEnd - $timestampStart;
2051
						$event['url']          = $url;
2052
2053
						if ($obj->status == 2) {
2054
							// 2 = leave wait for approval
2055
							$event['summary'] = $title." - ".$obj->lastname." (wait for approval)";
2056
						} else {
2057
							// 3 = leave approved
2058
							$event['summary'] = $title." - ".$obj->lastname;
2059
						}
2060
2061
						$eventarray[] = $event;
2062
2063
						$i++;
2064
					}
2065
				}
2066
			}
2067
2068
			$langs->load("agenda");
2069
2070
			// Define title and desc
2071
			$more = '';
2072
			if ($login) {
2073
				$more = $langs->transnoentities("User").' '.$login;
2074
			}
2075
			if ($logina) {
2076
				$more = $langs->transnoentities("ActionsAskedBy").' '.$logina;
2077
			}
2078
			if ($logint) {
2079
				$more = $langs->transnoentities("ActionsToDoBy").' '.$logint;
2080
			}
2081
			if ($logind) {
2082
				$more = $langs->transnoentities("ActionsDoneBy").' '.$logind;
2083
			}
2084
			if ($more) {
2085
				$title = 'Dolibarr actions '.$mysoc->name.' - '.$more;
2086
				$desc = $more;
2087
				$desc .= ' ('.$mysoc->name.' - built by Dolibarr)';
2088
			} else {
2089
				$title = 'Dolibarr actions '.$mysoc->name;
2090
				$desc = $langs->transnoentities('ListOfActions');
2091
				$desc .= ' ('.$mysoc->name.' - built by Dolibarr)';
2092
			}
2093
2094
			// Create temp file
2095
			$outputfiletmp = tempnam($conf->agenda->dir_temp, 'tmp'); // Temporary file (allow call of function by different threads
2096
			@chmod($outputfiletmp, octdec($conf->global->MAIN_UMASK));
2097
2098
			// Write file
2099
			if ($format == 'vcal') {
2100
				$result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
2101
			} elseif ($format == 'ical') {
2102
				$result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
2103
			} elseif ($format == 'rss') {
2104
				$result = build_rssfile($format, $title, $desc, $eventarray, $outputfiletmp);
2105
			}
2106
2107
			if ($result >= 0) {
2108
				if (dol_move($outputfiletmp, $outputfile, 0, 1)) {
2109
					$result = 1;
2110
				} else {
2111
					$this->error = 'Failed to rename '.$outputfiletmp.' into '.$outputfile;
2112
					dol_syslog(get_class($this)."::build_exportfile ".$this->error, LOG_ERR);
2113
					dol_delete_file($outputfiletmp, 0, 1);
2114
					$result = -1;
2115
				}
2116
			} else {
2117
				dol_syslog(get_class($this)."::build_exportfile build_xxxfile function fails to for format=".$format." outputfiletmp=".$outputfile, LOG_ERR);
2118
				dol_delete_file($outputfiletmp, 0, 1);
2119
				$langs->load("errors");
2120
				$this->error = $langs->trans("ErrorFailToCreateFile", $outputfile);
2121
			}
2122
		}
2123
2124
		return $result;
2125
	}
2126
2127
	/**
2128
	 *  Initialise an instance with random values.
2129
	 *  Used to build previews or test instances.
2130
	 *  id must be 0 if object instance is a specimen.
2131
	 *
2132
	 *  @return	int >0 if ok
2133
	 */
2134
	public function initAsSpecimen()
2135
	{
2136
		global $user;
2137
2138
		$now = dol_now();
2139
2140
		// Initialise parametres
2141
		$this->id = 0;
2142
		$this->specimen = 1;
2143
2144
		$this->type_code = 'AC_OTH';
2145
		$this->code = 'AC_SPECIMEN_CODE';
2146
		$this->label = 'Label of event Specimen';
2147
		$this->datec = $now;
2148
		$this->datem = $now;
2149
		$this->datep = $now;
2150
		$this->datef = $now;
2151
		$this->fulldayevent = 0;
2152
		$this->percentage = 0;
2153
		$this->status = 0;
2154
		$this->location = 'Location';
2155
		$this->transparency = 1; // 1 means opaque
2156
		$this->priority = 1;
2157
		//$this->note_public = "This is a 'public' note.";
2158
		$this->note_private = "This is a 'private' note.";
2159
2160
		$this->userownerid = $user->id;
2161
		$this->userassigned[$user->id] = array('id'=>$user->id, 'transparency'=> 1);
2162
		return 1;
2163
	}
2164
2165
	/**
2166
	 *  Function used to replace a thirdparty id with another one.
2167
	 *
2168
	 *  @param DoliDB $db Database handler
2169
	 *  @param int $origin_id Old thirdparty id
2170
	 *  @param int $dest_id New thirdparty id
2171
	 *  @return bool
2172
	 */
2173
	public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2174
	{
2175
		$tables = array(
2176
			'actioncomm'
2177
		);
2178
2179
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2180
	}
2181
2182
	/**
2183
	 *  Is the action delayed?
2184
	 *
2185
	 *  @return bool
2186
	 */
2187
	public function hasDelay()
2188
	{
2189
		global $conf;
2190
2191
		$now = dol_now();
2192
2193
		return $this->datep && ($this->datep < ($now - $conf->agenda->warning_delay));
2194
	}
2195
2196
2197
	/**
2198
	 *  Load event reminder of events
2199
	 *
2200
	 *  @param	string	$type		Type of reminder 'browser' or 'email'
2201
	 *  @param	int		$fk_user	Id of user
2202
	 *  @param	bool	$onlypast	true = get only past reminder, false = get all reminders linked to this
2203
	 *  @return int         		0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
2204
	 */
2205
	public function loadReminders($type = '', $fk_user = 0, $onlypast = true)
2206
	{
2207
		global $conf, $langs, $user;
2208
2209
		$error = 0;
2210
2211
		$this->reminders = array();
2212
2213
		//Select all action comm reminders for event
2214
		$sql = "SELECT rowid as id, typeremind, dateremind, status, offsetvalue, offsetunit, fk_user";
2215
		$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2216
		$sql .= " WHERE fk_actioncomm = ".$this->id;
2217
		if ($onlypast) {
2218
			$sql .= " AND dateremind <= '".$this->db->idate(dol_now())."'";
2219
		}
2220
		if ($type) {
2221
			$sql .= " AND typeremind ='".$this->db->escape($type)."'";
2222
		}
2223
		if ($fk_user > 0) {
2224
			$sql .= " AND fk_user = ".((int) $fk_user);
2225
		}
2226
		if (empty($conf->global->AGENDA_REMINDER_EMAIL)) {
2227
			$sql .= " AND typeremind != 'email'";
2228
		}
2229
		if (empty($conf->global->AGENDA_REMINDER_BROWSER)) {
2230
			$sql .= " AND typeremind != 'browser'";
2231
		}
2232
2233
		$sql .= $this->db->order("dateremind", "ASC");
2234
		$resql = $this->db->query($sql);
2235
2236
		if ($resql) {
2237
			while ($obj = $this->db->fetch_object($resql)) {
2238
				$tmpactioncommreminder = new ActionCommReminder($this->db);
2239
				$tmpactioncommreminder->id = $obj->id;
2240
				$tmpactioncommreminder->typeremind = $obj->typeremind;
2241
				$tmpactioncommreminder->dateremind = $obj->dateremind;
2242
				$tmpactioncommreminder->offsetvalue = $obj->offsetvalue;
2243
				$tmpactioncommreminder->offsetunit = $obj->offsetunit;
2244
				$tmpactioncommreminder->status = $obj->status;
2245
				$tmpactioncommreminder->fk_user = $obj->fk_user;
2246
2247
				$this->reminders[$obj->id] = $tmpactioncommreminder;
2248
			}
2249
		} else {
2250
			$this->error = $this->db->lasterror();
2251
			$error++;
2252
		}
2253
2254
		return count($this->reminders);
2255
	}
2256
2257
2258
	/**
2259
	 *  Send reminders by emails
2260
	 *  CAN BE A CRON TASK
2261
	 *
2262
	 *  @return int         0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
2263
	 */
2264
	public function sendEmailsReminder()
2265
	{
2266
		global $conf, $langs, $user;
2267
2268
		$error = 0;
2269
		$this->output = '';
2270
		$this->error = '';
2271
		$nbMailSend = 0;
2272
		$errorsMsg = array();
2273
2274
		if (empty($conf->agenda->enabled)) {	// Should not happen. If module disabled, cron job should not be visible.
2275
			$langs->load("agenda");
2276
			$this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2277
			return 0;
2278
		}
2279
		if (empty($conf->global->AGENDA_REMINDER_EMAIL)) {
2280
			$langs->load("agenda");
2281
			$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2282
			return 0;
2283
		}
2284
2285
		$now = dol_now();
2286
		$actionCommReminder = new ActionCommReminder($this->db);
2287
2288
		dol_syslog(__METHOD__, LOG_DEBUG);
2289
2290
		$this->db->begin();
2291
2292
		//Select all action comm reminders
2293
		$sql = "SELECT rowid as id FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2294
		$sql .= " WHERE typeremind = 'email' AND status = 0";
2295
		$sql .= " AND dateremind <= '".$this->db->idate($now)."'";
2296
		$sql .= " AND entity IN (".getEntity('actioncomm').")";
2297
		$sql .= $this->db->order("dateremind", "ASC");
2298
		$resql = $this->db->query($sql);
2299
2300
		if ($resql) {
2301
			require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2302
			$formmail = new FormMail($this->db);
2303
2304
			while ($obj = $this->db->fetch_object($resql)) {
2305
				$res = $actionCommReminder->fetch($obj->id);
2306
				if ($res < 0) {
2307
					$error++;
2308
					$errorsMsg[] = "Failed to load invoice ActionComm Reminder";
2309
				}
2310
2311
				if (!$error) {
2312
					//Select email template
2313
					$arraymessage = $formmail->getEMailTemplate($this->db, 'actioncomm_send', $user, $langs, (!empty($actionCommReminder->fk_email_template)) ? $actionCommReminder->fk_email_template : -1, 1);
2314
2315
					// Load event
2316
					$res = $this->fetch($actionCommReminder->fk_actioncomm);
2317
					if ($res > 0) {
2318
						// PREPARE EMAIL
2319
						$errormesg = '';
2320
2321
						// Make substitution in email content
2322
						$substitutionarray = getCommonSubstitutionArray($langs, 0, '', $this);
2323
2324
						complete_substitutions_array($substitutionarray, $langs, $this);
2325
2326
						// Content
2327
						$sendContent = make_substitutions($langs->trans($arraymessage->content), $substitutionarray);
2328
2329
						//Topic
2330
						$sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->trans('EventReminder'));
2331
2332
						// Recipient
2333
						$recipient = new User($this->db);
2334
						$res = $recipient->fetch($actionCommReminder->fk_user);
2335
						if ($res > 0) {
2336
							if (!empty($recipient->email)) {
2337
								$to = $recipient->email;
2338
							} else {
2339
								$errormesg = "Failed to send remind to user id=".$actionCommReminder->fk_user.". No email defined for user.";
2340
								$error++;
2341
							}
2342
						} else {
2343
							$errormesg = "Failed to load recipient with user id=".$actionCommReminder->fk_user;
2344
							$error++;
2345
						}
2346
2347
						// Sender
2348
						$from = $conf->global->MAIN_MAIL_EMAIL_FROM;
2349
						if (empty($from)) {
2350
							$errormesg = "Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
2351
							$error++;
2352
						}
2353
2354
						if (!$error) {
2355
							// Errors Recipient
2356
							$errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
2357
2358
							// Mail Creation
2359
							$cMailFile = new CMailFile($sendTopic, $to, $from, $sendContent, array(), array(), array(), '', "", 0, 1, $errors_to, '', '', '', '', '');
2360
2361
							// Sending Mail
2362
							if ($cMailFile->sendfile()) {
2363
								$nbMailSend++;
2364
							} else {
2365
								$errormesg = $cMailFile->error.' : '.$to;
2366
								$error++;
2367
							}
2368
						}
2369
2370
						if (!$error) {
2371
							$actionCommReminder->status = $actionCommReminder::STATUS_DONE;
2372
2373
							$res = $actionCommReminder->update($user);
2374
							if ($res < 0) {
2375
								$errorsMsg[] = "Failed to update status to done of ActionComm Reminder";
2376
								$error++;
2377
								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.
2378
							}
2379
						} else {
2380
							$actionCommReminder->status = $actionCommReminder::STATUS_ERROR;
2381
							$actionCommReminder->lasterror = dol_trunc($errormesg, 128, 'right', 'UTF-8', 1);
2382
2383
							$res = $actionCommReminder->update($user);
2384
							if ($res < 0) {
2385
								$errorsMsg[] = "Failed to update status to error of ActionComm Reminder";
2386
								$error++;
2387
								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.
2388
							} else {
2389
								$errorsMsg[] = $errormesg;
2390
							}
2391
						}
2392
					} else {
2393
						$errorsMsg[] = 'Failed to fetch record actioncomm with ID = '.$actionCommReminder->fk_actioncomm;
2394
						$error++;
2395
					}
2396
				}
2397
			}
2398
		} else {
2399
			$error++;
2400
		}
2401
2402
		if (!$error) {
2403
			// Delete also very old past events (we do not keep more than 1 month record in past)
2404
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
2405
			$sql .= " WHERE dateremind < '".$this->db->idate($now - (3600 * 24 * 32))."'";
2406
			$sql .= " AND status = ".$actionCommReminder::STATUS_DONE;
2407
			$resql = $this->db->query($sql);
2408
2409
			if (!$resql) {
2410
				$errorsMsg[] = 'Failed to delete old reminders';
2411
				//$error++;		// If this fails, we must not rollback other SQL requests already done. Never mind.
2412
			}
2413
		}
2414
2415
		if (!$error) {
2416
			$this->output = 'Nb of emails sent : '.$nbMailSend;
2417
			$this->db->commit();
2418
			return 0;
2419
		} else {
2420
			$this->db->commit(); // We commit also on error, to have the error message recorded.
2421
			$this->error = 'Nb of emails sent : '.$nbMailSend.', '.(!empty($errorsMsg)) ? join(', ', $errorsMsg) : $error;
2422
			return $error;
2423
		}
2424
	}
2425
2426
	/**
2427
	 * Udpate the percent value of a event with the given id
2428
	 *
2429
	 * @param int		$id			The id of the event
2430
	 * @param int		$percent	The new percent value for the event
2431
	 * @return int					1 when update of the event was suscessfull, otherwise -1
2432
	 */
2433
	public function updatePercent($id, $percent)
2434
	{
2435
		$this->db->begin();
2436
2437
		$sql = "UPDATE ".MAIN_DB_PREFIX."actioncomm ";
2438
		$sql .= " SET percent = ".(int) $percent;
2439
		$sql .= " WHERE id=".$id;
2440
2441
		if ($this->db->query($sql)) {
2442
			$this->db->commit();
2443
			return 1;
2444
		} else {
2445
			$this->db->rollback();
2446
			$this->error = $this->db->lasterror();
2447
			return -1;
2448
		}
2449
	}
2450
}
2451