getManagerDeleteUrl()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 5
rs 9.4285
ccs 0
cts 3
cp 0
crap 2
1
<?php
2
/************************************************************************
3
 * OVIDENTIA http://www.ovidentia.org                                   *
4
 ************************************************************************
5
 * Copyright (c) 2003 by CANTICO ( http://www.cantico.fr )              *
6
 *                                                                      *
7
 * This file is part of Ovidentia.                                      *
8
 *                                                                      *
9
 * Ovidentia is free software; you can redistribute it and/or modify    *
10
 * it under the terms of the GNU General Public License as published by *
11
 * the Free Software Foundation; either version 2, or (at your option)  *
12
 * any later version.													*
13
 *																		*
14
 * This program is distributed in the hope that it will be useful, but  *
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of			*
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.					*
17
 * See the  GNU General Public License for more details.				*
18
 *																		*
19
 * You should have received a copy of the GNU General Public License	*
20
 * along with this program; if not, write to the Free Software			*
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,*
22
 * USA.																	*
23
************************************************************************/
24
25 1
require_once dirname(__FILE__).'/request.class.php';
26
27
28
29
/**
30
 * Work period recovery request
31
 * 
32
 * 
33
 * @property	int			$id_user
34
 * @property	string		$date_begin
35
 * @property	string		$date_end
36
 * @property	int			$id_type
37
 * @property	int			$idfai
38
 * @property	string		$comment
39
 * @property	string		$createdOn
40
 * @property	string		$modifiedOn
41
 * @property	string		$status
42
 * @property	int			$id_approver
43
 * @property	int			$id_right
44
 * @property	float		$quantity
45
 * @property	string		$quantity_unit
46
 * @property	string		validity_end
47
 * @property	int			$archived
48
 */
49
class absences_WorkperiodRecoverRequest extends absences_Request
50
{
51
	/**
52
	 * @var absences_WorkperiodType
53
	 */
54
	private $type;
55
	
56
	
57
	/**
58
	 * @param int $id
59
	 * @return absences_WorkperiodRecoverRequest
60
	 */
61
	public static function getById($id)
62
	{
63
		$request = new absences_WorkperiodRecoverRequest();
64
		$request->id = $id;
65
	
66
		return $request;
67
	}
68
	
69
	
70
	
71
	/**
72
	 * 
73
	 * @return array
74
	 */
75
	public function getRow()
76
	{
77
		if (null === $this->row)
78
		{
79
			global $babDB;
80
			$query = 'SELECT * FROM absences_workperiod_recover_request WHERE id='.$babDB->quote($this->id);
81
	
82
			$res = $babDB->db_query($query);
83
			$this->setRow($babDB->db_fetch_assoc($res));
84
		}
85
	
86
		return $this->row;
87
	}
88
	
89
	
90
	/**
91
	 *
92
	 * @param absences_WorkperiodType $type
93
	 * @return absences_WorkperiodRecoverRequest
94
	 */
95
	public function setType(absences_WorkperiodType $type)
96
	{
97
		$this->type = $type;
98
		return $this;
99
	}
100
	
101
	
102
	/**
103
	 * 
104
	 * @return absences_WorkperiodType
105
	 */
106
	public function getType()
107
	{
108
		if (!isset($this->type))
109
		{
110
			require_once dirname(__FILE__).'/workperiod_type.class.php';
111
			
112
			$row = $this->getRow();
113
			$this->type = absences_WorkperiodType::getFromId($row['id_type']);
114
		}
115
	
116
		return $this->type;
117
	}
118
	
119
	
120
	
121
	
122
	/**
123
	 * (non-PHPdoc)
124
	 * @see absences_Request::getRequestType()
125
	 *
126
	 * @return string
127
	 */
128
	public function getRequestType()
129
	{
130
		return absences_translate('Worked day entitling recovery');
131
	}
132
	
133
	
134
	
135
	/**
136
	 * 
137
	 */
138
	public function save()
139
	{
140
		global $babDB;
141
		require_once $GLOBALS['babInstallPath'].'utilit/dateTime.php';
142
		
143
		if (!isset($this->validity_end) || '0000-00-00' === $this->validity_end)
144
		{
145
			$end = BAB_DateTime::fromIsoDateTime($this->date_end);
146
			$days = absences_getVacationOption('end_recup');
147
			
148
			if (!$days) {
149
			    $days = 365;
150
			}
151
			
152
			// les annees ne foncitonnent pas avec cette API ?
153
			
154
			if (($days / 365) >= 1) {
155
			    $years = (int)($days / 365);
156
			    $days = $days % 365;
157
			    
158
			    $end->add($years, BAB_DATETIME_YEAR);
159
			}
160
			
161
			$end->add($days, BAB_DATETIME_DAY);
162
			
163
			$this->validity_end = $end->getIsoDate();
164
		}
165
		
166
		
167
		
168
		if (isset($this->id))
169
		{
170
		    $query = 'UPDATE absences_workperiod_recover_request SET 
171
				id_user='.$babDB->quote($this->id_user).', 
172
				date_begin='.$babDB->quote($this->date_begin).',	
173
				date_end='.$babDB->quote($this->date_end).', 
174
				id_type='.$babDB->quote($this->id_type).',	
175
				idfai='.$babDB->quote($this->idfai).',	
176
				comment='.$babDB->quote($this->comment).',	
177
				modifiedOn=NOW(),
178
				status='.$babDB->quote($this->status).',
179
				comment2='.$babDB->quote($this->comment2).',
180
				id_approver='.$babDB->quote($this->id_approver).',
181
				id_right='.$babDB->quote($this->id_right).',
182
				quantity='.$babDB->quote($this->quantity).',
183
				quantity_unit='.$babDB->quote($this->quantity_unit).', 
184
				validity_end='.$babDB->quote($this->validity_end).'
185
		    ';
186
		    
187
		    if (isset($this->todelete)) {
188
		        $query .= ', todelete='.$babDB->quote($this->todelete);
189
		    }
190
		    
191
		    $query .= 'WHERE id='.$babDB->quote($this->id);
192
		    
193
194
			$babDB->db_query($query);
195
			
196
			
197
		} else {
198
		
199
			$babDB->db_query('INSERT INTO absences_workperiod_recover_request (
200
					id_user,
201
					date_begin,
202
					date_end,
203
					id_type,
204
					comment,
205
					createdOn,
206
					modifiedOn,
207
					status,
208
					quantity,
209
					quantity_unit,
210
					validity_end
211
				) VALUES (
212
					
213
					'.$babDB->quote($this->id_user).',
214
					'.$babDB->quote($this->date_begin).',
215
					'.$babDB->quote($this->date_end).',
216
					'.$babDB->quote($this->id_type).',
217
					'.$babDB->quote($this->comment).',
218
					NOW(),
219
					NOW(),
220
					'.$babDB->quote($this->status).',
221
					'.$babDB->quote($this->quantity).',
222
					'.$babDB->quote($this->quantity_unit).',
223
					'.$babDB->quote($this->validity_end).'
224
				)
225
			');
226
			
227
			$this->id = $babDB->db_insert_id();
228
		}
229
	}
230
	
231
	
232
	
233
	
234
	/**
235
	 * Trouver la duree en calculee dans la meme unite que le type associe
236
	 * 
237
	 * duree en jour precis a la demie-journee ou duree en heuress precis a l'heure
238
	 * 
239
	 * 
240
	 * @return float | int
241
	 */
242
	public function getComputedDuration()
243
	{
244
		require_once $GLOBALS['babInstallPath'].'utilit/dateTime.php';
245
		$unit = $this->getType()->quantity_unit;
0 ignored issues
show
Documentation introduced by
The property quantity_unit does not exist on object<absences_WorkperiodType>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
246
		
247
		if ('H' === $unit)
248
		{
249
			return (int) floor((bab_mktime($this->date_end) - bab_mktime($this->date_begin)) / 3600);
250
		}
251
		
252
		// trouver les jours complets
253
		
254
		list($day1, $hour1) = explode(' ', $this->date_begin);
0 ignored issues
show
Unused Code introduced by
The assignment to $hour1 is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
255
		$full1 = BAB_DateTime::fromIsoDateTime($day1.' 00:00:00');
256
		$full1->add(1, BAB_DATETIME_DAY);
257
		
258
		list($day2, $hour2) = explode(' ', $this->date_end);
0 ignored issues
show
Unused Code introduced by
The assignment to $hour2 is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
259
		$full2 = BAB_DateTime::fromIsoDateTime($day2.' 00:00:00');
260
		
261
		$date_begin = BAB_DateTime::fromIsoDateTime($this->date_begin);
262
		$date_end = BAB_DateTime::fromIsoDateTime($this->date_end);
263
		
264
		if ($full1->getIsoDate() > $full2->getIsoDate())
265
		{
266
			$full_days = 0;
0 ignored issues
show
Unused Code introduced by
$full_days is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
267
			
268
			$diff_hour = round(($date_end->getTimeStamp() - $date_begin->getTimeStamp()) / 3600);
269
			$diff_days = $diff_hour > 4 ? 1 : .5;
270
			
271
			return $diff_days;
272
			
273
		} else {
274
			$full_days = $full2->dateDiffIso($full1->getIsoDate(), $full2->getIsoDate());
275
			
276
			bab_debug('Full days : '.$full_days);
277
			
278
			$diff_hour1 = round(($full1->getTimeStamp() - $date_begin->getTimeStamp()) / 3600);
279
			$diff_hour2 = round(($date_end->getTimeStamp() - $full2->getTimeStamp()) / 3600);
280
			
281
			bab_debug('before first complete day : '.$diff_hour1.' h');
282
			bab_debug('after last complete day : '.$diff_hour2.' h');
283
			
284
			
285
			$diff_days1 = $diff_hour1 > 12 ? 1 : .5;
286
			$diff_days2 = $diff_hour2 > 12 ? 1 : .5;
287
			
288
			return ($diff_days1 + $full_days + $diff_days2);
289
		}
290
291
	}
292
	
293
	
294
	
295
	
296
	
297
	/**
298
	 * (non-PHPdoc)
299
	 * @see absences_Request::getApprobationId()
300
	 *
301
	 * @return int
302
	 */
303
	public function getApprobationId()
304
	{
305
		if ($agent = $this->getAgent())
306
		{
307
			return $agent->getRecoverApprobationId();
308
		}
309
	
310
		return null;
311
	}
312
	
313
	/**
314
	 * Process specific code when the request is rejected
315
	 *
316
	 */
317
	protected function onReject()
318
	{
319
		
320
	}
321
	
322
	
323
    /**
324
     * programme de reprise des declaration de jours travaille approuvees par auto-approbation sans droit cree
325
     */
326
	public function restoreMissingRight()
327
	{
328
	    if ($this->id_right) {
329
	        return false;
330
	    }
331
	    $this->onConfirm();
332
	}
333
	
334
	
335
	
336
	public function getRight()
337
	{
338
	    if (!$this->id_right) {
339
	        return null;
340
	    }
341
	    
342
	    require_once dirname(__FILE__).'/right.class.php';
343
	    
344
	    $right = new absences_Right($this->id_right);
345
	    
346
	    if (!$right->getRow()) {
347
	        return null;
348
	    }
349
	    
350
	    
351
	    return $right;
352
	}
353
354
	
355
	
356
	/**
357
	 * Process specific code when the request is confirmed
358
	 * 
359
	 */
360
	protected function onConfirm()
361
	{
362
	    if (null !== $this->getRight()) {
363
	        return;
364
	    }
365
	    
366
		// create right access for recovery only if not allready created
367
		
368
		global $babDB;
369
		require_once dirname(__FILE__).'/right.class.php';
370
		
371
		$agent = $this->getAgent();
372
		
373
		$begin = mb_substr($this->date_end, 0, 10);
374
		$end = $this->validity_end;
375
		
376
		$date = bab_shortDate(bab_mktime($this->date_begin), false);
377
		
378
		$description = $agent->getName().' '.$date;
379
		
380
		// si un droit avec cette description existe deja on ne le cree pas
381
		// mais on fait la liaison avec la periode travaillee
382
		
383
		$res = $babDB->db_query('SELECT id FROM absences_rights WHERE description='.$babDB->quote($description));
384
		$existingRight = $babDB->db_fetch_assoc($res);
385
		
386
		if ($existingRight) {
387
		    $id_right = $existingRight['id'];
388
		} else {
389
		    $id_right = $agent->createRecoveryRight($begin, $end, $description, $this->quantity, $this->quantity_unit);
0 ignored issues
show
Security Bug introduced by
It seems like $end defined by $this->validity_end on line 374 can also be of type false; however, absences_Agent::createRecoveryRight() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
390
		}
391
		
392
		$babDB->db_query('UPDATE absences_workperiod_recover_request 
393
		    SET id_right='.$babDB->quote($id_right).' 
394
		    WHERE id='.$babDB->quote($this->id)
395
		);
396
	}
397
	
398
	public function getTitle()
399
	{
400
	    if (isset($this->todelete) && $this->todelete) {
401
	        return absences_translate('worked period entitling recovery to delete');
402
	    }
403
	    
404
		return absences_translate('worked period entitling recovery');
405
	}
406
	
407
	
408 View Code Duplication
	public function getNotifyFields()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
409
	{
410
		return array(
411
			absences_translate('From') 	=> bab_shortDate(bab_mktime($this->date_begin)),
412
			absences_translate('Until')	=> bab_shortDate(bab_mktime($this->date_end)),
413
			absences_translate('Quantity') 	=> absences_quantity($this->quantity, $this->quantity_unit)
414
		);
415
	}
416
	
417
	
418
	
419 View Code Duplication
	public function getYear()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
420
	{
421
		$year = (int) substr($this->date_begin, 0, 4);
422
	
423
		if (0 === $year)
424
		{
425
			return null;
426
		}
427
	
428
		return $year;
429
	}
430
	
431
	
432 View Code Duplication
	public function getArchiveYear()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
433
	{
434
		require_once $GLOBALS['babInstallPath'].'utilit/dateTime.php';
435
		$year = (int) substr($this->date_begin, 0, 4);
436
		
437
		if (0 === $year)
438
		{
439
			return null;
440
		}
441
		
442
		$day = absences_getVacationOption('archivage_day');
443
		$month = absences_getVacationOption('archivage_month');
444
		
445
		$currentYear = new BAB_DateTime($year, $month, $day);
446
		if($this->date_begin < $currentYear->getIsoDate()){
447
			$year = $year-1;
448
		}
449
		
450
		return $year;
451
	}
452
	
453
	
454 View Code Duplication
	public function archive()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
455
	{
456
		global $babDB;
457
	
458
		$babDB->db_query("
459
			UPDATE absences_workperiod_recover_request 
460
			SET
461
				archived=".$babDB->quote(1)."
462
			WHERE
463
				id=".$babDB->quote($this->id)."
464
		");
465
	}
466
	
467
	
468
	
469 View Code Duplication
	public function setNotified()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
470
	{
471
		global $babDB;
472
	
473
		$babDB->db_query("
474
			UPDATE absences_workperiod_recover_request
475
			SET
476
				appr_notified=".$babDB->quote(1)."
477
			WHERE
478
				id=".$babDB->quote($this->id)."
479
				");
480
	}
481
	
482
	
483
	public function getManagerEditUrl()
484
	{
485
		$addon = bab_getAddonInfosInstance('absences');
486
		return $addon->getUrl().'vacadmwd&idx=edit&id='.$this->id;
487
	}
488
	
489
	public function getManagerDeleteUrl()
490
	{
491
		$addon = bab_getAddonInfosInstance('absences');
492
		return $addon->getUrl().'vacadmwd&idx=delete&id='.$this->id;
493
	}
494
	
495
	
496
	
497
	/**
498
	 * @return string
499
	 */
500 View Code Duplication
	public function getEditUrl($rfrom, $ide = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
501
	{
502
		$url = absences_addon()->getUrl()."vacuser&idx=workperiod&id=".$this->id;
503
	
504
		if (isset($rfrom))
505
		{
506
			$url .= '&rfrom='.$rfrom;
507
		}
508
	
509
		if (isset($ide))
510
		{
511
			$url .= '&ide='.$ide;
512
		}
513
	
514
		return $url;
515
	}
516
	
517
	
518
	
519
	
520
	public function getManagerFrame()
521
	{
522
		$W = bab_Widgets();
523
	
524
		return $W->Link($W->Icon(absences_translate('Worked day entitling recovery'), Func_Icons::ACTIONS_VIEW_CALENDAR_WORKWEEK), absences_addon()->getUrl()."vacadmwd&idx=edit&id=".$this->id );
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $W->Link($W->Icon...edit&id=' . $this->id); (Widget_Link) is incompatible with the return type declared by the abstract method absences_Request::getManagerFrame of type Widget_Frame.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
525
	}
526
	
527
	
528
	/**
529
	 * Get request card frame to display in requests list
530
	 * @param bool 			$display_username	Affiche le nom du demandeur dans la card frame ou non, utile pour les listes contenant plusieurs demandeurs possibles
531
	 * @param int			$rfrom				si les demandes de la liste sont modifiee par un gestionnaire ou gestionnaire delegue
532
 	 * @param int			$ide				id entite de l'organigramme >0 si gestionnaire delegue seulement
533
	 * @return Widget_Frame
534
	 */
535
	public function getCardFrame($display_username, $rfrom, $ide)
536
	{
537
		bab_functionality::includeOriginal('Icons');
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class bab_functionality as the method includeOriginal() does only exist in the following sub-classes of bab_functionality: Func_Archive, Func_Archive_Zip, Func_Archive_Zip_ZipArchive, Func_Archive_Zip_Zlib, Func_CalendarBackend, Func_CalendarBackend_Ovi, Func_ContextActions, Func_ContextActions_Article, Func_ContextActions_ArticleTopic, Func_Home, Func_Home_Ovidentia, Func_Icons, Func_Icons_Default, Func_Ovml, Func_Ovml_Container, Func_Ovml_Container_Addon, Func_Ovml_Container_Article, Func_Ovml_Container_ArticleCategories, Func_Ovml_Container_ArticleCategory, Func_Ovml_Container_ArticleCategoryNext, Func_Ovml_Container_ArticleCategoryPrevious, Func_Ovml_Container_ArticleFiles, Func_Ovml_Container_ArticleNext, Func_Ovml_Container_ArticlePrevious, Func_Ovml_Container_ArticleTopic, Func_Ovml_Container_ArticleTopicNext, Func_Ovml_Container_ArticleTopicPrevious, Func_Ovml_Container_ArticleTopics, Func_Ovml_Container_Articles, Func_Ovml_Container_ArticlesHomePages, Func_Ovml_Container_CalendarCategories, Func_Ovml_Container_CalendarEventDomains, Func_Ovml_Container_CalendarEvents, Func_Ovml_Container_CalendarGroupEvents, Func_Ovml_Container_CalendarResourceEvents, Func_Ovml_Container_CalendarUserEvents, Func_Ovml_Container_Calendars, Func_Ovml_Container_DbDirectories, Func_Ovml_Container_DbDirectory, Func_Ovml_Container_DbDirectoryAcl, Func_Ovml_Container_DbDirectoryEntry, Func_Ovml_Container_DbDirectoryEntryFields, Func_Ovml_Container_DbDirectoryFields, Func_Ovml_Container_DbDirectoryMemberFields, Func_Ovml_Container_DbDirectoryMembers, Func_Ovml_Container_Delegation, Func_Ovml_Container_DelegationAdministrators, Func_Ovml_Container_DelegationItems, Func_Ovml_Container_DelegationManaged, Func_Ovml_Container_Delegations, Func_Ovml_Container_DelegationsCategories, Func_Ovml_Container_DelegationsCategory, Func_Ovml_Container_DelegationsManaged, Func_Ovml_Container_Faq, Func_Ovml_Container_FaqNext, Func_Ovml_Container_FaqPrevious, Func_Ovml_Container_FaqQuestion, Func_Ovml_Container_FaqQuestionNext, Func_Ovml_Container_FaqQuestionPrevious, Func_Ovml_Container_FaqQuestions, Func_Ovml_Container_FaqSubCategories, Func_Ovml_Container_FaqSubCategory, Func_Ovml_Container_Faqs, Func_Ovml_Container_File, Func_Ovml_Container_FileFields, Func_Ovml_Container_FileNext, Func_Ovml_Container_FilePrevious, Func_Ovml_Container_Files, Func_Ovml_Container_Folder, Func_Ovml_Container_FolderNext, Func_Ovml_Container_FolderPrevious, Func_Ovml_Container_Folders, Func_Ovml_Container_Forum, Func_Ovml_Container_ForumNext, Func_Ovml_Container_ForumPrevious, Func_Ovml_Container_Forums, Func_Ovml_Container_IfEqual, Func_Ovml_Container_IfGreaterThan, Func_Ovml_Container_IfGreaterThanOrEqual, Func_Ovml_Container_IfIsSet, Func_Ovml_Container_IfLessThan, Func_Ovml_Container_IfLessThanOrEqual, Func_Ovml_Container_IfNotEqual, Func_Ovml_Container_IfNotIsSet, Func_Ovml_Container_IfUserMemberOfGroups, Func_Ovml_Container_Multipages, Func_Ovml_Container_ObjectsInfo, Func_Ovml_Container_OrgPathToEntity, Func_Ovml_Container_OrgUserEntities, Func_Ovml_Container_OvmlArray, Func_Ovml_Container_OvmlArrayFields, Func_Ovml_Container_OvmlSoap, Func_Ovml_Container_ParentsArticleCategory, Func_Ovml_Container_Post, Func_Ovml_Container_PostFiles, Func_Ovml_Container_RecentArticles, Func_Ovml_Container_RecentComments, Func_Ovml_Container_RecentFaqQuestions, Func_Ovml_Container_RecentFiles, Func_Ovml_Container_RecentPosts, Func_Ovml_Container_RecentThreads, Func_Ovml_Container_SitemapCustomNode, Func_Ovml_Container_SitemapEntries, Func_Ovml_Container_SitemapEntry, Func_Ovml_Container_SitemapPath, Func_Ovml_Container_Soap, Func_Ovml_Container_SubFolders, Func_Ovml_Container_Tags, Func_Ovml_Container_Thread, Func_Ovml_Container_TmProjects, Func_Ovml_Container_TmSpaces, Func_Ovml_Container_TmTaskFields, Func_Ovml_Container_TmTasks, Func_Ovml_Container_WaitingArticles, Func_Ovml_Container_WaitingComments, Func_Ovml_Container_WaitingFiles, Func_Ovml_Container_WaitingPosts, Func_Ovml_Function, Func_Ovml_Function_AOAddition, Func_Ovml_Function_AODivision, Func_Ovml_Function_AOModulus, Func_Ovml_Function_AOMultiplication, Func_Ovml_Function_AOSubtraction, Func_Ovml_Function_AddStyleSheet, Func_Ovml_Function_Addon, Func_Ovml_Function_Ajax, Func_Ovml_Function_ArticleTree, Func_Ovml_Function_CurrentNode, Func_Ovml_Function_FileTree, Func_Ovml_Function_Get, Func_Ovml_Function_GetCookie, Func_Ovml_Function_GetCsrfProtectToken, Func_Ovml_Function_GetCurrentAdmGroup, Func_Ovml_Function_GetLanguage, Func_Ovml_Function_GetPageTitle, Func_Ovml_Function_GetPath, Func_Ovml_Function_GetSelectedSkinPath, Func_Ovml_Function_GetSessionVar, Func_Ovml_Function_GetVar, Func_Ovml_Function_Header, Func_Ovml_Function_IfNotIsSet, Func_Ovml_Function_Include, Func_Ovml_Function_NextArticle, Func_Ovml_Function_Post, Func_Ovml_Function_PreviousArticle, Func_Ovml_Function_PreviousOrNextArticle, Func_Ovml_Function_PutArray, Func_Ovml_Function_PutSoapArray, Func_Ovml_Function_PutVar, Func_Ovml_Function_Recurse, Func_Ovml_Function_Request, Func_Ovml_Function_SetCookie, Func_Ovml_Function_SetSessionVar, Func_Ovml_Function_SitemapCustomNodeId, Func_Ovml_Function_SitemapMenu, Func_Ovml_Function_SitemapPosition, Func_Ovml_Function_SitemapUrl, Func_Ovml_Function_Translate, Func_Ovml_Function_UrlContent, Func_Ovml_Function_WebStat, Func_PortalAuthentication, Func_PortalAuthentication_AuthOvidentia, Func_PwdComplexity, Func_PwdComplexity_DefaultPortal, Func_SearchUi, Func_SitemapDynamicNode, Func_SitemapDynamicNode_Topic, Func_UserEditor, Func_WorkingHours, Func_WorkingHours_Ovidentia, Ovml_Container_Sitemap, bab_ArithmeticOperator, bab_Ovml_Container_Operator, bab_rgp. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
538
		$W = bab_Widgets();
539
		$layout = $W->HBoxLayout()->setHorizontalSpacing(2,'em')->addClass('widget-full-width');
540
		$frame = $W->Frame(null, $layout);
541
		$frame->addClass(Func_Icons::ICON_LEFT_16);
542
543
		$layout->addItem($col1 = $W->VBoxLayout()->setVerticalSpacing(.5,'em'));
544
		$layout->addItem($col2 = $W->VBoxLayout()->setVerticalSpacing(.5,'em'));
545
		$layout->addItem($col3 = $W->VBoxLayout()->setVerticalSpacing(.5,'em'));
546
		
547
		
548
		$col1->addItem($W->Link($W->Icon(absences_translate('Worked day entitling recovery'), Func_Icons::ACTIONS_VIEW_CALENDAR_WORKWEEK), absences_addon()->getUrl()."vacuser&idx=view_wp_recovery&id=".$this->id));
549
		$col1->setCanvasOptions($col1->Options()->width(25,'em'));
0 ignored issues
show
Bug introduced by
It seems like $col1->Options()->width(25, 'em') targeting Widget_CanvasOptions::width() can also be of type double; however, Widget_Item::setCanvasOptions() does only seem to accept object<Widget_CanvasOptions>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
550
		$col2->setCanvasOptions($col1->Options()->width(25,'em'));
0 ignored issues
show
Bug introduced by
It seems like $col1->Options()->width(25, 'em') targeting Widget_CanvasOptions::width() can also be of type double; however, Widget_Item::setCanvasOptions() does only seem to accept object<Widget_CanvasOptions>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
551
		$layout->addItem($col3 = $W->VBoxLayout()->setVerticalSpacing(.5,'em'));
552
		$col2->setSizePolicy(Widget_SizePolicy::MAXIMUM);
553
		
554
		$col1->addItem($this->getStatusIcon());
555
	
556
		$col2->addItem($W->Title(absences_DateTimePeriod($this->date_begin, $this->date_end), 5));
557
		
558
		if ($display_username)
559
		{
560
			$col2->addItem($this->labelledValue(absences_translate('Owner'), $this->getUserName()));
561
		}
562
	
563
		$type = $this->getType();
564
		if ($type && $type->getRow())
565
		{
566
			$col2->addItem($this->labelledValue(absences_translate('Type'), $type->name));
0 ignored issues
show
Documentation introduced by
The property name does not exist on object<absences_WorkperiodType>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
567
		}
568
		
569
		
570 View Code Duplication
		if ($this->canModify())
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
571
		{
572
			$col3->addItem($W->Link($W->Icon(absences_translate('Modify'), Func_Icons::ACTIONS_DOCUMENT_EDIT), $this->getEditUrl($rfrom, $ide)));
573
		}
574
		
575
		if ($this->canDelete())
576
		{
577
			$urldelete = absences_addon()->getUrl()."vacuser&idx=delete&id_recovery=".$this->id;
578
			$col3->addItem($W->Link($W->Icon(absences_translate('Delete'), Func_Icons::ACTIONS_EDIT_DELETE), $urldelete));
579
		}
580
	
581
		$frame->setTitle(sprintf(absences_translate('Created the %s'), bab_shortDate(bab_mktime($this->createdOn()))));
582
	
583
		return $frame;
584
	}
585
	
586
	
587
	
588
	/**
589
	 * Delete request
590
	 */
591
	public function delete()
592
	{
593
	    require_once $GLOBALS['babInstallPath'].'utilit/dateTime.php';
594
	    
595
	    $date_begin = BAB_DateTime::fromIsoDateTime($this->date_begin);
596
	    $date_end = BAB_DateTime::fromIsoDateTime($this->date_end);
597
	    
598
		parent::delete();
599
	
600
		global $babDB;
601
		$babDB->db_query("delete from absences_workperiod_recover_request where id=".$babDB->quote($this->id));
602
		
603
		$this->addMovement(
604
		    sprintf(
605
		        absences_translate('The workperiod recover request from the %s to the %s has been deleted'),
606
		        $date_begin->shortFormat(true),
607
		        $date_end->shortFormat(true)
608
		    )
609
		);
610
	}
611
	
612
	
613
	/**
614
	 * Test form validity
615
	 * 
616
	 * @throws Exception
617
	 * 
618
	 * @return bool
619
	 */
620
	public static function checkForm(Array $workperiod, absences_WorkperiodRecoverRequest $wd = null)
621
	{
622
		// il ne doit pas exister de periode de conges sur la meme periode
623
		// TODO la periode ne doit pas etre travaillee ??
624
		// il ne doit pas deja exister de periode travaillee donnant droit a recuperation
625
		
626
		require_once dirname(__FILE__).'/workperiod_type.class.php';
627
		require_once $GLOBALS['babInstallPath'].'utilit/wfincl.php';
628
		require_once $GLOBALS['babInstallPath'].'utilit/dateTime.php';
629
		
630
		
631
		if (isset($wd))
632
		{
633
			$id_user = $wd->id_user;
634
		} else {
635
			$id_user = bab_getUserId();
636
		}
637
		
638
		
639
		global $babDB;
640
		$W = bab_Widgets();
641
		$datePicker = $W->DatePicker();
642
		
643
		$datebegin = $datePicker->getISODate($workperiod['datebegin']);
644
		$dateend = $datePicker->getISODate($workperiod['dateend']);
645
		
646
		if ('0000-00-00' === $datebegin || '0000-00-00' === $dateend)
647
		{
648
			throw new Exception(absences_translate('The begin and end dates are mandatory'));
649
		}
650
		
651
		if (!$datebegin || !$dateend)
0 ignored issues
show
Bug Best Practice introduced by
The expression $datebegin of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression $dateend of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
652
		{
653
			throw new Exception(absences_translate('Begin and end date are not correct'));
654
		}
655
		
656
		$begin = $datebegin.' '.$workperiod['hourbegin'];
657
		$end = $dateend.' '.$workperiod['hourend'];
658
		
659
		if ($begin >= $end)
660
		{
661
			throw new Exception(absences_translate('Start date must be prior to the end date'));
662
		}
663
		
664
		
665
		$delay_recovery = absences_getVacationOption('delay_recovery');
666
		$delay = BAB_DateTime::now();
667
		if ($delay_recovery) {
668
		    // 1 is added for the last 24H in the same day
669
		  $delay->add(1 + $delay_recovery, BAB_DATETIME_DAY);
670
		}
671
		if ($end > $delay->getIsoDateTime())
672
		{
673
		    if ($delay_recovery) {
674
		        throw new Exception(sprintf(absences_translate('The request dates must be in the next %d days'), $delay_recovery));
675
		    } else {
676
			    throw new Exception(absences_translate('The request dates must be over'));
677
		    }
678
		}
679
		
680
		
681
		
682
		$res = $babDB->db_query('SELECT * FROM absences_entries WHERE
683
				id_user='.$babDB->quote($id_user).'
684
				AND !(date_begin > '.$babDB->quote($end).' OR date_end < '.$babDB->quote($begin).')'
685
		);
686
		
687
		if (0 != $babDB->db_num_rows($res))
688
		{
689
			throw new Exception(absences_translate('A vacation request already exist on this period'));
690
		}
691
		
692
		
693
		$query = 'SELECT * FROM absences_workperiod_recover_request WHERE
694
				id_user='.$babDB->quote($id_user).'
695
				AND !(date_begin > '.$babDB->quote($end).' OR date_end < '.$babDB->quote($begin).')
696
				AND status<>'.$babDB->quote('N');
697
		
698
		if (isset($wd))
699
		{
700
			$query .= ' AND id<>'.$babDB->quote($wd->id); 
701
		}
702
		
703
		$res = $babDB->db_query($query);
704
		
705
		if (0 != $babDB->db_num_rows($res))
706
		{
707
			throw new Exception(absences_translate('A workperiod recover request already exist on this period'));
708
		}
709
		
710
		if (!isset($workperiod['id_type']))
711
		{
712
			throw new Exception(absences_translate('The type is mandatory'));
713
		}
714
		
715
		$type = absences_WorkperiodType::getFromId($workperiod['id_type']);
716
		
717
		if (!$type->getRow())
718
		{
719
			throw new Exception(absences_translate('The type is mandatory'));
720
		}
721
		
722
		
723
		return true;
724
	}
725
}
726
727
728
729
730
731
732
733
/**
734
 * Vacation requests
735
 *
736
 */
737
class absences_WorkperiodRecoverRequestIterator extends absences_Iterator
738
{
739
740
	/**
741
	 *
742
	 * @var array
743
	 */
744
	public $users;
745
	
746
	
747
	/**
748
	 * Organization filter
749
	 * @var int
750
	 */
751
	public $organization;
752
	
753
	
754
	/**
755
	 * Filtrer les demandes necessitant ou pas un email aux approbateurs
756
	 * @var int
757
	 */
758
	public $appr_notified;
759
	
760
	
761
	/**
762
	 * Filtrer les demandes avec unes instance d'approbation
763
	 * @var bool
764
	 */
765
	public $idfai_set;
766
	
767
	/**
768
	 * 
769
	 * @var string
770
	 */
771
	public $status;
772
	
773
	/**
774
	 * Search all request created before this date time
775
	 * @var string
776
	 */
777
	public $createdOn;
778
	
779
	
780
	/**
781
	 * Search all request modified before this date
782
	 * @var string
783
	 */
784
	public $modifiedOn;
785
	
786
	
787
	/**
788
	 * Filtrer les demandes par date de debut superieur
789
	 * @var int
790
	 */
791
	public $startFrom;
792
	
793
	/**
794
	 * Filtrer les demandes par date de debut inferieur
795
	 * @var int
796
	 */
797
	public $startTo;
798
	
799
	/**
800
	 * Filtrer les demandes par annee
801
	 * @var int
802
	 */
803
	public $year;
804
	
805
	
806
	/**
807
	 * Filtrer les demandes par statut d'archivage
808
	 * @var int
809
	 */
810
	public $archived = 0;
811
812
813
	public function getObject($data)
814
	{
815
816
		$entry = new absences_WorkperiodRecoverRequest;
817
		$entry->setRow($data);
818
		return $entry;
819
820
	}
821
822
823
824
	public function executeQuery()
825
	{
826
		if(is_null($this->_oResult))
827
		{
828
			global $babDB;
829
			$req = 'SELECT r.*
830
			FROM
831
				absences_workperiod_recover_request r 
832
			         LEFT JOIN absences_personnel p ON p.id_user=r.id_user 
833
			';
834
835
836
			$where = array();
837
838
			if (isset($this->users))
839
			{
840
				$where[] = 'r.id_user IN('.$babDB->quote($this->users).')';
841
			}
842
			
843
			if (isset($this->organization))
844
			{
845
			    $where[] = 'p.id_organization='.$babDB->quote($this->organization);
846
			}
847
			
848
			if (isset($this->appr_notified))
849
			{
850
				$where[] = 'r.appr_notified='.$babDB->quote($this->appr_notified);
851
			}
852
			
853
			if (isset($this->idfai_set) && $this->idfai_set)
854
			{
855
				$where[] = 'r.idfai>'.$babDB->quote(0);
856
			}
857
			
858
			if (isset($this->status))
859
			{
860
				$where[] = 'r.status='.$babDB->quote($this->status);
861
			}
862
			
863
			if (isset($this->createdOn))
864
			{
865
				$where[] = 'r.createdOn<='.$babDB->quote($this->createdOn);
866
			}
867
			
868
			if (isset($this->modifiedOn))
869
			{
870
				$where[] = 'r.modifiedOn<='.$babDB->quote($this->modifiedOn);
871
			}
872
			
873
			if (isset($this->year))
874
			{
875
				$where[] = 'YEAR(r.date_begin)='.$babDB->quote($this->year);
876
			}
877
			
878
			if (isset($this->startTo) && $this->startTo != '0000-00-00')
879
			{
880
				$where[] = 'r.date_begin <='.$babDB->quote($this->startTo);
881
			}
882
			
883
			if (isset($this->startFrom) && $this->startFrom != '0000-00-00')
884
			{
885
				$where[] = 'r.date_begin >='.$babDB->quote($this->startFrom);
886
			}
887
			
888
			if (isset($this->archived))
889
			{
890
				$where[] = 'r.archived='.$babDB->quote($this->archived);
891
			}
892
893
			if ($where)
0 ignored issues
show
Bug Best Practice introduced by
The expression $where of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
894
			{
895
				$req .= ' WHERE '.implode(' AND ', $where);
896
			}
897
			
898
			$this->setMySqlResult($this->getDataBaseAdapter()->db_query($req));
899
		}
900
	}
901
}
902