Completed
Push — master ( 70a6e2...26aa15 )
by Paul
04:11
created

absences_ExportEntry::output()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 32
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 6
nop 0
dl 0
loc 32
ccs 0
cts 18
cp 0
crap 30
rs 8.439
c 0
b 0
f 0
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
    /**
43
     * @var bool
44
     */
45
    private $splittype;
46
    
47
    /**
48
     * @var absences_EntryIterator
49
     */
50
    private $iterator;
51
52
    /**
53
     * @var string
54
     */
55
    private $separ;
56
57
    /**
58
     * @var string
59
     */
60
    private $sepdec;
61
62
    /**
63
     * @var array
64
     */
65
    private $users_with_requests = array();
66
67
    /**
68
     * @var bool
69
     */
70
    private $users_without_requests;
71
72
    /**
73
     * @var array
74
     */
75
    private $dirfields;
76
77
78
    private $types = array();
79
80
    /**
81
     * @var int
82
     */
83
    private $organization = '';
84
85 1
    public function __construct(BAB_DateTime $dateb, BAB_DateTime $datee, $idstatus, $wsepar, $separ, $sepdec, $users_without_requests, $dirfields, $organization, $splittype)
86
    {
87 1
        $this->dateb = $dateb;
88 1
        $this->datee = $datee;
89 1
        $this->organization = $organization;
90
91 1
        $status = array();
92 1
        if (in_array(0,$idstatus)) {
93 1
            $status[] = '';
94 1
        }
95
        
96 1
        if (in_array(1,$idstatus)) {
97 1
            $status[] = 'Y';
98 1
        }
99
        
100 1
        if (in_array(2,$idstatus)) {
101 1
            $status[] = 'N';
102 1
        }
103
        
104 1
        $this->splittype = (bool) $splittype;
105
106 1
        if ($this->splittype) {
107
            $this->iterator = $this->getRequestTypeIterator($status);
108
        } else {
109 1
            $this->iterator = $this->getRequestIterator($status);
110
        }
111
112
        switch($wsepar)
113
        {
114 1
            case "1":
115 1
                $this->separ = ",";
116 1
                break;
117
            case "2":
118
                $this->separ = "\t";
119
                break;
120
            case "3":
121
                $this->separ = ";";
122
                break;
123
            default:
124
                $this->separ = $separ;
125
                if( empty($separ)) {
126
                    $this->separ = ",";
127
                }
128
                break;
129
        }
130
131 1
        $this->sepdec = $sepdec;
132
133 1
        $this->users_without_requests = (bool) $users_without_requests;
134
135 1
        $this->dirfields = $dirfields;
136 1
    }
137
    
138
    
139 1 View Code Duplication
    private function getRequestIterator($status)
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...
140
    {
141 1
        $I = new absences_EntryIterator();
142 1
        $I->from = $this->dateb->getIsoDateTime();
143 1
        $I->to = $this->datee->getIsoDateTime();
144
        
145 1
        if($this->organization){
146
            $I->organization = (int) $this->organization ;
147
        }
148
        
149
        
150 1
        $I->status = $status;
151
        
152 1
        return $I;
153
    }
154
    
155
    
156
    
157 1 View Code Duplication
    private function getRequestTypeIterator($status)
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...
158
    {
159
        $I = new absences_ElementEntryIterator();
160
        $I->from = $this->dateb->getIsoDateTime();
161
        $I->to = $this->datee->getIsoDateTime();
162
        
163
        if($this->organization ){
164
            $I->organization = (int) $this->organization ;
165
        }
166
        
167 1
        $I->status = $status;
168
        
169
        return $I;
170
    }
171
172
173 1
    private function arr_csv(&$value)
174
    {
175 1
        $value = str_replace("\n"," ",$value);
176 1
        $value = str_replace('"',"'",$value);
177 1
        $value = '"'.$value.'"';
178 1
    }
179
180
181 1
    private function numberFormat($quantity)
182
    {
183 1
        return number_format($quantity, 1, $this->sepdec, '');
184
    }
185
    
186
    
187
    
188
    
189
190
191 1
    protected function getEntriesHeader()
192
    {
193 1
        global $babDB;
194
        
195 1
        $line = array();
196
197 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...
198
            $ov_fields = bab_getDirEntry(BAB_REGISTERED_GROUP, BAB_DIR_ENTRY_ID_GROUP);
199
        }
200
201 1
        $line[] = absences_translate("lastname");
202 1
        $line[] = absences_translate("firstname");
203 1
        $line[] = absences_translate("Created on");
204 1
        $line[] = absences_translate("Modified on");
205
        
206 1
        $dirfields = array_keys($this->dirfields);
207 1
        foreach ($dirfields as $name) {
208
            $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...
209 1
        }
210 1
        $line[] = absences_translate("Begin date");
211 1
        $line[] = absences_translate("Begin hour");
212 1
        $line[] = absences_translate("End date");
213 1
        $line[] = absences_translate("End hour");
214 1
        $line[] = absences_translate("Status");
215 1
        $line[] = absences_translate("Total days");
216 1
        $line[] = absences_translate("Total hours");
217
218 1
        $res = $babDB->db_query("SELECT 
219
                t.id,
220
                t.name, 
221
                COUNT(rd.id) with_day,
222
                COUNT(rh.id) with_hour 
223
            FROM absences_types t 
224
                LEFT JOIN absences_rights rd ON rd.id_type=t.id AND rd.quantity_unit='D' 
225
                LEFT JOIN absences_rights rh ON rh.id_type=t.id AND rh.quantity_unit='H' 
226
            GROUP BY t.id 
227
            ORDER BY t.name 
228 1
        ");
229 1
        while ($arr = $babDB->db_fetch_assoc($res))
230
        {
231 1
            if ((bool) $arr['with_day']) {
232 1
                $line[] = $arr['name'].' '.absences_translate('days');
233 1
            }
234
            
235 1
            if ((bool) $arr['with_hour']) {
236
                $line[] = $arr['name'].' '.absences_translate('hours');
237
            }
238
            
239 1
            $this->types[] = array(
240 1
                'id'        => $arr['id'],
241 1
                'with_day'  => (bool) $arr['with_day'],
242 1
                'with_hour' => (bool) $arr['with_hour']
243 1
            );
244 1
        }
245 1
        array_walk($line, array($this, 'arr_csv'));
246
247 1
        return $line;
248
    }
249
    
250
    
251
    protected function getElementsHeader()
252
    {
253
        $line = array();
254
        
255
        $line[] = absences_translate("lastname");
256
        $line[] = absences_translate("firstname");
257
        $line[] = absences_translate("Created on");
258
        $line[] = absences_translate("Modified on");
259
        $line[] = absences_translate("Type");
260
        $line[] = absences_translate("Right");
261
        $line[] = absences_translate("Begin date");
262
        $line[] = absences_translate("Begin hour");
263
        $line[] = absences_translate("End date");
264
        $line[] = absences_translate("End hour");
265
        $line[] = absences_translate("Status");
266
        $line[] = absences_translate("Days");
267
        $line[] = absences_translate("Hours");
268
        
269
        array_walk($line, array($this, 'arr_csv'));
270
        
271
        return $line;
272
    }
273
    
274
    
275 1
    public function getHeader()
276
    {
277 1
        if ($this->splittype) {
278
            return $this->getElementsHeader();
279
        }
280
        
281 1
        return $this->getEntriesHeader();
282
    }
283
284
285 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...
286
    {
287 1
        $direntry = $agent->getDirEntry();
288
289 1
        if (isset($direntry[$fieldname]))
290 1
        {
291 1
            return $direntry[$fieldname]['value'];
292
        }
293
294
        return '';
295
    }
296
297
298
    /**
299
     * Quantity for one type
300
     * @return float
301
     */
302 1
    private function getTypeDays(absences_Entry $entry, $id_type)
303
    {
304 1
        return $entry->getPlannedDaysBetween($this->iterator->from, $this->iterator->to, $id_type);
305
    }
306
307
308
    /**
309
     * Quantity for one type
310
     * @return float
311
     */
312
    private function getTypeHours(absences_Entry $entry, $id_type)
313
    {
314
        return $entry->getPlannedHoursBetween($this->iterator->from, $this->iterator->to, $id_type);
315
    }
316
317
    /**
318
     * Entry begin timestamp
319
     *
320
     * if overlap with the end date :
321
     * First try with planned periods (in database for absences >= 2.46)
322
     * second with the current working periods (if not removed by configuration)
323
     * last with the iterator boundaries
324
     *
325
     * @return int
326
     */
327 1
    private function getBeginTs(absences_Entry $entry)
328
    {
329 1
        if ($this->iterator->from > $entry->date_begin) {
330
331
            $day = substr($this->iterator->from, 0, 10);
332
            $planned = $entry->getDayPlannedPeriods($day);
333
334 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...
335
                $workingPeriods = $entry->getDayWorkingPeriods($day);
336
337
                if (0 === count($workingPeriods)) {
338
                    return bab_mktime($this->iterator->from);
339
                }
340
341
                $firstPeriod = reset($workingPeriods);
342
                return $firstPeriod->ts_begin;
343
            }
344
345
            $firstperiod = reset($planned);
346
347
            return bab_mktime($firstperiod->date_begin);
348
        }
349
350 1
        return bab_mktime($entry->date_begin);
351
    }
352
353
    /**
354
     * Entry end timestamp
355
     *
356
     * if overlap with the end date :
357
     * First try with planned periods (in database for absences >= 2.46)
358
     * second with the current working periods (if not removed by configuration)
359
     * last with the iterator boundaries
360
     *
361
     * @return int
362
     */
363 1
    private function getEndTs(absences_Entry $entry)
364
    {
365 1
        if ($this->iterator->to < $entry->date_end) {
366
367
            $end = $this->datee->cloneDate();
368
            $end->less(1, BAB_DATETIME_DAY); // un jour a ete ajoute pour inclure le dernier jour dans l'iterateur
369
                                             // on enleve 1 jour pour retrouver la date saisie
370
            $day = $end->getIsoDate();
371
            $planned = $entry->getDayPlannedPeriods($day);
372
373 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...
374
                $workingPeriods = $entry->getDayWorkingPeriods($day);
375
376
                if (0 === count($workingPeriods)) {
377
                    return bab_mktime($this->iterator->to);
378
                }
379
380
                $lastPeriod = end($workingPeriods);
381
                return $lastPeriod->ts_end;
382
            }
383
384
            $lastperiod = end($planned);
385
386
            return bab_mktime($lastperiod->date_end);
387
        }
388
389 1
        return bab_mktime($entry->date_end);
390
    }
391
    
392
    
393
    
394
    protected function getElementRow(absences_EntryElem $elem)
395
    {
396
        $entry = $elem->getEntry();
397
        $right = $elem->getRight();
398
        $type = $right->getType();
399
        $agent = $entry->getAgent();
400
        
401
        $line = array();
402
        
403
404
        $line[] = $this->getAgentDirValue($agent, 'sn');
405
        $line[] = $this->getAgentDirValue($agent, 'givenname');
406
        $line[] = bab_shortDate(bab_mktime($entry->createdOn), false);
407
        $line[] = bab_shortDate(bab_mktime($entry->modifiedOn()), false);
408
        $line[] = $type->name;
409
        $line[] = $right->description;
410
        
411
        $begin = bab_mktime($elem->date_begin);
412
        $end = bab_mktime($elem->date_end);
413
        
414
        $line[] = bab_shortDate($begin, false);
415
        $line[] = date('H:i', $begin);
416
        $line[] = bab_shortDate($end, false);
417
        $line[] = date('H:i', $end);
418
        $line[] = $entry->getShortStatusStr();
419
        
420
        $line[] = $this->numberFormat($elem->getDays());
421
        $line[] = $this->numberFormat($elem->getHours());
422
        
423
        array_walk($line, array($this, 'arr_csv'));
424
425
        return $line;
426
    }
427
428
429
    /**
430
     *
431
     * @return array
432
     */
433 1
    public function getEntryRow(absences_Entry $entry)
434
    {
435 1
        $agent = $entry->getAgent();
436
437 1
        if (isset($agent)) {
438 1
            $this->users_with_requests[] = $agent->getIdUser();
439 1
        }
440
441 1
        $line = array();
442 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...
443 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...
444
        
445
        
446 1
        if (empty($line[0]) && empty($line[1])) {
447
            // the user has been deleted?
448
            return null;
449
        }
450
        
451
        
452 1
        $line[] = bab_shortDate(bab_mktime($entry->createdOn), false);
453 1
        $line[] = bab_shortDate(bab_mktime($entry->modifiedOn()), false);
454
455 1
        foreach($this->dirfields as $name => $dummy)
456
        {
457
            $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...
458 1
        }
459
460 1
        $begin = $this->getBeginTs($entry);
461 1
        $end = $this->getEndTs($entry);
462
463 1
        $line[] = bab_shortDate($begin, false);
464 1
		$line[] = date('H:i', $begin);
465 1
		$line[] = bab_shortDate($end, false);
466 1
		$line[] = date('H:i', $end);
467 1
        $line[] = $entry->getShortStatusStr();
468
469 1
        $pos = count($line);
470 1
        $tdays = 0.0;
471 1
        $thours = 0.0;
472 1
        foreach ($this->types as $_arr) {
473
            
474 1
            $id_type = $_arr['id'];
475
            
476 1
            if ($_arr['with_day']) {
477 1
                $days = $this->getTypeDays($entry, $id_type);
478 1
                $line[] = $this->numberFormat($days);
479 1
                $tdays += $days;
480 1
            }
481
            
482 1
            if ($_arr['with_hour']) {
483
                $hours = $this->getTypeHours($entry, $id_type);
484
                $line[] = $this->numberFormat($hours);
485
                $thours += $hours;
486
            }
487
            
488 1
        }
489
        
490
        
491 1
        if (0 === (int) round(100 * $tdays) && 0 === (int) round(100 * $thours)) {
492
            return null;
493
        }
494
        
495
496 1
        array_splice($line, $pos++, 0, $this->numberFormat($tdays));
497 1
        array_splice($line, $pos++, 0, $this->numberFormat($thours));
498
499 1
        array_walk($line, array($this, 'arr_csv'));
500
501 1
        return $line;
502
    }
503
504
    
505
    
506
    public function getRow($object)
507
    {
508
        if ($this->splittype) {
509
            return $this->getElementRow($object);
510
        }
511
        
512
        return $this->getEntryRow($object);
513
    }
514
    
515
    
516
517
    /**
518
     * @return absences_Agent[]
519
     */
520
    private function getUsersWithoutRequests()
521
    {
522
        $I = new absences_AgentIterator();
523
        if (count($this->users_with_requests) > 0)
524
        {
525
            $I->exclude_users = $this->users_with_requests;
526
        }
527
        if($this->organization){
528
        	$Orga = absences_Organization::getById($this->organization);
529
        	$I->setOrganization($Orga);
530
        }
531
        return $I;
532
    }
533
534
535
    /**
536
     * @return array
537
     */
538 1
    public function getAgentRow(absences_Agent $agent)
539
    {
540
541 1
        $line = array();
542 1
        $line[] = $this->getAgentDirValue($agent, 'sn');
543 1
        $line[] = $this->getAgentDirValue($agent, 'givenname');
544 1
        $line[] = '';
545 1
        $line[] = '';
546 1
        foreach($this->dirfields as $name => $dummy)
547
        {
548
            $line[] = $this->getAgentDirValue($agent, $name);
549 1
        }
550
551 1
        $line[] = '';
552 1
        $line[] = '';
553 1
        $line[] = '';
554 1
        $line[] = '';
555 1
        $line[] = '';
556 1
        $line[] = 0;
557 1
        $line[] = 0;
558 1
        foreach ($this->types as $_arr) {
559 1
            if ($_arr['with_day']) {
560 1
                $line[] = 0;
561 1
            }
562
            
563 1
            if ($_arr['with_hour']) {
564
                $line[] = 0;
565
            }
566 1
        }
567
568 1
        array_walk($line, array($this, 'arr_csv'));
569
570 1
        return $line;
571
    }
572
573
574
575
    public function output()
576
    {
577
578
        header("Content-Disposition: attachment; filename=\"".absences_translate("Vacation").".csv\""."\n");
579
        header("Content-Type: text/csv"."\n");
580
581
        $header = $this->getHeader();
582
        echo implode($this->separ, $header)."\n";
583
584
        foreach ($this->iterator as $object) {
585
            $line = $this->getRow($object);
586
            
587
            
588
            if (!isset($line)) {
589
                // the entry contain no total quantity or no directory entry
590
                continue;
591
            }
592
593
            
594
595
            echo implode($this->separ, $line)."\n";
596
        }
597
598
        if ($this->users_without_requests) {
599
            foreach ($this->getUsersWithoutRequests() as $agent) {
600
                $line = $this->getAgentRow($agent);
601
                echo implode($this->separ, $line)."\n";
602
            }
603
        }
604
605
        exit;
606
    }
607
}
608
609