Completed
Branch develop (5cf21f)
by
unknown
27:49
created

Task::hasChildren()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 17
nc 6
nop 0
dl 0
loc 28
rs 8.5806
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2008-2014	Laurent Destailleur	<[email protected]>
3
 * Copyright (C) 2010-2012	Regis Houssin		<[email protected]>
4
 * Copyright (C) 2014       Marcos García       <[email protected]>
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
/**
21
 *      \file       htdocs/projet/class/task.class.php
22
 *      \ingroup    project
23
 *      \brief      This file is a CRUD class file for Task (Create/Read/Update/Delete)
24
 */
25
26
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
27
28
29
/**
30
 * 	Class to manage tasks
31
 */
32
class Task extends CommonObject
33
{
34
	public $element='project_task';		//!< Id that identify managed objects
35
	public $table_element='projet_task';	//!< Name of table without prefix where object is stored
36
	public $fk_element='fk_task';
37
	public $picto = 'task';
38
	protected $childtables=array('projet_task_time','projet_task_comment');    // To test if we can delete object
39
40
	var $fk_task_parent;
41
	var $label;
42
	var $description;
43
	var $duration_effective;		// total of time spent on this task
44
	var $planned_workload;
45
	var $date_c;
46
	var $date_start;
47
	var $date_end;
48
	var $progress;
49
	var $fk_statut;
50
	var $priority;
51
	var $fk_user_creat;
52
	var $fk_user_valid;
53
	var $rang;
54
55
	var $timespent_min_date;
56
	var $timespent_max_date;
57
	var $timespent_total_duration;
58
	var $timespent_total_amount;
59
	var $timespent_nblinesnull;
60
	var $timespent_nblines;
61
	// For detail of lines of timespent record, there is the property ->lines in common
62
63
	// Var used to call method addTimeSpent(). Bad practice.
64
	var $timespent_id;
65
	var $timespent_duration;
66
	var $timespent_old_duration;
67
	var $timespent_date;
68
	var $timespent_datehour;		// More accurate start date (same than timespent_date but includes hours, minutes and seconds)
69
	var $timespent_withhour;		// 1 = we entered also start hours for timesheet line
70
	var $timespent_fk_user;
71
	var $timespent_note;
72
73
	var $comments = array();
74
75
	public $oldcopy;
76
77
78
	/**
79
	 *  Constructor
80
	 *
81
	 *  @param      DoliDB		$db      Database handler
82
	 */
83
	function __construct($db)
84
	{
85
		$this->db = $db;
86
	}
87
88
89
	/**
90
	 *  Create into database
91
	 *
92
	 *  @param	User	$user        	User that create
93
	 *  @param 	int		$notrigger	    0=launch triggers after, 1=disable triggers
94
	 *  @return int 		        	<0 if KO, Id of created object if OK
95
	 */
96
	function create($user, $notrigger=0)
97
	{
98
		global $conf, $langs;
99
100
		$error=0;
101
102
		// Clean parameters
103
		$this->label = trim($this->label);
104
		$this->description = trim($this->description);
105
106
		// Check parameters
107
		// Put here code to add control on parameters values
108
109
		// Insert request
110
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."projet_task (";
111
		$sql.= "fk_projet";
112
		$sql.= ", ref";
113
		$sql.= ", fk_task_parent";
114
		$sql.= ", label";
115
		$sql.= ", description";
116
		$sql.= ", datec";
117
		$sql.= ", fk_user_creat";
118
		$sql.= ", dateo";
119
		$sql.= ", datee";
120
		$sql.= ", planned_workload";
121
		$sql.= ", progress";
122
		$sql.= ") VALUES (";
123
		$sql.= $this->fk_project;
124
		$sql.= ", ".(!empty($this->ref)?"'".$this->db->escape($this->ref)."'":'null');
125
		$sql.= ", ".$this->fk_task_parent;
126
		$sql.= ", '".$this->db->escape($this->label)."'";
127
		$sql.= ", '".$this->db->escape($this->description)."'";
128
		$sql.= ", '".$this->db->idate($this->date_c)."'";
129
		$sql.= ", ".$user->id;
130
		$sql.= ", ".($this->date_start!=''?"'".$this->db->idate($this->date_start)."'":'null');
131
		$sql.= ", ".($this->date_end!=''?"'".$this->db->idate($this->date_end)."'":'null');
132
		$sql.= ", ".(($this->planned_workload!='' && $this->planned_workload >= 0)?$this->planned_workload:'null');
133
		$sql.= ", ".(($this->progress!='' && $this->progress >= 0)?$this->progress:'null');
134
		$sql.= ")";
135
136
		$this->db->begin();
137
138
		dol_syslog(get_class($this)."::create", LOG_DEBUG);
139
		$resql=$this->db->query($sql);
140
		if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
141
142
		if (! $error)
143
		{
144
			$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."projet_task");
145
146
			if (! $notrigger)
147
			{
148
				// Call trigger
149
				$result=$this->call_trigger('TASK_CREATE',$user);
150
				if ($result < 0) { $error++; }
151
				// End call triggers
152
			}
153
		}
154
155
		// Update extrafield
156
		if (! $error)
157
		{
158
			if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
159
			{
160
				$result=$this->insertExtraFields();
161
				if ($result < 0)
162
				{
163
					$error++;
164
				}
165
			}
166
		}
167
168
		// Commit or rollback
169
		if ($error)
170
		{
171
			foreach($this->errors as $errmsg)
172
			{
173
				dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
174
				$this->error.=($this->error?', '.$errmsg:$errmsg);
175
			}
176
			$this->db->rollback();
177
			return -1*$error;
178
		}
179
		else
180
		{
181
			$this->db->commit();
182
			return $this->id;
183
		}
184
	}
185
186
187
	/**
188
	 *  Load object in memory from database
189
	 *
190
	 *  @param	int		$id			Id object
191
	 *  @param	int		$ref		ref object
192
	 *  @return int 		        <0 if KO, 0 if not found, >0 if OK
193
	 */
194
	function fetch($id,$ref='')
195
	{
196
		global $langs;
197
198
		$sql = "SELECT";
199
		$sql.= " t.rowid,";
200
		$sql.= " t.ref,";
201
		$sql.= " t.fk_projet,";
202
		$sql.= " t.fk_task_parent,";
203
		$sql.= " t.label,";
204
		$sql.= " t.description,";
205
		$sql.= " t.duration_effective,";
206
		$sql.= " t.planned_workload,";
207
		$sql.= " t.datec,";
208
		$sql.= " t.dateo,";
209
		$sql.= " t.datee,";
210
		$sql.= " t.fk_user_creat,";
211
		$sql.= " t.fk_user_valid,";
212
		$sql.= " t.fk_statut,";
213
		$sql.= " t.progress,";
214
		$sql.= " t.priority,";
215
		$sql.= " t.note_private,";
216
		$sql.= " t.note_public,";
217
		$sql.= " t.rang";
218
		$sql.= " FROM ".MAIN_DB_PREFIX."projet_task as t";
219
		$sql.= " WHERE ";
220
		if (!empty($ref)) {
221
			$sql.="t.ref = '".$this->db->escape($ref)."'";
222
		}else {
223
			$sql.="t.rowid = ".$id;
224
		}
225
226
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
227
		$resql=$this->db->query($sql);
228
		if ($resql)
229
		{
230
			$num_rows = $this->db->num_rows($resql);
231
232
			if ($num_rows)
233
			{
234
				$obj = $this->db->fetch_object($resql);
235
236
				$this->id					= $obj->rowid;
237
				$this->ref					= $obj->ref;
238
				$this->fk_project			= $obj->fk_projet;
239
				$this->fk_task_parent		= $obj->fk_task_parent;
240
				$this->label				= $obj->label;
241
				$this->description			= $obj->description;
242
				$this->duration_effective	= $obj->duration_effective;
243
				$this->planned_workload		= $obj->planned_workload;
244
				$this->date_c				= $this->db->jdate($obj->datec);
245
				$this->date_start			= $this->db->jdate($obj->dateo);
246
				$this->date_end				= $this->db->jdate($obj->datee);
247
				$this->fk_user_creat		= $obj->fk_user_creat;
248
				$this->fk_user_valid		= $obj->fk_user_valid;
249
				$this->fk_statut			= $obj->fk_statut;
250
				$this->progress				= $obj->progress;
251
				$this->priority				= $obj->priority;
252
				$this->note_private			= $obj->note_private;
253
				$this->note_public			= $obj->note_public;
254
				$this->rang					= $obj->rang;
255
256
				// Retreive all extrafield for thirdparty
257
			   	$this->fetch_optionals();
258
			}
259
260
			$this->db->free($resql);
261
262
			if ($num_rows) {
263
				$this->fetchComments();
264
				return 1;
265
			}else {
266
				return 0;
267
			}
268
		}
269
		else
270
		{
271
			$this->error="Error ".$this->db->lasterror();
272
			return -1;
273
		}
274
	}
275
276
277
	/**
278
	 *  Update database
279
	 *
280
	 *  @param	User	$user        	User that modify
281
	 *  @param  int		$notrigger	    0=launch triggers after, 1=disable triggers
282
	 *  @return int			         	<=0 if KO, >0 if OK
283
	 */
284
	function update($user=null, $notrigger=0)
285
	{
286
		global $conf, $langs;
287
		$error=0;
288
289
		// Clean parameters
290
		if (isset($this->fk_project)) $this->fk_project=trim($this->fk_project);
0 ignored issues
show
Documentation Bug introduced by
The property $fk_project was declared of type integer, but trim($this->fk_project) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
291
		if (isset($this->ref)) $this->ref=trim($this->ref);
292
		if (isset($this->fk_task_parent)) $this->fk_task_parent=trim($this->fk_task_parent);
293
		if (isset($this->label)) $this->label=trim($this->label);
294
		if (isset($this->description)) $this->description=trim($this->description);
295
		if (isset($this->duration_effective)) $this->duration_effective=trim($this->duration_effective);
296
		if (isset($this->planned_workload)) $this->planned_workload=trim($this->planned_workload);
297
298
		// Check parameters
299
		// Put here code to add control on parameters values
300
301
		// Update request
302
		$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task SET";
303
		$sql.= " fk_projet=".(isset($this->fk_project)?$this->fk_project:"null").",";
304
		$sql.= " ref=".(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"'".$this->db->escape($this->id)."'").",";
305
		$sql.= " fk_task_parent=".(isset($this->fk_task_parent)?$this->fk_task_parent:"null").",";
306
		$sql.= " label=".(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").",";
307
		$sql.= " description=".(isset($this->description)?"'".$this->db->escape($this->description)."'":"null").",";
308
		$sql.= " duration_effective=".(isset($this->duration_effective)?$this->duration_effective:"null").",";
309
		$sql.= " planned_workload=".((isset($this->planned_workload) && $this->planned_workload != '')?$this->planned_workload:"null").",";
310
		$sql.= " dateo=".($this->date_start!=''?"'".$this->db->idate($this->date_start)."'":'null').",";
311
		$sql.= " datee=".($this->date_end!=''?"'".$this->db->idate($this->date_end)."'":'null').",";
312
		$sql.= " progress=".(($this->progress!='' && $this->progress >= 0)?$this->progress:'null').",";
313
		$sql.= " rang=".((!empty($this->rang))?$this->rang:"0");
314
		$sql.= " WHERE rowid=".$this->id;
315
316
		$this->db->begin();
317
318
		dol_syslog(get_class($this)."::update", LOG_DEBUG);
319
		$resql = $this->db->query($sql);
320
		if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
321
322
		if (! $error)
323
		{
324
			if (! $notrigger)
325
			{
326
				// Call trigger
327
				$result=$this->call_trigger('TASK_MODIFY',$user);
0 ignored issues
show
Bug introduced by
It seems like $user defined by parameter $user on line 284 can be null; however, CommonObject::call_trigger() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
328
				if ($result < 0) { $error++; }
329
				// End call triggers
330
			}
331
		}
332
333
		//Update extrafield
334
		if (!$error) {
335
			if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
336
			{
337
				$result=$this->insertExtraFields();
338
				if ($result < 0)
339
				{
340
					$error++;
341
				}
342
			}
343
		}
344
345
		if (! $error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref))
346
		{
347
			// We remove directory
348
			if ($conf->projet->dir_output)
349
			{
350
				$project = new Project($this->db);
351
				$project->fetch($this->fk_project);
352
353
				$olddir = $conf->projet->dir_output.'/'.dol_sanitizeFileName($project->ref).'/'.dol_sanitizeFileName($this->oldcopy->ref);
354
				$newdir = $conf->projet->dir_output.'/'.dol_sanitizeFileName($project->ref).'/'.dol_sanitizeFileName($this->ref);
355
				if (file_exists($olddir))
356
				{
357
					include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
358
					$res=dol_move($olddir, $newdir);
359
					if (! $res)
360
					{
361
						$langs->load("errors");
362
						$this->error=$langs->trans('ErrorFailToRenameDir',$olddir,$newdir);
363
						$error++;
364
					}
365
				}
366
			}
367
		}
368
369
		// Commit or rollback
370
		if ($error)
371
		{
372
			foreach($this->errors as $errmsg)
373
			{
374
				dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
375
				$this->error.=($this->error?', '.$errmsg:$errmsg);
376
			}
377
			$this->db->rollback();
378
			return -1*$error;
379
		}
380
		else
381
		{
382
			$this->db->commit();
383
			return 1;
384
		}
385
	}
386
387
388
	/**
389
	 *	Delete task from database
390
	 *
391
	 *	@param	User	$user        	User that delete
392
	 *  @param  int		$notrigger	    0=launch triggers after, 1=disable triggers
393
	 *	@return	int						<0 if KO, >0 if OK
394
	 */
395
	function delete($user, $notrigger=0)
396
	{
397
398
		global $conf, $langs;
399
		require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
400
401
		$error=0;
402
403
		$this->db->begin();
404
405
		if ($this->hasChildren() > 0)
406
		{
407
			dol_syslog(get_class($this)."::delete Can't delete record as it has some sub tasks", LOG_WARNING);
408
			$this->error='ErrorRecordHasSubTasks';
409
			$this->db->rollback();
410
			return 0;
411
		}
412
413
		$objectisused = $this->isObjectUsed($this->id);
414
		if (! empty($objectisused))
415
		{
416
			dol_syslog(get_class($this)."::delete Can't delete record as it has some child", LOG_WARNING);
417
			$this->error='ErrorRecordHasChildren';
418
			$this->db->rollback();
419
			return 0;
420
		}
421
422
		if (! $error)
423
		{
424
			// Delete linked contacts
425
			$res = $this->delete_linked_contact();
426
			if ($res < 0)
427
			{
428
				$this->error='ErrorFailToDeleteLinkedContact';
429
				//$error++;
430
				$this->db->rollback();
431
				return 0;
432
			}
433
		}
434
435
		if (! $error)
436
		{
437
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task_time";
438
			$sql.= " WHERE fk_task=".$this->id;
439
440
			$resql = $this->db->query($sql);
441
			if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
442
		}
443
444
		if (! $error)
445
		{
446
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task_extrafields";
447
			$sql.= " WHERE fk_object=".$this->id;
448
449
			$resql = $this->db->query($sql);
450
			if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
451
		}
452
453
		if (! $error)
454
		{
455
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task";
456
			$sql.= " WHERE rowid=".$this->id;
457
458
			$resql = $this->db->query($sql);
459
			if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
460
		}
461
462
		if (! $error)
463
		{
464
			if (! $notrigger)
465
			{
466
				// Call trigger
467
				$result=$this->call_trigger('TASK_DELETE',$user);
468
				if ($result < 0) { $error++; }
469
				// End call triggers
470
			}
471
		}
472
473
		// Commit or rollback
474
		if ($error)
475
		{
476
			foreach($this->errors as $errmsg)
477
			{
478
				dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
479
				$this->error.=($this->error?', '.$errmsg:$errmsg);
480
			}
481
			$this->db->rollback();
482
			return -1*$error;
483
		}
484
		else
485
		{
486
			//Delete associated link file
487
			if ($conf->projet->dir_output)
488
			{
489
				$projectstatic=new Project($this->db);
490
				$projectstatic->fetch($this->fk_project);
491
492
				$dir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($projectstatic->ref) . '/' . dol_sanitizeFileName($this->id);
493
				dol_syslog(get_class($this)."::delete dir=".$dir, LOG_DEBUG);
494
				if (file_exists($dir))
495
				{
496
					require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
497
					$res = @dol_delete_dir_recursive($dir);
498
					if (!$res)
499
					{
500
						$this->error = 'ErrorFailToDeleteDir';
501
						$this->db->rollback();
502
						return 0;
503
					}
504
				}
505
			}
506
507
			$this->db->commit();
508
509
			return 1;
510
		}
511
	}
512
513
	/**
514
	 *	Return nb of children
515
	 *
516
	 *	@return	int		<0 if KO, 0 if no children, >0 if OK
517
	 */
518
	function hasChildren()
519
	{
520
		$error=0;
521
		$ret=0;
522
523
		$sql = "SELECT COUNT(*) as nb";
524
		$sql.= " FROM ".MAIN_DB_PREFIX."projet_task";
525
		$sql.= " WHERE fk_task_parent=".$this->id;
526
527
		dol_syslog(get_class($this)."::hasChildren", LOG_DEBUG);
528
		$resql = $this->db->query($sql);
529
		if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
530
		else
531
		{
532
			$obj=$this->db->fetch_object($resql);
533
			if ($obj) $ret=$obj->nb;
534
			$this->db->free($resql);
535
		}
536
537
		if (! $error)
538
		{
539
			return $ret;
540
		}
541
		else
542
		{
543
			return -1;
544
		}
545
	}
546
547
	/**
548
	 *	Return nb of time spent
549
	 *
550
	 *	@return	int		<0 if KO, 0 if no children, >0 if OK
551
	 */
552
	function hasTimeSpent()
553
	{
554
		$error=0;
555
		$ret=0;
556
557
		$sql = "SELECT COUNT(*) as nb";
558
		$sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time";
559
		$sql.= " WHERE fk_task=".$this->id;
560
561
		dol_syslog(get_class($this)."::hasTimeSpent", LOG_DEBUG);
562
		$resql = $this->db->query($sql);
563
		if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
564
		else
565
		{
566
			$obj=$this->db->fetch_object($resql);
567
			if ($obj) $ret=$obj->nb;
568
			$this->db->free($resql);
569
		}
570
571
		if (! $error)
572
		{
573
			return $ret;
574
		}
575
		else
576
		{
577
			return -1;
578
		}
579
	}
580
581
582
	/**
583
	 *	Return clicable name (with picto eventually)
584
	 *
585
	 *	@param	int		$withpicto		0=No picto, 1=Include picto into link, 2=Only picto
586
	 *	@param	string	$option			'withproject' or ''
587
	 *  @param	string	$mode			Mode 'task', 'time', 'contact', 'note', document' define page to link to.
588
	 * 	@param	int		$addlabel		0=Default, 1=Add label into string, >1=Add first chars into string
589
	 *  @param	string	$sep			Separator between ref and label if option addlabel is set
590
	 *  @param	int   	$notooltip		1=Disable tooltip
591
	 *  @param  int     $save_lastsearch_value    -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
592
	 *	@return	string					Chaine avec URL
593
	 */
594
	function getNomUrl($withpicto=0,$option='',$mode='task', $addlabel=0, $sep=' - ', $notooltip=0, $save_lastsearch_value=-1)
595
	{
596
		global $conf, $langs, $user;
597
598
		if (! empty($conf->dol_no_mouse_hover)) $notooltip=1;   // Force disable tooltips
599
600
		$result='';
601
		$label = '<u>' . $langs->trans("ShowTask") . '</u>';
602
		if (! empty($this->ref))
603
			$label .= '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
604
		if (! empty($this->label))
605
			$label .= '<br><b>' . $langs->trans('LabelTask') . ':</b> ' . $this->label;
606
		if ($this->date_start || $this->date_end)
607
		{
608
			$label .= "<br>".get_date_range($this->date_start,$this->date_end,'',$langs,0);
609
		}
610
611
		$url = DOL_URL_ROOT.'/projet/tasks/'.$mode.'.php?id='.$this->id.($option=='withproject'?'&withproject=1':'');
612
		// Add param to save lastsearch_values or not
613
		$add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
614
		if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
615
		if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
616
617
		$linkclose = '';
618
		if (empty($notooltip))
619
		{
620
			if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
621
			{
622
				$label=$langs->trans("ShowTask");
623
				$linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
624
			}
625
			$linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
626
			$linkclose.=' class="classfortooltip"';
627
		}
628
629
		$linkstart = '<a href="'.$url.'"';
630
		$linkstart.=$linkclose.'>';
631
		$linkend='</a>';
632
633
		$picto='projecttask';
634
635
		$result .= $linkstart;
636
		if ($withpicto) $result.=img_object(($notooltip?'':$label), $picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
637
		if ($withpicto != 2) $result.= $this->ref;
638
		$result .= $linkend;
639
		if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
640
641
		return $result;
642
	}
643
644
	/**
645
	 *  Initialise an instance with random values.
646
	 *  Used to build previews or test instances.
647
	 *	id must be 0 if object instance is a specimen.
648
	 *
649
	 *  @return	void
650
	 */
651
	function initAsSpecimen()
652
	{
653
		$this->id=0;
654
655
		$this->fk_projet='';
656
		$this->ref='TK01';
657
		$this->fk_task_parent='';
658
		$this->label='Specimen task TK01';
659
		$this->duration_effective='';
660
		$this->fk_user_creat='';
661
		$this->progress='25';
662
		$this->fk_statut='';
663
		$this->note='This is a specimen task not';
664
	}
665
666
	/**
667
	 * Return list of tasks for all projects or for one particular project
668
	 * Sort order is on project, then on position of task, and last on start date of first level task
669
	 *
670
	 * @param	User	$usert				Object user to limit tasks affected to a particular user
671
	 * @param	User	$userp				Object user to limit projects of a particular user and public projects
672
	 * @param	int		$projectid			Project id
673
	 * @param	int		$socid				Third party id
674
	 * @param	int		$mode				0=Return list of tasks and their projects, 1=Return projects and tasks if exists
675
	 * @param	string	$filteronproj    	Filter on project ref or label
676
	 * @param	string	$filteronprojstatus	Filter on project status
677
	 * @param	string	$morewherefilter	Add more filter into where SQL request (must start with ' AND ...')
678
	 * @param	string	$filteronprojuser	Filter on user that is a contact of project
679
	 * @param	string	$filterontaskuser	Filter on user assigned to task
680
	 * @return 	array						Array of tasks
681
	 */
682
	function getTasksArray($usert=null, $userp=null, $projectid=0, $socid=0, $mode=0, $filteronproj='', $filteronprojstatus=-1, $morewherefilter='',$filteronprojuser=0,$filterontaskuser=0)
683
	{
684
		global $conf;
685
686
		$tasks = array();
687
688
		//print $usert.'-'.$userp.'-'.$projectid.'-'.$socid.'-'.$mode.'<br>';
689
690
		// List of tasks (does not care about permissions. Filtering will be done later)
691
		$sql = "SELECT ";
692
		if ($filteronprojuser > 0 || $filterontaskuser > 0) $sql.= " DISTINCT";		// We may get several time the same record if user has several roles on same project/task
693
		$sql.= " p.rowid as projectid, p.ref, p.title as plabel, p.public, p.fk_statut as projectstatus,";
694
		$sql.= " t.rowid as taskid, t.ref as taskref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut as status,";
695
		$sql.= " t.dateo as date_start, t.datee as date_end, t.planned_workload, t.rang,";
696
		$sql.= " s.rowid as thirdparty_id, s.nom as thirdparty_name, s.email as thirdparty_email";
697
		$sql.= " FROM ".MAIN_DB_PREFIX."projet as p";
698
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
699
		if ($mode == 0)
700
		{
701
			if ($filteronprojuser > 0)
702
			{
703
				$sql.= ", ".MAIN_DB_PREFIX."element_contact as ec";
704
				$sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc";
705
			}
706
			$sql.= ", ".MAIN_DB_PREFIX."projet_task as t";
707
			if ($filterontaskuser > 0)
708
			{
709
				$sql.= ", ".MAIN_DB_PREFIX."element_contact as ec2";
710
				$sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc2";
711
			}
712
			$sql.= " WHERE p.entity IN (".getEntity('project').")";
713
			$sql.= " AND t.fk_projet = p.rowid";
714
		}
715
		elseif ($mode == 1)
716
		{
717
			if ($filteronprojuser > 0)
718
			{
719
				$sql.= ", ".MAIN_DB_PREFIX."element_contact as ec";
720
				$sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc";
721
			}
722
			if ($filterontaskuser > 0)
723
			{
724
				$sql.= ", ".MAIN_DB_PREFIX."projet_task as t";
725
				$sql.= ", ".MAIN_DB_PREFIX."element_contact as ec2";
726
				$sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc2";
727
			}
728
			else
729
			{
730
				$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t on t.fk_projet = p.rowid";
731
			}
732
			$sql.= " WHERE p.entity IN (".getEntity('project').")";
733
		}
734
		else return 'BadValueForParameterMode';
735
736
		if ($filteronprojuser > 0)
737
		{
738
			$sql.= " AND p.rowid = ec.element_id";
739
			$sql.= " AND ctc.rowid = ec.fk_c_type_contact";
740
			$sql.= " AND ctc.element = 'project'";
741
			$sql.= " AND ec.fk_socpeople = ".$filteronprojuser;
742
			$sql.= " AND ec.statut = 4";
743
			$sql.= " AND ctc.source = 'internal'";
744
		}
745
		if ($filterontaskuser > 0)
746
		{
747
			$sql.= " AND t.fk_projet = p.rowid";
748
			$sql.= " AND p.rowid = ec2.element_id";
749
			$sql.= " AND ctc2.rowid = ec2.fk_c_type_contact";
750
			$sql.= " AND ctc2.element = 'project_task'";
751
			$sql.= " AND ec2.fk_socpeople = ".$filterontaskuser;
752
			$sql.= " AND ec2.statut = 4";
753
			$sql.= " AND ctc2.source = 'internal'";
754
		}
755
		if ($socid)	$sql.= " AND p.fk_soc = ".$socid;
756
		if ($projectid) $sql.= " AND p.rowid in (".$projectid.")";
757
		if ($filteronproj) $sql.= " AND (p.ref LIKE '%".$this->db->escape($filteronproj)."%' OR p.title LIKE '%".$this->db->escape($filteronproj)."%')";
758
		if ($filteronprojstatus > -1) $sql.= " AND p.fk_statut = ".$filteronprojstatus;
759
		if ($morewherefilter) $sql.=$morewherefilter;
760
		$sql.= " ORDER BY p.ref, t.rang, t.dateo";
761
762
		//print $sql;exit;
763
		dol_syslog(get_class($this)."::getTasksArray", LOG_DEBUG);
764
		$resql = $this->db->query($sql);
765
		if ($resql)
766
		{
767
			$num = $this->db->num_rows($resql);
768
			$i = 0;
769
			// Loop on each record found, so each couple (project id, task id)
770
			while ($i < $num)
771
			{
772
				$error=0;
773
774
				$obj = $this->db->fetch_object($resql);
775
776
				if ((! $obj->public) && (is_object($userp)))	// If not public project and we ask a filter on project owned by a user
777
				{
778
					if (! $this->getUserRolesForProjectsOrTasks($userp, 0, $obj->projectid, 0))
779
					{
780
						$error++;
781
					}
782
				}
783
				if (is_object($usert))							// If we ask a filter on a user affected to a task
784
				{
785
					if (! $this->getUserRolesForProjectsOrTasks(0, $usert, $obj->projectid, $obj->taskid))
786
					{
787
						$error++;
788
					}
789
				}
790
791
				if (! $error)
792
				{
793
					$tasks[$i] = new Task($this->db);
794
					$tasks[$i]->id				= $obj->taskid;
795
					$tasks[$i]->ref				= $obj->taskref;
796
					$tasks[$i]->fk_project		= $obj->projectid;
797
					$tasks[$i]->projectref		= $obj->ref;
798
					$tasks[$i]->projectlabel	= $obj->plabel;
799
					$tasks[$i]->projectstatus	= $obj->projectstatus;
800
					$tasks[$i]->label			= $obj->label;
801
					$tasks[$i]->description		= $obj->description;
802
					$tasks[$i]->fk_parent		= $obj->fk_task_parent;      // deprecated
803
					$tasks[$i]->fk_task_parent	= $obj->fk_task_parent;
804
					$tasks[$i]->duration		= $obj->duration_effective;
805
					$tasks[$i]->planned_workload= $obj->planned_workload;
806
					$tasks[$i]->progress		= $obj->progress;
807
					$tasks[$i]->fk_statut		= $obj->status;
808
					$tasks[$i]->public			= $obj->public;
809
					$tasks[$i]->date_start		= $this->db->jdate($obj->date_start);
810
					$tasks[$i]->date_end		= $this->db->jdate($obj->date_end);
811
					$tasks[$i]->rang	   		= $obj->rang;
812
813
					$tasks[$i]->socid           = $obj->thirdparty_id;	// For backward compatibility
814
					$tasks[$i]->thirdparty_id	= $obj->thirdparty_id;
815
					$tasks[$i]->thirdparty_name	= $obj->thirdparty_name;
816
					$tasks[$i]->thirdparty_email= $obj->thirdparty_email;
817
				}
818
819
				$i++;
820
			}
821
			$this->db->free($resql);
822
		}
823
		else
824
		{
825
			dol_print_error($this->db);
826
		}
827
828
		return $tasks;
829
	}
830
831
	/**
832
	 * Return list of roles for a user for each projects or each tasks (or a particular project or a particular task).
833
	 *
834
	 * @param	User	$userp			      Return roles on project for this internal user. If set, usert and taskid must not be defined.
835
	 * @param	User	$usert			      Return roles on task for this internal user. If set userp must NOT be defined. -1 means no filter.
836
	 * @param 	int		$projectid		      Project id list separated with , to filter on project
837
	 * @param 	int		$taskid			      Task id to filter on a task
838
	 * @param	integer	$filteronprojstatus	  Filter on project status if userp is set. Not used if userp not defined.
839
	 * @return 	array					      Array (projectid => 'list of roles for project' or taskid => 'list of roles for task')
840
	 */
841
	function getUserRolesForProjectsOrTasks($userp, $usert, $projectid='', $taskid=0, $filteronprojstatus=-1)
842
	{
843
		$arrayroles = array();
844
845
		dol_syslog(get_class($this)."::getUserRolesForProjectsOrTasks userp=".is_object($userp)." usert=".is_object($usert)." projectid=".$projectid." taskid=".$taskid);
846
847
		// We want role of user for a projet or role of user for a task. Both are not possible.
848
		if (empty($userp) && empty($usert))
849
		{
850
			$this->error="CallWithWrongParameters";
851
			return -1;
852
		}
853
		if (! empty($userp) && ! empty($usert))
854
		{
855
			$this->error="CallWithWrongParameters";
856
			return -1;
857
		}
858
859
		/* Liste des taches et role sur les projets ou taches */
860
		$sql = "SELECT pt.rowid as pid, ec.element_id, ctc.code, ctc.source";
861
		if ($userp) $sql.= " FROM ".MAIN_DB_PREFIX."projet as pt";
862
		if ($usert && $filteronprojstatus > -1) $sql.= " FROM ".MAIN_DB_PREFIX."projet as p, ".MAIN_DB_PREFIX."projet_task as pt";
863
		if ($usert && $filteronprojstatus <= -1) $sql.= " FROM ".MAIN_DB_PREFIX."projet_task as pt";
864
		$sql.= ", ".MAIN_DB_PREFIX."element_contact as ec";
865
		$sql.= ", ".MAIN_DB_PREFIX."c_type_contact as ctc";
866
		$sql.= " WHERE pt.rowid = ec.element_id";
867
		if ($userp && $filteronprojstatus > -1) $sql.= " AND pt.fk_statut = ".$filteronprojstatus;
868
		if ($usert && $filteronprojstatus > -1) $sql.= " AND pt.fk_projet = p.rowid AND p.fk_statut = ".$filteronprojstatus;
869
		if ($userp) $sql.= " AND ctc.element = 'project'";
870
		if ($usert) $sql.= " AND ctc.element = 'project_task'";
871
		$sql.= " AND ctc.rowid = ec.fk_c_type_contact";
872
		if ($userp) $sql.= " AND ec.fk_socpeople = ".$userp->id;
873
		if ($usert) $sql.= " AND ec.fk_socpeople = ".$usert->id;
874
		$sql.= " AND ec.statut = 4";
875
		$sql.= " AND ctc.source = 'internal'";
876
		if ($projectid)
877
		{
878
			if ($userp) $sql.= " AND pt.rowid in (".$projectid.")";
879
			if ($usert) $sql.= " AND pt.fk_projet in (".$projectid.")";
880
		}
881
		if ($taskid)
882
		{
883
			if ($userp) $sql.= " ERROR SHOULD NOT HAPPENS";
884
			if ($usert) $sql.= " AND pt.rowid = ".$taskid;
885
		}
886
		//print $sql;
887
888
		dol_syslog(get_class($this)."::getUserRolesForProjectsOrTasks execute request", LOG_DEBUG);
889
		$resql = $this->db->query($sql);
890
		if ($resql)
891
		{
892
			$num = $this->db->num_rows($resql);
893
			$i = 0;
894
			while ($i < $num)
895
			{
896
				$obj = $this->db->fetch_object($resql);
897
				if (empty($arrayroles[$obj->pid])) $arrayroles[$obj->pid] = $obj->code;
898
				else $arrayroles[$obj->pid].=','.$obj->code;
899
				$i++;
900
			}
901
			$this->db->free($resql);
902
		}
903
		else
904
		{
905
			dol_print_error($this->db);
906
		}
907
908
		return $arrayroles;
909
	}
910
911
912
	/**
913
	 * 	Return list of id of contacts of task
914
	 *
915
	 *	@param	string	$source		Source
916
	 *  @return array				Array of id of contacts
917
	 */
918
	function getListContactId($source='internal')
919
	{
920
		$contactAlreadySelected = array();
921
		$tab = $this->liste_contact(-1,$source);
922
		//var_dump($tab);
923
		$num=count($tab);
924
		$i = 0;
925
		while ($i < $num)
926
		{
927
			if ($source == 'thirdparty') $contactAlreadySelected[$i] = $tab[$i]['socid'];
928
			else  $contactAlreadySelected[$i] = $tab[$i]['id'];
929
			$i++;
930
		}
931
		return $contactAlreadySelected;
932
	}
933
934
935
	/**
936
	 *  Add time spent
937
	 *
938
	 *  @param	User	$user           User object
939
	 *  @param  int		$notrigger	    0=launch triggers after, 1=disable triggers
940
	 *  @return	int                     <=0 if KO, >0 if OK
941
	 */
942
	function addTimeSpent($user, $notrigger=0)
943
	{
944
		global $conf,$langs;
945
946
		dol_syslog(get_class($this)."::addTimeSpent", LOG_DEBUG);
947
948
		$ret = 0;
949
950
		// Check parameters
951
		if (! is_object($user))
952
		{
953
			dol_print_error('',"Method addTimeSpent was called with wrong parameter user");
954
			return -1;
955
		}
956
957
		// Clean parameters
958
		if (isset($this->timespent_note)) $this->timespent_note = trim($this->timespent_note);
959
		if (empty($this->timespent_datehour)) $this->timespent_datehour = $this->timespent_date;
960
961
		$this->db->begin();
962
963
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."projet_task_time (";
964
		$sql.= "fk_task";
965
		$sql.= ", task_date";
966
		$sql.= ", task_datehour";
967
		$sql.= ", task_date_withhour";
968
		$sql.= ", task_duration";
969
		$sql.= ", fk_user";
970
		$sql.= ", note";
971
		$sql.= ") VALUES (";
972
		$sql.= $this->id;
973
		$sql.= ", '".$this->db->idate($this->timespent_date)."'";
974
		$sql.= ", '".$this->db->idate($this->timespent_datehour)."'";
975
		$sql.= ", ".(empty($this->timespent_withhour)?0:1);
976
		$sql.= ", ".$this->timespent_duration;
977
		$sql.= ", ".$this->timespent_fk_user;
978
		$sql.= ", ".(isset($this->timespent_note)?"'".$this->db->escape($this->timespent_note)."'":"null");
979
		$sql.= ")";
980
981
		$resql=$this->db->query($sql);
982
		if ($resql)
983
		{
984
			$tasktime_id = $this->db->last_insert_id(MAIN_DB_PREFIX."projet_task_time");
985
			$ret = $tasktime_id;
986
			$this->timespent_id = $ret;
987
988
			if (! $notrigger)
989
			{
990
				// Call trigger
991
				$result=$this->call_trigger('TASK_TIMESPENT_CREATE',$user);
992
				if ($result < 0) { $ret=-1; }
993
				// End call triggers
994
			}
995
		}
996
		else
997
		{
998
			$this->error=$this->db->lasterror();
999
			$ret = -1;
1000
		}
1001
1002
		if ($ret > 0)
1003
		{
1004
			// Recalculate amount of time spent for task and update denormalized field
1005
			$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
1006
			$sql.= " SET duration_effective = (SELECT SUM(task_duration) FROM ".MAIN_DB_PREFIX."projet_task_time as ptt where ptt.fk_task = ".$this->id.")";
1007
			if (isset($this->progress)) $sql.= ", progress = " . $this->progress;	// Do not overwrite value if not provided
1008
			$sql.= " WHERE rowid = ".$this->id;
1009
1010
			dol_syslog(get_class($this)."::addTimeSpent", LOG_DEBUG);
1011
			if (! $this->db->query($sql) )
1012
			{
1013
				$this->error=$this->db->lasterror();
1014
				$ret = -2;
1015
			}
1016
1017
			$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_time";
1018
			$sql.= " SET thm = (SELECT thm FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".$this->timespent_fk_user.")";	// set average hour rate of user
1019
			$sql.= " WHERE rowid = ".$tasktime_id;
0 ignored issues
show
Bug introduced by
The variable $tasktime_id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1020
1021
			dol_syslog(get_class($this)."::addTimeSpent", LOG_DEBUG);
1022
			if (! $this->db->query($sql) )
1023
			{
1024
				$this->error=$this->db->lasterror();
1025
				$ret = -2;
1026
			}
1027
		}
1028
1029
		if ($ret >0)
1030
		{
1031
			$this->db->commit();
1032
		}
1033
		else
1034
		{
1035
			$this->db->rollback();
1036
		}
1037
		return $ret;
1038
	}
1039
1040
	/**
1041
	 *  Calculate total of time spent for task
1042
	 *
1043
	 *  @param  User|int	$userobj			Filter on user. null or 0=No filter
1044
	 *  @param	string		$morewherefilter	Add more filter into where SQL request (must start with ' AND ...')
1045
	 *  @return array		 					Array of info for task array('min_date', 'max_date', 'total_duration', 'total_amount', 'nblines', 'nblinesnull')
1046
	 */
1047
	function getSummaryOfTimeSpent($userobj=null, $morewherefilter='')
1048
	{
1049
		global $langs;
1050
1051
		if (is_object($userobj)) $userid=$userobj->id;
1052
		else $userid=$userobj;	// old method
1053
1054
		$id=$this->id;
1055
		if (empty($id) && empty($userid))
1056
		{
1057
			dol_syslog("getSummaryOfTimeSpent called on a not loaded task without user param defined", LOG_ERR);
1058
			return -1;
1059
		}
1060
1061
		$result=array();
1062
1063
		$sql = "SELECT";
1064
		$sql.= " MIN(t.task_datehour) as min_date,";
1065
		$sql.= " MAX(t.task_datehour) as max_date,";
1066
		$sql.= " SUM(t.task_duration) as total_duration,";
1067
		$sql.= " SUM(t.task_duration / 3600 * ".$this->db->ifsql("t.thm IS NULL", 0, "t.thm").") as total_amount,";
1068
		$sql.= " COUNT(t.rowid) as nblines,";
1069
		$sql.= " SUM(".$this->db->ifsql("t.thm IS NULL", 1, 0).") as nblinesnull";
1070
		$sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time as t";
1071
		$sql.= " WHERE 1 = 1";
1072
		if ($morewherefilter) $sql.=$morewherefilter;
1073
		if ($id > 0) $sql.= " AND t.fk_task = ".$id;
1074
		if ($userid > 0) $sql.=" AND t.fk_user = ".$userid;
1075
1076
		dol_syslog(get_class($this)."::getSummaryOfTimeSpent", LOG_DEBUG);
1077
		$resql=$this->db->query($sql);
1078
		if ($resql)
1079
		{
1080
			$obj = $this->db->fetch_object($resql);
1081
1082
			$result['min_date'] = $obj->min_date;               // deprecated. use the ->timespent_xxx instead
1083
			$result['max_date'] = $obj->max_date;               // deprecated. use the ->timespent_xxx instead
1084
			$result['total_duration'] = $obj->total_duration;   // deprecated. use the ->timespent_xxx instead
1085
1086
			$this->timespent_min_date=$this->db->jdate($obj->min_date);
1087
			$this->timespent_max_date=$this->db->jdate($obj->max_date);
1088
			$this->timespent_total_duration=$obj->total_duration;
1089
			$this->timespent_total_amount=$obj->total_amount;
1090
			$this->timespent_nblinesnull=($obj->nblinesnull?$obj->nblinesnull:0);
1091
			$this->timespent_nblines=($obj->nblines?$obj->nblines:0);
1092
1093
			$this->db->free($resql);
1094
		}
1095
		else
1096
		{
1097
			dol_print_error($this->db);
1098
		}
1099
		return $result;
1100
	}
1101
1102
	/**
1103
	 *  Calculate quantity and value of time consumed using the thm (hourly amount value of work for user entering time)
1104
	 *
1105
	 *	@param		User		$fuser		Filter on a dedicated user
1106
	 *  @param		string		$dates		Start date (ex 00:00:00)
1107
	 *  @param		string		$datee		End date (ex 23:59:59)
1108
	 *  @return 	array	        		Array of info for task array('amount','nbseconds','nblinesnull')
1109
	 */
1110
	function getSumOfAmount($fuser='', $dates='', $datee='')
1111
	{
1112
		global $langs;
1113
1114
		if (empty($id)) $id=$this->id;
0 ignored issues
show
Bug introduced by
The variable $id seems only to be defined at a later point. As such the call to empty() seems to always evaluate to true.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
1115
1116
		$result=array();
1117
1118
		$sql = "SELECT";
1119
		$sql.= " SUM(t.task_duration) as nbseconds,";
1120
		$sql.= " SUM(t.task_duration / 3600 * ".$this->db->ifsql("t.thm IS NULL", 0, "t.thm").") as amount, SUM(".$this->db->ifsql("t.thm IS NULL", 1, 0).") as nblinesnull";
1121
		$sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time as t";
1122
		$sql.= " WHERE t.fk_task = ".$id;
1123
		if (is_object($fuser) && $fuser->id > 0)
1124
		{
1125
			$sql.=" AND fk_user = ".$fuser->id;
1126
		}
1127
		if ($dates > 0)
1128
		{
1129
			$datefieldname="task_datehour";
1130
			$sql.=" AND (".$datefieldname." >= '".$this->db->idate($dates)."' OR ".$datefieldname." IS NULL)";
1131
		}
1132
		if ($datee > 0)
1133
		{
1134
			$datefieldname="task_datehour";
1135
			$sql.=" AND (".$datefieldname." <= '".$this->db->idate($datee)."' OR ".$datefieldname." IS NULL)";
1136
		}
1137
		//print $sql;
1138
1139
		dol_syslog(get_class($this)."::getSumOfAmount", LOG_DEBUG);
1140
		$resql=$this->db->query($sql);
1141
		if ($resql)
1142
		{
1143
			$obj = $this->db->fetch_object($resql);
1144
1145
			$result['amount'] = $obj->amount;
1146
			$result['nbseconds'] = $obj->nbseconds;
1147
			$result['nblinesnull'] = $obj->nblinesnull;
1148
1149
			$this->db->free($resql);
1150
			return $result;
1151
		}
1152
		else
1153
		{
1154
			dol_print_error($this->db);
1155
			return $result;
1156
		}
1157
	}
1158
1159
	/**
1160
	 *  Load one record of time spent
1161
	 *
1162
	 *  @param	int		$id 	Id object
1163
	 *  @return int		        <0 if KO, >0 if OK
1164
	 */
1165
	function fetchTimeSpent($id)
1166
	{
1167
		global $langs;
1168
1169
		$sql = "SELECT";
1170
		$sql.= " t.rowid,";
1171
		$sql.= " t.fk_task,";
1172
		$sql.= " t.task_date,";
1173
		$sql.= " t.task_datehour,";
1174
		$sql.= " t.task_date_withhour,";
1175
		$sql.= " t.task_duration,";
1176
		$sql.= " t.fk_user,";
1177
		$sql.= " t.note";
1178
		$sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time as t";
1179
		$sql.= " WHERE t.rowid = ".$id;
1180
1181
		dol_syslog(get_class($this)."::fetchTimeSpent", LOG_DEBUG);
1182
		$resql=$this->db->query($sql);
1183
		if ($resql)
1184
		{
1185
			if ($this->db->num_rows($resql))
1186
			{
1187
				$obj = $this->db->fetch_object($resql);
1188
1189
				$this->timespent_id			= $obj->rowid;
1190
				$this->id					= $obj->fk_task;
1191
				$this->timespent_date		= $this->db->jdate($obj->task_date);
1192
				$this->timespent_datehour   = $this->db->jdate($obj->task_datehour);
1193
				$this->timespent_withhour   = $obj->task_date_withhour;
1194
				$this->timespent_duration	= $obj->task_duration;
1195
				$this->timespent_fk_user	= $obj->fk_user;
1196
				$this->timespent_note		= $obj->note;
1197
			}
1198
1199
			$this->db->free($resql);
1200
1201
			return 1;
1202
		}
1203
		else
1204
		{
1205
			$this->error="Error ".$this->db->lasterror();
1206
			return -1;
1207
		}
1208
	}
1209
1210
	/**
1211
	 *  Load all records of time spent
1212
	 *
1213
	 *  @param	User	$userobj			User object
1214
	 *  @param	string	$morewherefilter	Add more filter into where SQL request (must start with ' AND ...')
1215
	 *  @return int							<0 if KO, array of time spent if OK
1216
	 */
1217
	function fetchAllTimeSpent(User $userobj, $morewherefilter='')
1218
	{
1219
		global $langs;
1220
1221
		$arrayres=array();
1222
1223
		$sql = "SELECT";
1224
		$sql.= " s.rowid as socid,";
1225
		$sql.= " s.nom as thirdparty_name,";
1226
		$sql.= " s.email as thirdparty_email,";
1227
		$sql.= " ptt.rowid,";
1228
		$sql.= " ptt.fk_task,";
1229
		$sql.= " ptt.task_date,";
1230
		$sql.= " ptt.task_datehour,";
1231
		$sql.= " ptt.task_date_withhour,";
1232
		$sql.= " ptt.task_duration,";
1233
		$sql.= " ptt.fk_user,";
1234
		$sql.= " ptt.note,";
1235
		$sql.= " pt.rowid as task_id,";
1236
		$sql.= " pt.ref as task_ref,";
1237
		$sql.= " pt.label as task_label,";
1238
		$sql.= " p.rowid as project_id,";
1239
		$sql.= " p.ref as project_ref,";
1240
		$sql.= " p.title as project_label,";
1241
		$sql.= " p.public as public";
1242
		$sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time as ptt, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."projet as p";
1243
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
1244
		$sql.= " WHERE ptt.fk_task = pt.rowid AND pt.fk_projet = p.rowid";
1245
		$sql.= " AND ptt.fk_user = ".$userobj->id;
1246
		$sql.= " AND pt.entity IN (".getEntity('project').")";
1247
		if ($morewherefilter) $sql.=$morewherefilter;
1248
1249
		dol_syslog(get_class($this)."::fetchAllTimeSpent", LOG_DEBUG);
1250
		$resql=$this->db->query($sql);
1251
		if ($resql)
1252
		{
1253
			$num = $this->db->num_rows($resql);
1254
1255
			$i=0;
1256
			while ($i < $num)
1257
			{
1258
				$obj = $this->db->fetch_object($resql);
1259
1260
				$newobj = new stdClass();
1261
1262
				$newobj->socid              = $obj->socid;
1263
				$newobj->thirdparty_name    = $obj->thirdparty_name;
1264
				$newobj->thirdparty_email   = $obj->thirdparty_email;
1265
1266
				$newobj->fk_project			= $obj->project_id;
1267
				$newobj->project_ref		= $obj->project_ref;
1268
				$newobj->project_label		= $obj->project_label;
1269
				$newobj->public				= $obj->project_public;
1270
1271
				$newobj->fk_task			= $obj->task_id;
1272
				$newobj->task_ref			= $obj->task_ref;
1273
				$newobj->task_label			= $obj->task_label;
1274
1275
				$newobj->timespent_id		= $obj->rowid;
1276
				$newobj->timespent_date		= $this->db->jdate($obj->task_date);
1277
				$newobj->timespent_datehour	= $this->db->jdate($obj->task_datehour);
1278
				$newobj->timespent_withhour = $obj->task_date_withhour;
1279
				$newobj->timespent_duration = $obj->task_duration;
1280
				$newobj->timespent_fk_user	= $obj->fk_user;
1281
				$newobj->timespent_note		= $obj->note;
1282
1283
				$arrayres[] = $newobj;
1284
1285
				$i++;
1286
			}
1287
1288
			$this->db->free($resql);
1289
		}
1290
		else
1291
		{
1292
			dol_print_error($this->db);
1293
			$this->error="Error ".$this->db->lasterror();
1294
			return -1;
1295
		}
1296
1297
		return $arrayres;
1298
	}
1299
1300
	/**
1301
	 *	Update time spent
1302
	 *
1303
	 *  @param	User	$user           User id
1304
	 *  @param  int		$notrigger	    0=launch triggers after, 1=disable triggers
1305
	 *  @return	int						<0 if KO, >0 if OK
1306
	 */
1307
	function updateTimeSpent($user, $notrigger=0)
1308
	{
1309
		global $conf,$langs;
1310
1311
		$ret = 0;
1312
1313
		// Clean parameters
1314
		if (empty($this->timespent_datehour)) $this->timespent_datehour = $this->timespent_date;
1315
		if (isset($this->timespent_note)) $this->timespent_note = trim($this->timespent_note);
1316
1317
		$this->db->begin();
1318
1319
		$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_time SET";
1320
		$sql.= " task_date = '".$this->db->idate($this->timespent_date)."',";
1321
		$sql.= " task_datehour = '".$this->db->idate($this->timespent_datehour)."',";
1322
		$sql.= " task_date_withhour = ".(empty($this->timespent_withhour)?0:1).",";
1323
		$sql.= " task_duration = ".$this->timespent_duration.",";
1324
		$sql.= " fk_user = ".$this->timespent_fk_user.",";
1325
		$sql.= " note = ".(isset($this->timespent_note)?"'".$this->db->escape($this->timespent_note)."'":"null");
1326
		$sql.= " WHERE rowid = ".$this->timespent_id;
1327
1328
		dol_syslog(get_class($this)."::updateTimeSpent", LOG_DEBUG);
1329
		if ($this->db->query($sql) )
1330
		{
1331
			if (! $notrigger)
1332
			{
1333
				// Call trigger
1334
				$result=$this->call_trigger('TASK_TIMESPENT_MODIFY',$user);
1335
				if ($result < 0)
1336
				{
1337
					$this->db->rollback();
1338
					$ret = -1;
1339
				}
1340
				else $ret = 1;
1341
				// End call triggers
1342
			}
1343
			else $ret = 1;
1344
		}
1345
		else
1346
		{
1347
			$this->error=$this->db->lasterror();
1348
			$this->db->rollback();
1349
			$ret = -1;
1350
		}
1351
1352
		if ($ret == 1 && ($this->timespent_old_duration != $this->timespent_duration))
1353
		{
1354
			$newDuration = $this->timespent_duration - $this->timespent_old_duration;
1355
1356
			$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
1357
			$sql.= " SET duration_effective = (SELECT SUM(task_duration) FROM ".MAIN_DB_PREFIX."projet_task_time as ptt where ptt.fk_task = ".$this->db->escape($this->id).")";
1358
			$sql.= " WHERE rowid = ".$this->id;
1359
1360
			dol_syslog(get_class($this)."::updateTimeSpent", LOG_DEBUG);
1361
			if (! $this->db->query($sql) )
1362
			{
1363
				$this->error=$this->db->lasterror();
1364
				$this->db->rollback();
1365
				$ret = -2;
1366
			}
1367
		}
1368
1369
		if ($ret >= 0) $this->db->commit();
1370
		return $ret;
1371
	}
1372
1373
	/**
1374
	 *  Delete time spent
1375
	 *
1376
	 *  @param	User	$user        	User that delete
1377
	 *  @param  int		$notrigger	    0=launch triggers after, 1=disable triggers
1378
	 *  @return	int						<0 if KO, >0 if OK
1379
	 */
1380
	function delTimeSpent($user, $notrigger=0)
1381
	{
1382
		global $conf, $langs;
1383
1384
		$error=0;
1385
1386
		$this->db->begin();
1387
1388
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task_time";
1389
		$sql.= " WHERE rowid = ".$this->timespent_id;
1390
1391
		dol_syslog(get_class($this)."::delTimeSpent", LOG_DEBUG);
1392
		$resql = $this->db->query($sql);
1393
		if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
1394
1395
		if (! $error)
1396
		{
1397
			if (! $notrigger)
1398
			{
1399
				// Call trigger
1400
				$result=$this->call_trigger('TASK_TIMESPENT_DELETE',$user);
1401
				if ($result < 0) { $error++; }
1402
				// End call triggers
1403
			}
1404
		}
1405
1406
		if (! $error)
1407
		{
1408
			$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
1409
			$sql.= " SET duration_effective = duration_effective - ".$this->db->escape($this->timespent_duration?$this->timespent_duration:0);
1410
			$sql.= " WHERE rowid = ".$this->id;
1411
1412
			dol_syslog(get_class($this)."::delTimeSpent", LOG_DEBUG);
1413
			if ($this->db->query($sql) )
1414
			{
1415
				$result = 0;
1416
			}
1417
			else
1418
			{
1419
				$this->error=$this->db->lasterror();
1420
				$result = -2;
1421
			}
1422
		}
1423
1424
		// Commit or rollback
1425
		if ($error)
1426
		{
1427
			foreach($this->errors as $errmsg)
1428
			{
1429
				dol_syslog(get_class($this)."::delTimeSpent ".$errmsg, LOG_ERR);
1430
				$this->error.=($this->error?', '.$errmsg:$errmsg);
1431
			}
1432
			$this->db->rollback();
1433
			return -1*$error;
1434
		}
1435
		else
1436
		{
1437
			$this->db->commit();
1438
			return 1;
1439
		}
1440
	}
1441
1442
	 /**	Load an object from its id and create a new one in database
1443
	  *
1444
	  *	@param	int		$fromid     			Id of object to clone
1445
	  *  @param	int		$project_id				Id of project to attach clone task
1446
	  *  @param	int		$parent_task_id			Id of task to attach clone task
1447
	  *  @param	bool	$clone_change_dt		recalculate date of task regarding new project start date
1448
	  *	@param	bool	$clone_affectation		clone affectation of project
1449
	  *	@param	bool	$clone_time				clone time of project
1450
	  *	@param	bool	$clone_file				clone file of project
1451
	  *  @param	bool	$clone_note				clone note of project
1452
	  *	@param	bool	$clone_prog				clone progress of project
1453
	  * 	@return	int								New id of clone
1454
	  */
1455
	function createFromClone($fromid,$project_id,$parent_task_id,$clone_change_dt=false,$clone_affectation=false,$clone_time=false,$clone_file=false,$clone_note=false,$clone_prog=false)
1456
	{
1457
		global $user,$langs,$conf;
1458
1459
		$error=0;
1460
1461
		//Use 00:00 of today if time is use on task.
1462
		$now=dol_mktime(0,0,0,dol_print_date(dol_now(),'%m'),dol_print_date(dol_now(),'%d'),dol_print_date(dol_now(),'%Y'));
1463
1464
		$datec = $now;
1465
1466
		$clone_task=new Task($this->db);
1467
		$origin_task=new Task($this->db);
1468
1469
		$clone_task->context['createfromclone']='createfromclone';
1470
1471
		$this->db->begin();
1472
1473
		// Load source object
1474
		$clone_task->fetch($fromid);
1475
		$clone_task->fetch_optionals();
1476
		//var_dump($clone_task->array_options);exit;
1477
1478
		$origin_task->fetch($fromid);
1479
1480
		$defaultref='';
1481
		$obj = empty($conf->global->PROJECT_TASK_ADDON)?'mod_task_simple':$conf->global->PROJECT_TASK_ADDON;
1482
		if (! empty($conf->global->PROJECT_TASK_ADDON) && is_readable(DOL_DOCUMENT_ROOT ."/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.".php"))
1483
		{
1484
			require_once DOL_DOCUMENT_ROOT ."/core/modules/project/task/".$conf->global->PROJECT_TASK_ADDON.'.php';
1485
			$modTask = new $obj;
1486
			$defaultref = $modTask->getNextValue(0,$clone_task);
1487
		}
1488
1489
		$ori_project_id					= $clone_task->fk_project;
1490
1491
		$clone_task->id					= 0;
1492
		$clone_task->ref				= $defaultref;
1493
		$clone_task->fk_project			= $project_id;
1494
		$clone_task->fk_task_parent		= $parent_task_id;
1495
		$clone_task->date_c				= $datec;
1496
		$clone_task->planned_workload	= $origin_task->planned_workload;
1497
		$clone_task->rang				= $origin_task->rang;
1498
1499
		//Manage Task Date
1500
		if ($clone_change_dt)
1501
		{
1502
			$projectstatic=new Project($this->db);
1503
			$projectstatic->fetch($ori_project_id);
1504
1505
			//Origin project strat date
1506
			$orign_project_dt_start = $projectstatic->date_start;
1507
1508
			//Calcultate new task start date with difference between origin proj start date and origin task start date
1509
			if (!empty($clone_task->date_start))
1510
			{
1511
				$clone_task->date_start			= $now + $clone_task->date_start - $orign_project_dt_start;
1512
			}
1513
1514
			//Calcultate new task end date with difference between origin proj end date and origin task end date
1515
			if (!empty($clone_task->date_end))
1516
			{
1517
				$clone_task->date_end			= $now + $clone_task->date_end - $orign_project_dt_start;
1518
			}
1519
1520
		}
1521
1522
		if (!$clone_prog)
1523
		{
1524
				$clone_task->progress=0;
1525
		}
1526
1527
		// Create clone
1528
		$result=$clone_task->create($user);
1529
1530
		// Other options
1531
		if ($result < 0)
1532
		{
1533
			$this->error=$clone_task->error;
1534
			$error++;
1535
		}
1536
1537
		// End
1538
		if (! $error)
1539
		{
1540
			$clone_task_id=$clone_task->id;
1541
			$clone_task_ref = $clone_task->ref;
1542
1543
	   		//Note Update
1544
			if (!$clone_note)
1545
	   		{
1546
				$clone_task->note_private='';
1547
				$clone_task->note_public='';
1548
			}
1549
			else
1550
			{
1551
				$this->db->begin();
1552
				$res=$clone_task->update_note(dol_html_entity_decode($clone_task->note_public, ENT_QUOTES),'_public');
1553
				if ($res < 0)
1554
				{
1555
					$this->error.=$clone_task->error;
1556
					$error++;
1557
					$this->db->rollback();
1558
				}
1559
				else
1560
				{
1561
					$this->db->commit();
1562
				}
1563
1564
				$this->db->begin();
1565
				$res=$clone_task->update_note(dol_html_entity_decode($clone_task->note_private, ENT_QUOTES), '_private');
1566
				if ($res < 0)
1567
				{
1568
					$this->error.=$clone_task->error;
1569
					$error++;
1570
					$this->db->rollback();
1571
				}
1572
				else
1573
				{
1574
					$this->db->commit();
1575
				}
1576
			}
1577
1578
			//Duplicate file
1579
			if ($clone_file)
1580
			{
1581
				require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1582
1583
				//retreive project origin ref to know folder to copy
1584
				$projectstatic=new Project($this->db);
1585
				$projectstatic->fetch($ori_project_id);
1586
				$ori_project_ref=$projectstatic->ref;
1587
1588
				if ($ori_project_id!=$project_id)
1589
				{
1590
					$projectstatic->fetch($project_id);
1591
					$clone_project_ref=$projectstatic->ref;
1592
				}
1593
				else
1594
				{
1595
					$clone_project_ref=$ori_project_ref;
1596
				}
1597
1598
				$clone_task_dir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($clone_project_ref). "/" . dol_sanitizeFileName($clone_task_ref);
1599
				$ori_task_dir = $conf->projet->dir_output . "/" . dol_sanitizeFileName($ori_project_ref). "/" . dol_sanitizeFileName($fromid);
1600
1601
				$filearray=dol_dir_list($ori_task_dir,"files",0,'','(\.meta|_preview.*\.png)$','',SORT_ASC,1);
1602
				foreach($filearray as $key => $file)
1603
				{
1604
					if (!file_exists($clone_task_dir))
1605
					{
1606
						if (dol_mkdir($clone_task_dir) < 0)
1607
						{
1608
							$this->error.=$langs->trans('ErrorInternalErrorDetected').':dol_mkdir';
1609
							$error++;
1610
						}
1611
					}
1612
1613
					$rescopy = dol_copy($ori_task_dir . '/' . $file['name'], $clone_task_dir . '/' . $file['name'],0,1);
1614
					if (is_numeric($rescopy) && $rescopy < 0)
1615
					{
1616
						$this->error.=$langs->trans("ErrorFailToCopyFile",$ori_task_dir . '/' . $file['name'],$clone_task_dir . '/' . $file['name']);
1617
						$error++;
1618
					}
1619
				}
1620
			}
1621
1622
			// clone affectation
1623
			if ($clone_affectation)
1624
			{
1625
				$origin_task = new Task($this->db);
1626
				$origin_task->fetch($fromid);
1627
1628
				foreach(array('internal','external') as $source)
1629
				{
1630
					$tab = $origin_task->liste_contact(-1,$source);
1631
					$num=count($tab);
1632
					$i = 0;
1633
					while ($i < $num)
1634
					{
1635
						$clone_task->add_contact($tab[$i]['id'], $tab[$i]['code'], $tab[$i]['source']);
1636
						if ($clone_task->error == 'DB_ERROR_RECORD_ALREADY_EXISTS')
1637
						{
1638
							$langs->load("errors");
1639
							$this->error.=$langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType");
1640
							$error++;
1641
						}
1642
						else
1643
						{
1644
							if ($clone_task->error!='')
1645
							{
1646
								$this->error.=$clone_task->error;
1647
								$error++;
1648
							}
1649
						}
1650
						$i++;
1651
					}
1652
				}
1653
			}
1654
1655
			if($clone_time)
1656
			{
1657
				//TODO clone time of affectation
1658
			}
1659
		}
1660
1661
		unset($clone_task->context['createfromclone']);
1662
1663
		if (! $error)
1664
		{
1665
			$this->db->commit();
1666
			return $clone_task_id;
0 ignored issues
show
Bug introduced by
The variable $clone_task_id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1667
		}
1668
		else
1669
		{
1670
			$this->db->rollback();
1671
			dol_syslog(get_class($this)."::createFromClone nbError: ".$error." error : " . $this->error, LOG_ERR);
1672
			return -1;
1673
		}
1674
	}
1675
1676
1677
	/**
1678
	 *	Return status label of object
1679
	 *
1680
	 *	@param	integer	$mode		0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
1681
	 * 	@return	string	  			Label
1682
	 */
1683
	function getLibStatut($mode=0)
1684
	{
1685
		return $this->LibStatut($this->fk_statut,$mode);
1686
	}
1687
1688
	/**
1689
	 *	Return status label for an object
1690
	 *
1691
	 *	@param	int			$statut	  	Id statut
1692
	 *	@param	integer		$mode		0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
1693
	 * 	@return	string	  				Label
1694
	 */
1695
	function LibStatut($statut,$mode=0)
1696
	{
1697
		// list of Statut of the task
1698
		$this->statuts[0]='Draft';
1699
		$this->statuts[1]='Validated';
1700
		$this->statuts[2]='Running';
1701
		$this->statuts[3]='Finish';
1702
		$this->statuts[4]='Transfered';
1703
		$this->statuts_short[0]='Draft';
1704
		$this->statuts_short[1]='Validated';
1705
		$this->statuts_short[2]='Running';
1706
		$this->statuts_short[3]='Finish';
1707
		$this->statuts_short[4]='Transfered';
1708
1709
		global $langs;
1710
1711
		if ($mode == 0)
1712
		{
1713
			return $langs->trans($this->statuts[$statut]);
1714
		}
1715
		if ($mode == 1)
1716
		{
1717
			return $langs->trans($this->statuts_short[$statut]);
1718
		}
1719
		if ($mode == 2)
1720
		{
1721
			if ($statut==0) return img_picto($langs->trans($this->statuts_short[$statut]),'statut0').' '.$langs->trans($this->statuts_short[$statut]);
1722
			if ($statut==1) return img_picto($langs->trans($this->statuts_short[$statut]),'statut1').' '.$langs->trans($this->statuts_short[$statut]);
1723
			if ($statut==2) return img_picto($langs->trans($this->statuts_short[$statut]),'statut3').' '.$langs->trans($this->statuts_short[$statut]);
1724
			if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut4').' '.$langs->trans($this->statuts_short[$statut]);
1725
			if ($statut==4) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6').' '.$langs->trans($this->statuts_short[$statut]);
1726
			if ($statut==5) return img_picto($langs->trans($this->statuts_short[$statut]),'statut5').' '.$langs->trans($this->statuts_short[$statut]);
1727
		}
1728
		if ($mode == 3)
1729
		{
1730
			if ($statut==0) return img_picto($langs->trans($this->statuts_short[$statut]),'statut0');
1731
			if ($statut==1) return img_picto($langs->trans($this->statuts_short[$statut]),'statut1');
1732
			if ($statut==2) return img_picto($langs->trans($this->statuts_short[$statut]),'statut3');
1733
			if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut4');
1734
			if ($statut==4) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6');
1735
			if ($statut==5) return img_picto($langs->trans($this->statuts_short[$statut]),'statut5');
1736
		}
1737
		if ($mode == 4)
1738
		{
1739
			if ($statut==0) return img_picto($langs->trans($this->statuts_short[$statut]),'statut0').' '.$langs->trans($this->statuts[$statut]);
1740
			if ($statut==1) return img_picto($langs->trans($this->statuts_short[$statut]),'statut1').' '.$langs->trans($this->statuts[$statut]);
1741
			if ($statut==2) return img_picto($langs->trans($this->statuts_short[$statut]),'statut3').' '.$langs->trans($this->statuts[$statut]);
1742
			if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut4').' '.$langs->trans($this->statuts[$statut]);
1743
			if ($statut==4) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6').' '.$langs->trans($this->statuts[$statut]);
1744
			if ($statut==5) return img_picto($langs->trans($this->statuts_short[$statut]),'statut5').' '.$langs->trans($this->statuts[$statut]);
1745
		}
1746
		if ($mode == 5)
1747
		{
1748
			if ($statut==0) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut0');
1749
			if ($statut==1) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut1');
1750
			if ($statut==2) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut3');
1751
			if ($statut==3) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut4');
1752
			if ($statut==4) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut6');
1753
			if ($statut==5) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut5');
1754
		}
1755
		if ($mode == 6)
1756
		{
1757
			/*if ($statut==0) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut0');
1758
			if ($statut==1) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut1');
1759
			if ($statut==2) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut3');
1760
			if ($statut==3) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut4');
1761
			if ($statut==4) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut6');
1762
			if ($statut==5) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut5');*/
1763
			//return $this->progress.' %';
1764
			return '&nbsp;';
1765
		}
1766
	}
1767
1768
	/**
1769
	 *  Create an intervention document on disk using template defined into PROJECT_TASK_ADDON_PDF
1770
	 *
1771
	 *  @param	string		$modele			force le modele a utiliser ('' par defaut)
1772
	 *  @param	Translate	$outputlangs	objet lang a utiliser pour traduction
1773
	 *  @param  int			$hidedetails    Hide details of lines
1774
	 *  @param  int			$hidedesc       Hide description
1775
	 *  @param  int			$hideref        Hide ref
1776
	 *  @return int         				0 if KO, 1 if OK
1777
	 */
1778
	public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
1779
	{
1780
		global $conf,$langs;
1781
1782
		$langs->load("projects");
1783
1784
		if (! dol_strlen($modele)) {
1785
1786
			$modele = 'nodefault';
1787
1788
			if ($this->modelpdf) {
1789
				$modele = $this->modelpdf;
1790
			} elseif (! empty($conf->global->PROJECT_TASK_ADDON_PDF)) {
1791
				$modele = $conf->global->PROJECT_TASK_ADDON_PDF;
1792
			}
1793
		}
1794
1795
		$modelpath = "core/modules/project/task/doc/";
1796
1797
		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
1798
	}
1799
1800
1801
	/**
1802
	 * Load indicators for dashboard (this->nbtodo and this->nbtodolate)
1803
	 *
1804
	 * @param	User	$user   Objet user
1805
	 * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK
1806
	 */
1807
	function load_board($user)
1808
	{
1809
		global $conf, $langs;
1810
1811
		$mine=0; $socid=$user->societe_id;
1812
1813
		$projectstatic = new Project($this->db);
1814
		$projectsListId = $projectstatic->getProjectsAuthorizedForUser($user,$mine,1,$socid);
1815
1816
		// List of tasks (does not care about permissions. Filtering will be done later)
1817
		$sql = "SELECT p.rowid as projectid, p.fk_statut as projectstatus,";
1818
		$sql.= " t.rowid as taskid, t.progress as progress, t.fk_statut as status,";
1819
		$sql.= " t.dateo as date_start, t.datee as datee";
1820
		$sql.= " FROM ".MAIN_DB_PREFIX."projet as p";
1821
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
1822
		if (! $user->rights->societe->client->voir && ! $socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = s.rowid";
1823
		$sql.= ", ".MAIN_DB_PREFIX."projet_task as t";
1824
		$sql.= " WHERE p.entity IN (".getEntity('project', 0).')';
1825
		$sql.= " AND p.fk_statut = 1";
1826
		$sql.= " AND t.fk_projet = p.rowid";
1827
		$sql.= " AND t.progress < 100";         // tasks to do
1828
		if ($mine || ! $user->rights->projet->all->lire) $sql.= " AND p.rowid IN (".$projectsListId.")";
1829
		// No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser
1830
		//if ($socid || ! $user->rights->societe->client->voir)	$sql.= "  AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
1831
		if ($socid) $sql.= "  AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
1832
		if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND ((s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id.") OR (s.rowid IS NULL))";
1833
		//print $sql;
1834
		$resql=$this->db->query($sql);
1835
		if ($resql)
1836
		{
1837
			$task_static = new Task($this->db);
1838
1839
			$response = new WorkboardResponse();
1840
			$response->warning_delay = $conf->projet->task->warning_delay/60/60/24;
1841
			$response->label = $langs->trans("OpenedTasks");
1842
			if ($user->rights->projet->all->lire) $response->url = DOL_URL_ROOT.'/projet/tasks/list.php?mainmenu=project';
1843
			else $response->url = DOL_URL_ROOT.'/projet/tasks/list.php?mode=mine&amp;mainmenu=project';
1844
			$response->img = img_object('',"task");
1845
1846
			// This assignment in condition is not a bug. It allows walking the results.
1847
			while ($obj=$this->db->fetch_object($resql))
1848
			{
1849
				$response->nbtodo++;
1850
1851
				$task_static->projectstatus = $obj->projectstatus;
1852
				$task_static->progress = $obj->progress;
1853
				$task_static->fk_statut = $obj->status;
1854
				$task_static->date_end = $this->db->jdate($obj->datee);
1855
1856
				if ($task_static->hasDelay()) {
1857
					$response->nbtodolate++;
1858
				}
1859
			}
1860
1861
			return $response;
1862
		}
1863
		else
1864
		{
1865
			$this->error=$this->db->error();
1866
			return -1;
1867
		}
1868
	}
1869
1870
1871
	/**
1872
	 *      Charge indicateurs this->nb de tableau de bord
1873
	 *
1874
	 *      @return     int         <0 if ko, >0 if ok
1875
	 */
1876
	function load_state_board()
1877
	{
1878
		global $user;
1879
1880
		$mine=0; $socid=$user->societe_id;
1881
1882
		$projectstatic = new Project($this->db);
1883
		$projectsListId = $projectstatic->getProjectsAuthorizedForUser($user,$mine,1,$socid);
1884
1885
		// List of tasks (does not care about permissions. Filtering will be done later)
1886
		$sql = "SELECT count(p.rowid) as nb";
1887
		$sql.= " FROM ".MAIN_DB_PREFIX."projet as p";
1888
		$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
1889
		if (! $user->rights->societe->client->voir && ! $socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = s.rowid";
1890
		$sql.= ", ".MAIN_DB_PREFIX."projet_task as t";
1891
		$sql.= " WHERE p.entity IN (".getEntity('project', 0).')';
1892
		$sql.= " AND t.fk_projet = p.rowid";         // tasks to do
1893
		if ($mine || ! $user->rights->projet->all->lire) $sql.= " AND p.rowid IN (".$projectsListId.")";
1894
		// No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser
1895
		//if ($socid || ! $user->rights->societe->client->voir)	$sql.= "  AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
1896
		if ($socid) $sql.= "  AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
1897
		if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND ((s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id.") OR (s.rowid IS NULL))";
1898
1899
		$resql=$this->db->query($sql);
1900
		if ($resql)
1901
		{
1902
1903
			// This assignment in condition is not a bug. It allows walking the results.
1904
			while ($obj=$this->db->fetch_object($resql))
1905
			{
1906
				$this->nb["tasks"]=$obj->nb;
1907
			}
1908
			$this->db->free($resql);
1909
			return 1;
1910
		}
1911
		else
1912
		{
1913
			dol_print_error($this->db);
1914
			$this->error=$this->db->error();
1915
			return -1;
1916
		}
1917
	}
1918
1919
	/**
1920
	 * Is the task delayed?
1921
	 *
1922
	 * @return bool
1923
	 */
1924
	public function hasDelay()
1925
	{
1926
		global $conf;
1927
1928
		if (! ($this->progress >= 0 && $this->progress < 100)) {
1929
			return false;
1930
		}
1931
1932
		$now = dol_now();
1933
1934
		$datetouse = ($this->date_end > 0) ? $this->date_end : ($this->datee > 0 ? $this->datee : 0);
1935
1936
		return ($datetouse > 0 && ($datetouse < ($now - $conf->projet->task->warning_delay)));
1937
	}
1938
}