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

ActionComm::getActions()   B

Complexity

Conditions 11

Size

Total Lines 49
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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

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

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

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

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

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

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

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

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