Completed
Push — master ( 7f1093...c1fa0c )
by Paul
04:04
created

absences_ExportEntry::getEntryRow()   C

Complexity

Conditions 10
Paths 42

Size

Total Lines 70
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 10.4027
Metric Value
dl 0
loc 70
ccs 37
cts 44
cp 0.8409
rs 5.9999
cc 10
eloc 39
nc 42
nop 1
crap 10.4027

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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
require_once dirname(__FILE__).'/entry.class.php';
26
require_once dirname(__FILE__).'/agent.class.php';
27
require_once dirname(__FILE__).'/organization.class.php';
28
29
class absences_ExportEntry
30
{
31
    /**
32
     * @var BAB_DateTime
33
     */
34
    protected $dateb;
35
36
    /**
37
     * @var BAB_DateTime
38
     */
39
    protected $datee;
40
41
    /**
42
     * @var absences_EntryIterator
43
     */
44
    private $iterator;
45
46
    /**
47
     * @var string
48
     */
49
    private $separ;
50
51
    /**
52
     * @var string
53
     */
54
    private $sepdec;
55
56
    /**
57
     * @var array
58
     */
59
    private $users_with_requests = array();
60
61
    /**
62
     * @var bool
63
     */
64
    private $users_without_requests;
65
66
    /**
67
     * @var array
68
     */
69
    private $dirfields;
70
71
72
    private $types = array();
73
74
    /**
75
     * @var int
76
     */
77
    private $organization = '';
78
79 1
    public function __construct(BAB_DateTime $dateb, BAB_DateTime $datee, $idstatus, $wsepar, $separ, $sepdec, $users_without_requests, $dirfields, $organization = '')
80
    {
81 1
        $this->dateb = $dateb;
82 1
        $this->datee = $datee;
83 1
        $this->organization = $organization;
0 ignored issues
show
Documentation Bug introduced by
The property $organization was declared of type integer, but $organization 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...
84
85 1
        $I = new absences_EntryIterator();
86 1
        $I->from = $dateb->getIsoDateTime();
87
        
88 1
        $I->to = $datee->getIsoDateTime();
89
90 1
        if($organization){
91
        	$I->organization = (int) $organization;
92
        }
93
94 1
        $status = array();
95 1
        if (in_array(0,$idstatus)) {
96 1
            $status[] = '';
97 1
        }
98
99 1
        if (in_array(1,$idstatus)) {
100 1
            $status[] = 'Y';
101 1
        }
102
103 1
        if (in_array(2,$idstatus)) {
104 1
            $status[] = 'N';
105 1
        }
106
107 1
        $I->status = $status;
108
109 1
        $this->iterator = $I;
110
111
        switch($wsepar)
112
        {
113 1
            case "1":
114 1
                $this->separ = ",";
115 1
                break;
116
            case "2":
117
                $this->separ = "\t";
118
                break;
119
            case "3":
120
                $this->separ = ";";
121
                break;
122
            default:
123
                $this->separ = $separ;
124
                if( empty($separ)) {
125
                    $this->separ = ",";
126
                }
127
                break;
128
        }
129
130 1
        $this->sepdec = $sepdec;
131
132 1
        $this->users_without_requests = (bool) $users_without_requests;
133
134 1
        $this->dirfields = $dirfields;
135 1
    }
136
137
138 1
    private function arr_csv(&$value)
139
    {
140 1
        $value = str_replace("\n"," ",$value);
141 1
        $value = str_replace('"',"'",$value);
142 1
        $value = '"'.$value.'"';
143 1
    }
144
145
146 1
    private function numberFormat($quantity)
147
    {
148 1
        return number_format($quantity, 1, $this->sepdec, '');
149
    }
150
151
152 1
    public function getHeader()
153
    {
154 1
        global $babDB;
155
        
156 1
        $line = array();
157
158 1
        if ($this->dirfields) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->dirfields 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...
159
            $ov_fields = bab_getDirEntry(BAB_REGISTERED_GROUP, BAB_DIR_ENTRY_ID_GROUP);
160
        }
161
162 1
        $line[] = absences_translate("lastname");
163 1
        $line[] = absences_translate("firstname");
164 1
        $line[] = absences_translate("Created on");
165 1
        $line[] = absences_translate("Modified on");
166 1
        foreach ($this->dirfields as $name => $dummy) {
167 1
            $line[] = $ov_fields[$name]['name'];
0 ignored issues
show
Bug introduced by
The variable $ov_fields 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...
168 1
        }
169 1
        $line[] = absences_translate("Begin date");
170 1
        $line[] = absences_translate("Begin hour");
171 1
        $line[] = absences_translate("End date");
172 1
        $line[] = absences_translate("End hour");
173 1
        $line[] = absences_translate("Status");
174 1
        $line[] = absences_translate("Total days");
175 1
        $line[] = absences_translate("Total hours");
176
177 1
        $res = $babDB->db_query("SELECT 
178
                t.id,
179
                t.name, 
180
                COUNT(rd.id) with_day,
181
                COUNT(rh.id) with_hour 
182
            FROM absences_types t 
183
                LEFT JOIN absences_rights rd ON rd.id_type=t.id AND rd.quantity_unit='D' 
184
                LEFT JOIN absences_rights rh ON rh.id_type=t.id AND rh.quantity_unit='H' 
185
            GROUP BY t.id 
186
            ORDER BY t.name 
187 1
        ");
188 1
        while ($arr = $babDB->db_fetch_assoc($res))
189
        {
190 1
            if ((bool) $arr['with_day']) {
191 1
                $line[] = $arr['name'].' '.absences_translate('days');
192 1
            }
193
            
194 1
            if ((bool) $arr['with_hour']) {
195
                $line[] = $arr['name'].' '.absences_translate('hours');
196
            }
197
            
198 1
            $this->types[] = array(
199 1
                'id'        => $arr['id'],
200 1
                'with_day'  => (bool) $arr['with_day'],
201 1
                'with_hour' => (bool) $arr['with_hour']
202 1
            );
203 1
        }
204 1
        array_walk($line, array($this, 'arr_csv'));
205
206 1
        return $line;
207
    }
208
209
210 1 View Code Duplication
    private function getAgentDirValue(absences_Agent $agent, $fieldname)
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...
211
    {
212 1
        $direntry = $agent->getDirEntry();
213
214 1
        if (isset($direntry[$fieldname]))
215 1
        {
216 1
            return $direntry[$fieldname]['value'];
217
        }
218
219
        return '';
220
    }
221
222
223
    /**
224
     * Quantity for one type
225
     * @return float
226
     */
227 1
    private function getTypeDays(absences_Entry $entry, $id_type)
228
    {
229 1
        return $entry->getPlannedDaysBetween($this->iterator->from, $this->iterator->to, $id_type);
230
    }
231
232
233
    /**
234
     * Quantity for one type
235
     * @return float
236
     */
237
    private function getTypeHours(absences_Entry $entry, $id_type)
238
    {
239
        return $entry->getPlannedHoursBetween($this->iterator->from, $this->iterator->to, $id_type);
240
    }
241
242
    /**
243
     * Entry begin timestamp
244
     *
245
     * if overlap with the end date :
246
     * First try with planned periods (in database for absences >= 2.46)
247
     * second with the current working periods (if not removed by configuration)
248
     * last with the iterator boundaries
249
     *
250
     * @return int
251
     */
252 1
    private function getBeginTs(absences_Entry $entry)
253
    {
254 1
        if ($this->iterator->from > $entry->date_begin) {
255
256
            $day = substr($this->iterator->from, 0, 10);
257
            $planned = $entry->getDayPlannedPeriods($day);
258
259 View Code Duplication
            if (0 === count($planned)) {
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...
260
                $workingPeriods = $entry->getDayWorkingPeriods($day);
261
262
                if (0 === count($workingPeriods)) {
263
                    return bab_mktime($this->iterator->from);
264
                }
265
266
                $firstPeriod = reset($workingPeriods);
267
                return $firstPeriod->ts_begin;
268
            }
269
270
            $firstperiod = reset($planned);
271
272
            return bab_mktime($firstperiod->date_begin);
273
        }
274
275 1
        return bab_mktime($entry->date_begin);
276
    }
277
278
    /**
279
     * Entry end timestamp
280
     *
281
     * if overlap with the end date :
282
     * First try with planned periods (in database for absences >= 2.46)
283
     * second with the current working periods (if not removed by configuration)
284
     * last with the iterator boundaries
285
     *
286
     * @return int
287
     */
288 1
    private function getEndTs(absences_Entry $entry)
289
    {
290 1
        if ($this->iterator->to < $entry->date_end) {
291
292
            $end = $this->datee->cloneDate();
293
            $end->less(1, BAB_DATETIME_DAY); // un jour a ete ajoute pour inclure le dernier jour dans l'iterateur
294
                                             // on enleve 1 jour pour retrouver la date saisie
295
            $day = $end->getIsoDate();
296
            $planned = $entry->getDayPlannedPeriods($day);
297
298 View Code Duplication
            if (0 === count($planned)) {
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...
299
                $workingPeriods = $entry->getDayWorkingPeriods($day);
300
301
                if (0 === count($workingPeriods)) {
302
                    return bab_mktime($this->iterator->to);
303
                }
304
305
                $lastPeriod = end($workingPeriods);
306
                return $lastPeriod->ts_end;
307
            }
308
309
            $lastperiod = end($planned);
310
311
            return bab_mktime($lastperiod->date_end);
312
        }
313
314 1
        return bab_mktime($entry->date_end);
315
    }
316
317
318
    /**
319
     *
320
     * @return array
321
     */
322 1
    public function getEntryRow(absences_Entry $entry)
323
    {
324 1
        $agent = $entry->getAgent();
325
326 1
        if (isset($agent)) {
327 1
            $this->users_with_requests[] = $agent->getIdUser();
328 1
        }
329
330 1
        $line = array();
331 1
        $line[] = $this->getAgentDirValue($agent, 'sn');
0 ignored issues
show
Bug introduced by
It seems like $agent can be null; however, getAgentDirValue() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
332 1
        $line[] = $this->getAgentDirValue($agent, 'givenname');
0 ignored issues
show
Bug introduced by
It seems like $agent can be null; however, getAgentDirValue() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
333
        
334
        
335 1
        if (empty($line[0]) && empty($line[1])) {
336
            // the user has been deleted?
337
            return null;
338
        }
339
        
340
        
341 1
        $line[] = bab_shortDate(bab_mktime($entry->createdOn), false);
342 1
        $line[] = bab_shortDate(bab_mktime($entry->modifiedOn()), false);
343
344 1
        foreach($this->dirfields as $name => $dummy)
345
        {
346
            $line[] = $this->getAgentDirValue($agent, $name);
0 ignored issues
show
Bug introduced by
It seems like $agent can be null; however, getAgentDirValue() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
347 1
        }
348
349 1
        $begin = $this->getBeginTs($entry);
350 1
        $end = $this->getEndTs($entry);
351
352 1
        $line[] = bab_shortDate($begin, false);
353 1
		$line[] = date('H:i', $begin);
354 1
		$line[] = bab_shortDate($end, false);
355 1
		$line[] = date('H:i', $end);
356 1
        $line[] = $entry->getShortStatusStr();
357
358 1
        $pos = count($line);
359 1
        $tdays = 0.0;
360 1
        $thours = 0.0;
361 1
        foreach ($this->types as $_arr) {
362
            
363 1
            $id_type = $_arr['id'];
364
            
365 1
            if ($_arr['with_day']) {
366 1
                $days = $this->getTypeDays($entry, $id_type);
367 1
                $line[] = $this->numberFormat($days);
368 1
                $tdays += $days;
369 1
            }
370
            
371 1
            if ($_arr['with_hour']) {
372
                $hours = $this->getTypeHours($entry, $id_type);
373
                $line[] = $this->numberFormat($hours);
374
                $thours += $hours;
375
            }
376
            
377 1
        }
378
        
379
        
380 1
        if (0 === (int) round(100 * $tdays) && 0 === (int) round(100 * $thours)) {
381
            return null;
382
        }
383
        
384
385 1
        array_splice($line, $pos++, 0, $this->numberFormat($tdays));
386 1
        array_splice($line, $pos++, 0, $this->numberFormat($thours));
387
388 1
        array_walk($line, array($this, 'arr_csv'));
389
390 1
        return $line;
391
    }
392
393
394
    /**
395
     * @return absences_Agent[]
396
     */
397
    private function getUsersWithoutRequests()
398
    {
399
        $I = new absences_AgentIterator();
400
        if (count($this->users_with_requests) > 0)
401
        {
402
            $I->exclude_users = $this->users_with_requests;
403
        }
404
        if($this->organization){
405
        	$Orga = absences_Organization::getById($this->organization);
406
        	$I->setOrganization($Orga);
407
        }
408
        return $I;
409
    }
410
411
412
    /**
413
     * @return array
414
     */
415 1
    public function getAgentRow(absences_Agent $agent)
416
    {
417
418 1
        $line = array();
419 1
        $line[] = $this->getAgentDirValue($agent, 'sn');
420 1
        $line[] = $this->getAgentDirValue($agent, 'givenname');
421 1
        $line[] = '';
422 1
        $line[] = '';
423 1
        foreach($this->dirfields as $name => $dummy)
424
        {
425
            $line[] = $this->getAgentDirValue($agent, $name);
426 1
        }
427
428 1
        $line[] = '';
429 1
        $line[] = '';
430 1
        $line[] = '';
431 1
        $line[] = '';
432 1
        $line[] = '';
433 1
        $line[] = 0;
434 1
        $line[] = 0;
435 1
        foreach ($this->types as $_arr) {
436 1
            if ($_arr['with_day']) {
437 1
                $line[] = 0;
438 1
            }
439
            
440 1
            if ($_arr['with_hour']) {
441
                $line[] = 0;
442
            }
443 1
        }
444
445 1
        array_walk($line, array($this, 'arr_csv'));
446
447 1
        return $line;
448
    }
449
450
451
452
    public function output()
453
    {
454
455
        header("Content-Disposition: attachment; filename=\"".absences_translate("Vacation").".csv\""."\n");
456
        header("Content-Type: text/csv"."\n");
457
458
        $header = $this->getHeader();
459
        echo implode($this->separ, $header)."\n";
460
461
        foreach ($this->iterator as $entry) {
462
            $line = $this->getEntryRow($entry);
463
            
464
            if (!isset($line)) {
465
                // the entry contain no total quantity or no directory entry
466
                continue;
467
            }
468
469
            
470
471
            echo implode($this->separ, $line)."\n";
472
        }
473
474
        if ($this->users_without_requests) {
475
            foreach ($this->getUsersWithoutRequests() as $agent) {
476
                $line = $this->getAgentRow($agent);
477
                echo implode($this->separ, $line)."\n";
478
            }
479
        }
480
481
        exit;
482
    }
483
}
484
485