absences_AgentCet   C
last analyzed

Complexity

Total Complexity 56

Size/Duplication

Total Lines 551
Duplicated Lines 20.51 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
dl 113
loc 551
rs 6.5957
c 0
b 0
f 0
wmc 56
lcom 1
cbo 6

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B updateRights() 0 36 5
A getRightsIterator() 0 18 2
A getUseRight() 0 14 3
A getQuantity() 15 15 3
A getConfirmedQuantity() 15 15 3
A getAvailableQuantity() 0 15 3
B getDepositAgentRight() 0 48 5
A getDepositRight() 0 16 3
A getQuantityUnit() 0 11 2
A getTotalDeposits() 0 18 1
A getYearlyDeposits() 0 19 1
A getYearlyMaxDeposit() 22 22 3
B getMaxDepositTotal() 25 25 3
A canAdd() 0 7 1
A canUse() 0 7 1
D testDepositQuantity() 36 103 16

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like absences_AgentCet often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use absences_AgentCet, and based on these observations, apply Extract Interface, too.

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
26
27
require_once dirname(__FILE__).'/right.class.php';
28
29
class absences_AgentCet
30
{
31
	/**
32
	 * 
33
	 * @var absences_Agent
34
	 */
35
	private $agent;
36
	
37
	/**
38
	 * 
39
	 * @var absences_Right
40
	 */
41
	private $depositRight;
42
	
43
	/**
44
	 *
45
	 * @var absences_AgentRight
46
	 */
47
	private $depositAgentRight;
48
	
49
	
50
	private $rights_withDeposits = null;
51
	
52
	/**
53
	 * 
54
	 * @var array
55
	 */
56
	private $rights_withAvailable = null;
57
	
58
	
59
	public function __construct(absences_Agent $agent)
60
	{
61
		$this->agent = $agent;
62
	}
63
	
64
	/**
65
	 * Liste des droits contenant de l'epargne
66
	 * @return multitype:absences_AgentRight
0 ignored issues
show
Documentation introduced by
The doc-type multitype:absences_AgentRight could not be parsed: Unknown type name "multitype:absences_AgentRight" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
67
	 */
68
	private function updateRights()
69
	{
70
		
71
		$this->rights_withDeposits = array();
72
		$this->rights_withAvailable = array();
73
		
74
		$I = $this->agent->getAgentRightUserIterator();
75
		$I->setKind(absences_Right::CET);
76
77
		foreach($I as $agentRight)
78
		{
79
			/*@var $agentRight absences_AgentRight */
80
			
81
			
82
			if (0 !== (int) round(100 * $agentRight->getQuantity()))
83
			{
84
				$this->rights_withDeposits[] = $agentRight;
85
			}
86
			
87
			
88
89
			if (0 !== (int) round(100 * $agentRight->getAvailableQuantity()))
90
			{
91
				$begin = $agentRight->getDateBeginValid();
92
				if (isset($this->rights_withAvailable[$begin]))
93
				{
94
					$this->rights_withAvailable[] = $agentRight;
95
				} else {
96
					$this->rights_withAvailable[$begin] = $agentRight;
97
				}
98
			}
99
		}
100
		
101
		ksort($this->rights_withAvailable);
102
	
103
	}
104
105
	
106
	/**
107
	 * Get user agent rights with flag use_in_cet
108
	 * liste des droits accessibles par l'utilisateurs, qui peuvent etres utilises par le CET
109
	 * 
110
	 * @return absences_AgentRightUserIterator
111
	 */
112
	public function getRightsIterator()
113
	{
114
		$deposit = $this->getDepositRight(false);
115
116
		require_once dirname(__FILE__).'/agent_right.class.php';
117
		
118
		$I = new absences_AgentRightUserIterator;
119
		$I->setAgent($this->agent);
120
		$I->setUseInCet(true);
121
		if (isset($deposit))
122
		{
123
		    // si on a access a un droit CET pour le depot
124
		    // le droits remontes comme source compatibles 
125
		    // sont obligatoirement dans la meme unite
126
			$I->setQuantityUnit($deposit->quantity_unit);
127
		}
128
		return $I;
129
	}
130
	
131
	
132
	
133
	
134
	/**
135
	 * Premier droit a utiliser pour les retraits, peut ne pas etre disponible pour les depots
136
	 * utiliser toujours le droit dont la date de debut de disponiblite est la plus ancienne pour l'agent, ignorer les droits soldes
137
	 * 
138
	 * @throws absences_CetException
139
	 * @return absences_AgentRight
140
	 */
141
	public function getUseRight()
142
	{
143
		if (!isset($this->rights_withAvailable))
144
		{
145
			$this->updateRights();
146
		}
147
		
148
		if (empty($this->rights_withAvailable))
149
		{
150
			return null;
151
		}
152
		
153
		return reset($this->rights_withAvailable);
154
	}
155
	
156
	
157
	
158
	
159
	
160
	
161
	
162
	
163
	/**
164
	 * somme des jours epargnes sur les CET ouverts
165
	 * @return float
166
	 */
167 View Code Duplication
	public function getQuantity()
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...
168
	{
169
		if (!isset($this->rights_withDeposits))
170
		{
171
			$this->updateRights();
172
		}
173
		
174
		$total = 0.0;
175
		foreach($this->rights_withDeposits as $agentRight)
0 ignored issues
show
Bug introduced by
The expression $this->rights_withDeposits of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
176
		{
177
			$total += $agentRight->getQuantity();
178
		}
179
	
180
		return $total;
181
	}
182
	
183
	
184
	
185
	/**
186
	 * somme des jours utilises confirmes sur les CET ouverts
187
	 * @return float
188
	 */
189 View Code Duplication
	public function getConfirmedQuantity()
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...
190
	{
191
		if (!isset($this->rights_withDeposits))
192
		{
193
			$this->updateRights();
194
		}
195
		
196
		$total = 0.0;
197
		foreach($this->rights_withDeposits as $agentRight)
0 ignored issues
show
Bug introduced by
The expression $this->rights_withDeposits of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
198
		{
199
			$total += $agentRight->getConfirmedQuantity();
200
		}
201
		
202
		return $total;
203
	}
204
	
205
	
206
	/**
207
	 * Get number of days in CET
208
	 * somme des jours epargnes - les jours utilises sur les CET ouverts
209
	 * @return float
210
	 */
211
	public function getAvailableQuantity()
212
	{
213
		if (!isset($this->rights_withAvailable))
214
		{
215
			$this->updateRights();
216
		}
217
		
218
		$total = 0.0;
219
		foreach($this->rights_withAvailable as $agentRight)
0 ignored issues
show
Bug introduced by
The expression $this->rights_withAvailable of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
220
		{
221
			$total += $agentRight->getAvailableQuantity();
222
		}
223
		
224
		return $total;
225
	}
226
	
227
	
228
	
229
	
230
	/**
231
	 * le droit a utiliser pour les depots, peut ne pas etre accessible a l'utilsation
232
	 * Deposer sur le droit avec la date de fin de depot la plus recente
233
	 * 
234
	 * @param bool $onlyActive
235
	 * 
236
	 * @return absences_AgentRight
237
	 */
238
	public function getDepositAgentRight($onlyActive)
239
	{
240
241
		require_once dirname(__FILE__).'/agent_right.class.php';
242
		global $babDB;
243
		
244
		$query = "SELECT u.* FROM 
245
			absences_users_rights u,
246
			absences_rights r,
247
			absences_rights_cet c
248
		WHERE 
249
			u.id_right = r.id 
250
			AND u.id_user=".$babDB->quote($this->agent->getIdUser())."
251
	    ";
252
		
253
		$currentAgent = absences_Agent::getCurrentUser();
254
		
255
		
256
		if ($onlyActive && !$currentAgent->isManager()) {
257
		    $query .= " AND r.active='Y' ";
258
		}
259
		
260
		$query .= "
261
			AND r.kind=".$babDB->quote(absences_Right::CET)." 
262
			AND c.id_right=r.id 
263
			AND (c.saving_begin='0000-00-00' OR c.saving_begin<=CURDATE()) 
264
			AND (c.saving_end='0000-00-00' OR c.saving_end>=CURDATE()) 
265
			AND (u.saving_begin='0000-00-00' OR u.saving_begin<=CURDATE()) 
266
			AND (u.saving_end='0000-00-00' OR u.saving_end>=CURDATE()) 
267
		 ORDER BY c.saving_end DESC ";
268
		
269
270
		$res = $babDB->db_query($query);
271
		
272
		if (0 === $babDB->db_num_rows($res)) {
273
			return null;
274
		}
275
		
276
		if (1 !== $babDB->db_num_rows($res)) {
277
		    throw new Exception(absences_translate('There is more than one time saving account associated to user'));
278
		}
279
		
280
		$row = $babDB->db_fetch_assoc($res);
281
		$depositAgentRight = new absences_AgentRight;
282
		$depositAgentRight->setRow($row);
283
		
284
		return $depositAgentRight;
285
	}
286
	
287
	
288
	/**
289
	 * Droit utilise pour les depot dans le CET
290
	 * @return absences_Right
291
	 */
292
	public function getDepositRight($onlyActive = true)
293
	{
294
		if (!isset($this->depositRight))
295
		{
296
			$agent_right = $this->getDepositAgentRight($onlyActive);
297
			
298
			if (!isset($agent_right))
299
			{
300
				return null;
301
			}
302
			
303
			$this->depositRight = $agent_right->getRight();
304
		}
305
		
306
		return $this->depositRight;
307
	}
308
	
309
	
310
	
311
	/**
312
	 * 
313
	 * @return string
314
	 */
315
	public function getQuantityUnit()
316
	{
317
		$right = $this->getDepositRight(false);
318
		
319
		if (!$right)
320
		{
321
			return null;
322
		}
323
		
324
		return $right->quantity_unit;
325
	}
326
	
327
	
328
	/**
329
	 * Total des depot sur le CET
330
	 * @return float
331
	 */
332
	public function getTotalDeposits()
333
	{
334
		global $babDB;
335
	
336
		$agentRight = $this->getDepositAgentRight(false);
337
		$id_user = $this->agent->getIdUser();
338
	
339
		$res = $babDB->db_query('
340
				SELECT SUM(quantity) total
341
				FROM absences_cet_deposit_request
342
				WHERE
343
				id_user='.$babDB->quote($id_user).'
344
				AND id_agent_right_cet='.$babDB->quote($agentRight->id));
345
	
346
		$arr = $babDB->db_fetch_assoc($res);
347
	
348
		return (float) $arr['total'];
349
	}
350
	
351
	
352
	
353
	/**
354
	 * Total des depot dans l'annee en cours
355
	 * @return float
356
	 */
357
	public function getYearlyDeposits()
358
	{
359
		global $babDB;
360
		
361
		$agentRight = $this->getDepositAgentRight(false);
362
		$id_user = $this->agent->getIdUser();
363
		
364
		$res = $babDB->db_query('
365
			SELECT SUM(quantity) total  
366
				FROM absences_cet_deposit_request 
367
				WHERE 
368
					id_user='.$babDB->quote($id_user).' 
369
					AND id_agent_right_cet='.$babDB->quote($agentRight->id).' 
370
					AND YEAR(createdOn)='.$babDB->quote(date('Y')));
371
		
372
		$arr = $babDB->db_fetch_assoc($res);
373
		
374
		return (float) $arr['total'];
375
	}
376
	
377
	/**
378
	 * Restant a deposer avant d'atteindre le max pour l'annee
379
	 * @return number
380
	 */
381 View Code Duplication
	public function getYearlyMaxDeposit()
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...
382
	{
383
		$right = $this->getDepositRight(false);
384
		
385
		if (!isset($right))
386
		{
387
			throw new Exception(absences_translate('The applicant time saving account is not accessible'));
388
		}
389
		
390
		$rightcet = $right->getRightCet();
391
392
		$per_year = (float) $rightcet->per_year;
393
		
394
		if (0 === (int) round($per_year * 10))
395
		{
396
			// no limit set
397
			return null;
398
		}
399
		
400
		
401
		return ($per_year - $this->getYearlyDeposits()); 
402
	}
403
	
404
	
405
	/**
406
	 * Restant a deposer avant d'atteindre le plafont total
407
	 * @return number
408
	 */
409 View Code Duplication
	public function getMaxDepositTotal()
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...
410
	{
411
		$right = $this->getDepositRight(false);
412
		
413
		if (!isset($right))
414
		{
415
			throw new Exception(absences_translate('The applicant time saving account is not accessible'));
416
		}
417
		
418
		$rightcet = $right->getRightCet();
419
		
420
		$celling = (float) $rightcet->ceiling;
421
		
422
		if (0 === (int) round($celling * 10))
423
		{
424
			// no limit set
425
			return null;
426
		}
427
		
428
		return ($celling - $this->getTotalDeposits());
429
		
430
		
431
		
432
		// TODO available period deposits
433
	}
434
	
435
	
436
	/**
437
	 * Tester si il existe au moins un droit CET actif avec une periode de depot accessible
438
	 * is l'utilsateur est gestionnaire permettre l'acces aux droits desactives
439
	 * 
440
	 * @throws Exception
441
	 * 
442
	 * @return bool
443
	 */
444
	public function canAdd()
445
	{
446
	    $onlyActive = !absences_agent::getCurrentUser()->isManager();
447
	    
448
	    return (null !== $this->getDepositRight($onlyActive));
449
	    
450
	}
451
	
452
	/**
453
	 * Tester si il existe des droits utilisables
454
	 * @return bool
455
	 */
456
	public function canUse()
457
	{
458
		$I = $this->agent->getAgentRightUserIterator();
459
		$I->setKind(absences_Right::CET);
460
		
461
		return ($I->count() > 0);
462
	}
463
	
464
	
465
	
466
	/**
467
	 * Tester s'il est possible d'epargner
468
	 * @throws Exception
469
	 * 
470
	 * @param	absences_AgentRight				$agent_right		Right source
471
	 * @param	float							$quantity			Quantity to save
472
	 * @param 	absences_CetDepositRequest		$deposit			The deposit if allready created
473
	 * 
474
	 * @return bool
475
	 */
476
	public function testDepositQuantity(absences_AgentRight $agent_right, $quantity, absences_CetDepositRequest $deposit = null)
477
	{
478
		if (0 === (int) round($quantity*100))
479
		{
480
			throw new Exception(absences_translate('This quantity in not valid'));
481
		}
482
		
483
		
484
		$right = $agent_right->getRight();
485
486
		$onlyActive = !absences_agent::getCurrentUser()->isManager();
487
		$rightCet = $this->getDepositRight($onlyActive);
488
		
489
		if (!isset($rightCet))
490
		{
491
			throw new Exception(absences_translate('The applicant time saving account is not accessible'));
492
		}
493
		
494
		if ($rightCet->quantity_unit !== $right->quantity_unit)
495
		{
496
			throw new Exception(absences_translate('The quantity unit of source right must be the same as the time saving account quantity unit'));
497
		}
498
		
499
		
500
		$available = $agent_right->getCetAvailableQuantity(); // Do not allow using waiting quantity
501
		
502
		if (isset($deposit) && 'Y' !== $deposit->status)
503
		{
504
			// la quantite de la demande en cours est considere comme disponible si la demande est bien en attente
505
			$available += (float) $deposit->quantity;
506
		}
507
		
508
		$right = $agent_right->getRight();
509
		
510
		
511
		// verifier que la quantite est disponible dans le droit
512
		
513 View Code Duplication
		if ($available < $quantity)
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...
514
		{
515
			throw new Exception(sprintf(
516
					absences_translate('The requested quantity is not available in the specified right, the right %s contain only %s available'),
517
					$right->description,
518
					absences_quantity($available, $right->quantity_unit)
519
				)
520
			);
521
		}
522
		
523
		$cet_quantity = $agent_right->getCetMaxQuantity();
524 View Code Duplication
		if ($cet_quantity < $quantity)
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...
525
		{
526
			
527
			throw new Exception(sprintf(
528
					//TRANSLATORS: Vous ne pouvez deposer plus de %s de "%s" sur le compte epargne temps
529
					absences_translate('You cant deposit more than %s of "%s" one the time saving account'),
530
					$right->description,
531
					absences_quantity($cet_quantity, $right->quantity_unit)
532
				)
533
			);
534
		}
535
		
536
		
537
		
538
		
539
		// verifier que la quantite peut etre recue par le CET
540
		
541
		$max = $this->getMaxDepositTotal();
542
		
543
		if (isset($deposit) && 'Y' !== $deposit->status)
544
		{
545
			// la quantite de la demande en cours est considere comme disponible si la demande est bien en attente
546
			$max += (float) $deposit->quantity;
547
		}
548
		
549 View Code Duplication
		if ($max > 0 && $quantity > $max)
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...
550
		{
551
			throw new Exception(sprintf(
552
					absences_translate('The time saving account does not allow more than %s to reach the ceilling'),
553
					absences_quantity($max, $right->quantity_unit)
554
				)
555
			);
556
		}
557
		
558
		$max = $this->getYearlyMaxDeposit();
559
		
560
		
561
		if (isset($deposit) && 'Y' !== $deposit->status)
562
		{
563
			// la quantite de la demande en cours est considere comme disponible si la demande est bien en attente
564
			$max += (float) $deposit->quantity;
565
		}
566
		
567 View Code Duplication
		if ($max > 0 && $quantity > $max)
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...
568
		{
569
			throw new Exception(sprintf(
570
					absences_translate('The time saving account does not allow more than %s to reach the yearly maximum deposit'),
571
					absences_quantity($max, $right->quantity_unit)
572
				)
573
			);
574
		}
575
		
576
		
577
		return true;
578
	}
579
}
580
581
582
583
584
class absences_CetException extends Exception {
585
	
586
}