Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
3.19% covered (danger)
3.19%
12 / 376
0.00% covered (danger)
0.00%
0 / 28
CRAP
0.00% covered (danger)
0.00%
0 / 1
Lggr
3.19% covered (danger)
3.19%
12 / 376
0.00% covered (danger)
0.00%
0 / 28
6485.76
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
 __destruct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getAuthUser
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 checkSecurity
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
30
 getViewName
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
42
 getLevels
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
42
 getAllServers
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
3.00
 getServersName
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 getServers
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
42
 getArchived
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
12
 getLatest
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 getCloud
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 getNewer
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getEntry
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getFromTo
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
 getHostFromTo
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 getFiltered
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
20
 getText
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
 getMessagesPerHour
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 getArchivedStatistic
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 getStatistic
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 purgeOldMessages
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 updateServers
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
56
 setArchive
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 normalizeHosts
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
56
 getResultSize
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 sendResult
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 getPerf
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2namespace Lggr;
3
4use PHPAuth\Config as PHPAuthConfig;
5use PHPAuth\Auth as PHPAuth;
6
7/**
8 * @brief Main class for logic.
9 */
10class Lggr {
11
12    const LASTSTAT = 5000;
13
14    const ARCHIVEDSIZE = 'archivedSize';
15
16    const INNERAND = ' AND ';
17
18    private $config = null;
19
20    private $db = null;
21
22    private $state = null;
23
24    private $cache = null;
25
26    private $aPerf = null;
27
28    private $auth = null;
29
30    function __construct(LggrState $state, AbstractConfig $config) {
31        $this->config = $config;
32        $this->state = $state;
33        $this->cache = new LggrCacheRedis(); // or use LggrCacheFile instead
34    $this->aPerf = array(); // of type LggrPerf objects
35
36    $dbh = new \PDO("mysql:host=" . $this->config->getDbHost() . ";dbname=" . $this->config->getDbName(), $this->config->getDbUser(), $this->config->getDbPwd());
37    $authConfig = new PHPAuthConfig($dbh);
38    $this->auth = new PHPAuth($dbh, $authConfig);
39        
40        if (! $this->state->isLocalCall()) {
41            $this->checkSecurity();
42        }
43        
44        $this->db = new \mysqli($this->config->getDbHost(), $this->config->getDbUSer(),
45            $this->config->getDbPwd(), $this->config->getDbName());
46        if ($this->db->connect_error) {
47            die('DB connect failed: ' . $this->db->connect_error);
48        }
49        $this->db->set_charset('utf8');
50    }
51
52    // constructor
53    function __destruct() {
54        if (null != $this->db) {
55            $this->db->close();
56        } // if
57    }
58
59    public function getAuthUser() {
60        return $this->auth->getCurrentUser();
61    }
62
63    // check auth
64    private function checkSecurity() {
65        // might be called by cli
66        if(!isset($_SERVER["REMOTE_ADDR"])) {
67            return;
68        }
69
70    // local access allowed without login data
71    // Attention: Using a reverse proxy might change the requester IP
72    // to the localhost one. Change the code or add remote IP
73    // to the request headers!
74        if ($_SERVER["REMOTE_ADDR"] === "::1") {
75            return;
76        }
77        if ($_SERVER["REMOTE_ADDR"] === "127.0.0.1") {
78            return;
79    }
80    if(!$this->auth->isLogged()) {
81            throw new LggrException('You must be logged in here, go to <a href="/login.php">/login.php</a>');
82        } // if
83    }
84
85    // function
86    private function getViewName() {
87        $rcView = '';
88        switch ($this->state->getRange()) {
89            case 1:
90                $rcView = 'lasthour';
91                break;
92            case 24:
93                $rcView = 'today';
94                break;
95            case 168:
96                $rcView = 'week';
97                break;
98            case 8760:
99                $rcView = 'year';
100                break;
101            default:
102                $rcView = 'today';
103                break;
104        }
105        return $rcView;
106    }
107
108    function getLevels() {
109        $perf = new LggrPerf();
110        
111        $v = $this->getViewName();
112        $sql = "
113SELECT level, COUNT(*) AS c
114FROM (SELECT level FROM $v ORDER BY `date` DESC LIMIT " .
115             self::LASTSTAT . ") AS sub
116GROUP BY level
117ORDER BY c DESC
118";
119        
120        $a = $this->cache->retrieve("levels$v");
121        if (null != $a) {
122            return $a;
123        } // if
124        $a = array();
125        
126        $perf->start($sql);
127        
128        $res = $this->db->query($sql);
129        if (false === $res) {
130            throw new LggrException($this->db->error);
131        } // if
132        while ($row = $res->fetch_object()) {
133            $a[] = $row;
134        } // while
135        $res->close();
136        
137        $sum = 0;
138        foreach ($a as $level) {
139            $sum += $level->c;
140        } // foreach
141        foreach ($a as $level) {
142            $f = $level->c / $sum * 100;
143            $level->f = round($f, 2);
144        } // foreach
145        
146        $perf->stop();
147        $this->aPerf[] = $perf;
148        
149        $this->cache->store("levels$v", $a);
150        return $a;
151    }
152
153    // function
154    function getAllServers() {
155        $perf = new LggrPerf();
156        
157        $sql = "
158SELECT id,name AS host
159FROM servers";
160        
161        $perf->start($sql);
162        $a = array();
163        $res = $this->db->query($sql);
164        if (false === $res) {
165            throw new LggrException($this->db->error);
166        } // if
167        while ($row = $res->fetch_object()) {
168            $a[] = $row;
169        } // while
170        $res->close();
171        
172        $perf->stop();
173        $this->aPerf[] = $perf;
174        
175        return $a;
176    }
177
178    // function
179    function getServersName($id) {
180        $perf = new LggrPerf();
181        
182        $sql = "
183SELECT name
184FROM servers
185WHERE id=$id";
186        
187        $perf->start($sql);
188        
189        $a = null;
190        $res = $this->db->query($sql);
191        if (false === $res) {
192            throw new LggrException($this->db->error);
193        } // if
194        if ($row = $res->fetch_object()) {
195            $a = $row;
196        } // while
197        $res->close();
198        
199        $perf->stop();
200        $this->aPerf[] = $perf;
201        
202        return $a->name;
203    }
204
205    // function
206    function getServers() {
207        $perf = new LggrPerf();
208        
209        $v = $this->getViewName();
210        
211        $sql = "
212SELECT host, COUNT(*) AS c
213FROM (SELECT host FROM $v ORDER BY `date` DESC LIMIT " .
214             self::LASTSTAT . ") AS sub
215GROUP BY host
216ORDER BY c DESC";
217        
218        $a = $this->cache->retrieve("servers$v");
219        if (null != $a) {
220            return $a;
221        } // if
222        $a = array();
223        
224        $perf->start($sql);
225        
226        $res = $this->db->query($sql);
227        if (false === $res) {
228            throw new LggrException($this->db->error);
229        } // if
230        while ($row = $res->fetch_object()) {
231            $a[] = $row;
232        } // while
233        $res->close();
234        
235        $sum = 0;
236        foreach ($a as $host) {
237            $sum += $host->c;
238        } // foreach
239        foreach ($a as $host) {
240            $f = $host->c / $sum * 100;
241            $host->f = round($f, 2);
242        } // foreach
243        
244        $perf->stop();
245        $this->aPerf[] = $perf;
246        
247        $this->cache->store("servers$v", $a);
248        return $a;
249    }
250
251    // function
252    function getArchived($from = 0, $count = LggrState::PAGELEN) {
253        $iArchivedSize = $this->cache->retrieve(Lggr::ARCHIVEDSIZE);
254        $aArchivedData = $this->cache->retrieve(Lggr::ARCHIVEDSIZE . intval($from));
255        
256        if ((null != $iArchivedSize) && (null != $aArchivedData)) {
257            $this->state->setResultSize($iArchivedSize);
258            return $aArchivedData;
259        } // if
260        
261        $perfSize = new LggrPerf();
262        $perfData = new LggrPerf();
263        
264        $sqlSize = "SELECT COUNT(*) AS c FROM archived";
265        $sqlData = "
266SELECT * FROM archived
267ORDER BY `date` DESC
268LIMIT $from,$count";
269        
270        $perfSize->start($sqlSize);
271        $this->getResultSize($sqlSize);
272        $perfSize->stop();
273        
274        $perfData->start($sqlData);
275        $a = $this->sendResult($sqlData);
276        $perfData->stop();
277        
278        $this->aPerf[] = $perfSize;
279        $this->aPerf[] = $perfData;
280        
281        $this->cache->store("archivedSize", $this->state->getResultSize());
282        $this->cache->store("archivedData" . intval($from), $a);
283        
284        return $a;
285    }
286
287    // function
288    function getLatest($from = 0, $count = LggrState::PAGELEN) {
289        $perfSize = new LggrPerf();
290        $perfData = new LggrPerf();
291        
292        $v = $this->getViewName();
293        
294        $sqlSize = "SELECT COUNT(*) AS c FROM $v";
295        $sqlData = "
296SELECT * FROM $v
297ORDER BY `date` DESC
298LIMIT $from,$count";
299        
300        $perfSize->start($sqlSize);
301        $this->getResultSize($sqlSize);
302        $perfSize->stop();
303        
304        $perfData->start($sqlData);
305        $a = $this->sendResult($sqlData);
306        $perfData->stop();
307        
308        $this->aPerf[] = $perfSize;
309        $this->aPerf[] = $perfData;
310        
311        return $a;
312    }
313
314    // function
315    function getCloud() {
316        $perf = new LggrPerf();
317        
318        $v = $this->getViewName();
319        
320        $a = $this->cache->retrieve("cloud$v");
321        if (null != $a) {
322            return $a;
323        } // if
324        
325        $sql = "SELECT COUNT(*) AS c, program FROM $v GROUP BY program HAVING CHAR_LENGTH(program)>2 ORDER BY c DESC";
326        $perf->start($sql);
327        $a = $this->sendResult($sql);
328        $perf->stop();
329        
330        $this->aPerf[] = $perf;
331        
332        $this->cache->store("cloud$v", $a);
333        
334        return $a;
335    }
336
337    // function
338    function getNewer($id) {
339        $perf = new LggrPerf();
340        
341        $sqlData = "
342SELECT * FROM lasthour
343WHERE id>$id
344ORDER BY `date` DESC
345LIMIT " . LggrState::PAGELEN;
346        
347        $perf->start($sqlData);
348        $a = $this->sendResult($sqlData);
349        $perf->stop();
350        
351        $this->aPerf[] = $perf;
352        
353        return $a;
354    }
355
356    // function
357    function getEntry($id) {
358        $perf = new LggrPerf();
359        
360        $sqlData = "
361SELECT * FROM lasthour
362WHERE id=$id";
363        
364        $perf->start($sqlData);
365        $a = $this->sendResult($sqlData);
366        $perf->stop();
367        
368        $this->aPerf[] = $perf;
369        return $a;
370    }
371
372    // function
373    function getFromTo($from = 0, $count = LggrState::PAGELEN) {
374        $perfSize = new LggrPerf();
375        $perfData = new LggrPerf();
376        
377        $sFrom = $this->db->escape_string($this->state->getFrom());
378        $sTo = $this->db->escape_string($this->state->getTo());
379        
380        $sqlSize = "
381SELECT COUNT(*) AS c FROM newlogs
382WHERE `date` BETWEEN '$sFrom' AND '$sTo'";
383        
384        $sqlData = "
385SELECT * FROM newlogs
386WHERE `date` BETWEEN '$sFrom' AND '$sTo'
387ORDER BY `date` DESC
388LIMIT $from,$count";
389        
390        $perfSize->start($sqlSize);
391        $this->getResultSize($sqlSize);
392        $perfSize->stop();
393        
394        $perfData->start($sqlData);
395        $a = $this->sendResult($sqlData);
396        $perfData->stop();
397        
398        $this->aPerf[] = $perfSize;
399        $this->aPerf[] = $perfData;
400        
401        return $a;
402    }
403
404    // function
405    function getHostFromTo($from = 0, $count = LggrState::PAGELEN) {
406        $perfSize = new LggrPerf();
407        $perfData = new LggrPerf();
408        
409        $iHost = $this->state->getHostId();
410        $sFrom = $this->db->escape_string($this->state->getFrom());
411        $sTo = $this->db->escape_string($this->state->getTo());
412        
413        $sqlSize = "
414SELECT COUNT(*) AS c FROM newlogs
415WHERE `date` BETWEEN '$sFrom' AND '$sTo'
416AND idhost=$iHost";
417        
418        $sqlData = "
419SELECT * FROM newlogs
420WHERE `date` BETWEEN '$sFrom' AND '$sTo'
421AND idhost=$iHost
422ORDER BY `date` DESC
423LIMIT $from,$count";
424        
425        $perfSize->start($sqlSize);
426        $this->getResultSize($sqlSize);
427        $perfSize->stop();
428        
429        $perfData->start($sqlData);
430        $a = $this->sendResult($sqlData);
431        $perfData->stop();
432        
433        $this->aPerf[] = $perfSize;
434        $this->aPerf[] = $perfData;
435        
436        return $a;
437    }
438
439    // function
440    function getFiltered($host = null, $level = null, $from = 0,
441        $count = LggrState::PAGELEN) {
442        $perfSize = new LggrPerf();
443        $perfData = new LggrPerf();
444        
445        $v = $this->getViewName();
446        
447        $sqlSize = "SELECT COUNT(*) AS c FROM $v";
448        $sqlData = "SELECT * FROM $v";
449        
450        $aWhere = array();
451        if (null != $host) {
452            $sTmp = $this->db->escape_string($host);
453            $aWhere[] = "host='$sTmp'";
454        } // if
455        if (null != $level) {
456            $sTmp = $this->db->escape_string($level);
457            $aWhere[] = "level='$sTmp'";
458        } // if
459        
460        if (!empty($aWhere)) {
461            $sqlSize .= " WHERE " . implode(Lggr::INNERAND, $aWhere);
462            $sqlData .= " WHERE " . implode(Lggr::INNERAND, $aWhere);
463        } // if
464        
465        $sqlData .= " ORDER BY `date` DESC LIMIT $from,$count";
466        
467        $perfSize->start($sqlSize);
468        $this->getResultSize($sqlSize);
469        $perfSize->stop();
470        
471        $perfData->start($sqlData);
472        $a = $this->sendResult($sqlData);
473        $perfData->stop();
474        
475        $this->aPerf[] = $perfSize;
476        $this->aPerf[] = $perfData;
477        
478        return $a;
479    }
480
481    // function
482    function getText($msg = '', $prog = '', $from = 0, $count = LggrState::PAGELEN) {
483        $perf = new LggrPerf();
484        
485        $v = $this->getViewName();
486        $sTmpMsg = $this->db->escape_string($msg);
487        $sTmpProg = $this->db->escape_string($prog);
488        
489        $aWhere = array();
490        if ('' != $msg) {
491            $aWhere[] = "message LIKE '%{$sTmpMsg}%'";
492        } // if
493        if ('' != $prog) {
494            $aWhere[] = "program LIKE '%{$sTmpProg}%'";
495        } // if
496        $sWhere = implode(' AND ', $aWhere);
497        
498        $sql = "
499SELECT * FROM $v
500WHERE $sWhere
501ORDER BY `date` DESC
502LIMIT $from,$count";
503        
504        $perf->start($sql);
505        $a = $this->sendResult($sql);
506        $perf->stop();
507        
508        $this->aPerf[] = $perf;
509        
510        return $a;
511    }
512
513    // function
514    function getMessagesPerHour() {
515        $perf = new LggrPerf();
516        
517        $sql = "
518SELECT HOUR(TIME(`date`)) AS h, COUNT(*) AS c
519FROM today
520GROUP BY h";
521        
522        $a = $this->cache->retrieve('mph');
523        if (null != $a) {
524            return $a;
525        } // if
526        
527        $perf->start($sql);
528        $a = $this->sendResult($sql);
529        $perf->stop();
530        
531        $this->aPerf[] = $perf;
532        
533        $this->cache->store('mph', $a);
534        return $a;
535    }
536
537    // function
538    function getArchivedStatistic() {
539        $perf = new LggrPerf();
540        
541        $sql = "
542SELECT COUNT(*) AS cnt
543FROM archived
544";
545        
546        $a = $this->cache->retrieve('archivedstats');
547        if (null != $a) {
548            return $a;
549        } // if
550        
551        $perf->start($sql);
552        $a = $this->sendResult($sql);
553        $perf->stop();
554        
555        $this->aPerf[] = $perf;
556        
557        $this->cache->store('archivedstats', $a);
558        return $a;
559    }
560
561    // function
562    function getStatistic() {
563        $perf = new LggrPerf();
564        
565        $sql = "
566SELECT COUNT(*) AS cnt, MIN(`date`) AS oldest
567FROM newlogs
568";
569        
570        $a = $this->cache->retrieve('stats');
571        if (null != $a) {
572            return $a;
573        } // if
574        
575        $perf->start($sql);
576        $a = $this->sendResult($sql);
577        $perf->stop();
578        
579        $this->aPerf[] = $perf;
580        
581        $this->cache->store('stats', $a);
582        return $a;
583    }
584
585    // function
586    
587    /* delete anything older than maxage hours */
588    function purgeOldMessages($maxage = 672) {
589    $iMaxAge = intval($maxage);
590        $perf = new LggrPerf();
591        
592        $sql = "call Purge_entries($iMaxAge);";
593        
594        $perf->start($sql);
595        $res = $this->db->query($sql);
596        if (false === $res) {
597            throw new LggrException($this->db->error);
598        } // if
599        $perf->stop();
600        $this->aPerf[] = $perf;
601        
602        return $this->db->affected_rows;
603    }
604
605    // function
606    function updateServers() {
607        $perf = new LggrPerf();
608        $iCount = 0;
609        
610        // First, get list of all known servers
611        $sql = "SELECT id,name FROM servers";
612        $perf->start($sql);
613        $aServersKnownObj = $this->sendResult($sql);
614        $perf->stop();
615        $this->aPerf[] = $perf;
616        
617        $aServersKnown = array();
618        foreach ($aServersKnownObj as $obj) {
619            $aServersKnown[$obj->name] = $obj->id;
620        } // foreach
621          
622        // Second, get list of all used servers in logs
623        $sql = "SELECT DISTINCT host FROM newlogs";
624        $perf->start($sql);
625        $aServersUsed = $this->sendResult($sql);
626        $perf->stop();
627        $this->aPerf[] = $perf;
628        
629        // Third, Look for servers not yet in the known servers list
630        foreach ($aServersUsed as $obj) {
631            $sName = $obj->host;
632            if (array_key_exists($sName, $aServersKnown)) {
633                // already existing
634            } else {
635                $sName = $this->db->escape_string($sName);
636                $sql = "INSERT INTO servers SET name='$sName'";
637                $res = $this->db->query($sql);
638                if (false === $res) {
639                    throw new LggrException($this->db->error);
640                } // if
641                $iCount ++;
642            } // if
643        } // foreach
644          
645        // Fourth, add foreign key of server to new entries with null foreign key
646        foreach ($aServersKnown as $sName => $sID) {
647            $sName = $this->db->escape_string($sName);
648            $sql = "UPDATE newlogs SET idhost=$sID WHERE host='$sName' AND idhost IS NULL";
649            $res = $this->db->query($sql);
650            if (false === $res) {
651                throw new LggrException($this->db->error);
652            } // if
653            $iCount += $this->db->affected_rows;
654        } // foreach
655          
656        // return to caller
657        return $iCount;
658    }
659
660    function setArchive($iID, $bIsArchived) {
661        $iID = intval($iID);
662        if ($bIsArchived) {
663            $sArchive = 'Y';
664        } else {
665            $sArchive = 'N';
666        } // if
667        
668        $sql = "UPDATE newlogs SET archived='$sArchive' WHERE id=$iID LIMIT 1";
669        $res = $this->db->query($sql);
670        if (false === $res) {
671            throw new LggrException($this->db->error);
672        } // if
673        
674        $this->cache->purge(Lggr::ARCHIVEDSIZE);
675        $this->cache->purge("archivedData0");
676    }
677
678    // function
679    function normalizeHosts() {
680        
681        // Find any new hostnames
682        $sql = "
683SELECT newlogs.host
684FROM newlogs
685LEFT JOIN hosts ON hosts.name=newlogs.host
686WHERE hosts.id IS NULL
687GROUP BY newlogs.host";
688        $aEmpty = $this->sendResult($sql);
689        foreach ($aEmpty as $o) {
690            $host = $o->host;
691            $host = $this->db->escape_string($host);
692            
693            $sql = "INSERT INTO hosts (name) VALUES ('$host')";
694            $res = $this->db->query($sql);
695            if (false === $res) {
696                throw new LggrException($this->db->error);
697            } // if
698            $id = $this->db->insert_id;
699            
700            $sql = "UPDATE newlogs SET idhost=$id WHERE host='$host'";
701            $res = $this->db->query($sql);
702            if (false === $res) {
703                throw new LggrException($this->db->error);
704            } // if
705        } // foreach
706          
707        // read current list of hostnames and ids
708        $sql = "
709SELECT *
710FROM hosts";
711        $aTmp = $this->sendResult($sql);
712        $aHosts = array();
713        foreach ($aTmp as $o) {
714            $hostId = $o->id;
715            $hostName = $o->name;
716            $aHosts[$hostName] = $hostId;
717        } // foreach
718          
719        // search any new entry without hostid and update it
720        foreach ($aHosts as $hostName => $hostId) {
721            $hostName = $this->db->escape_string($hostName);
722            $sql = "
723UPDATE newlogs
724SET idhost=$hostId
725WHERE idhost IS NULL
726AND host='$hostName'
727";
728            $res = $this->db->query($sql);
729            if (false === $res) {
730                throw new LggrException($this->db->error);
731            } // if
732        } // foreach
733    }
734
735    // function
736    private function getResultSize($sql) {
737        $res = $this->db->query($sql);
738        if (false === $res) {
739            throw new LggrException($this->db->error);
740        } // if
741        if ($row = $res->fetch_object()) {
742            $i = $row->c;
743            $this->state->setResultSize($i);
744        } // if
745        $res->close();
746    }
747
748    // function
749    private function sendResult($sql) {
750        $a = array();
751        
752        $res = $this->db->query($sql);
753        if (false === $res) {
754            throw new LggrException($this->db->error);
755        } // if
756        while ($row = $res->fetch_object()) {
757            $a[] = $row;
758        } // while
759        
760        $res->close();
761        return $a;
762    }
763
764    // function
765    public function getPerf() {
766        return $this->aPerf;
767    } // function
768} // class