source: extensions/EStat/lib/statDBMonth.class.inc.php @ 22483

Last change on this file since 22483 was 17760, checked in by grum, 12 years ago

version 0.1.0b

. fix bug on period tab (empty period is managed)
. fix bug on date/time filter (+set time as mandatory value)

  • Property svn:executable set to *
File size: 47.7 KB
Line 
1<?php
2
3require_once('statDB.class.inc.php');
4
5/**
6 * specific class for SQLite monthly stat managment
7 */
8class StatDBMonth extends StatDB
9{
10  protected $year='';
11  protected $month='';
12  protected $nbDaysMonth=0;
13
14  /**
15   * constructor
16   *
17   * @param String $directory: directory where the sqlite file is saved
18   * @param String $fileName: file name (without extension)
19   */
20  public function __construct($directory='', $fileName='', $year='', $month='')
21  {
22    parent::__construct($directory, $fileName);
23    $this->setPeriod($year, $month);
24  }
25
26
27  /**
28   * define the covered period (year/month)
29   * @param String $year;
30   * @param String $month;
31   * @return String
32   */
33  public function setPeriod($year, $month)
34  {
35    $this->month=$month;
36    $this->year=$year;
37    $this->fileRootName=ASDF_FILE_ROOT_MONTH.$year.$month;
38
39    $this->nbDaysMonth=date('d', strtotime('-1 day', strtotime('+1 month', strtotime("$year-$month-01"))))*1;
40
41    return($this->fileRootName);
42  }
43
44
45  /**
46   * return the number of days for the month
47   *
48   * @return Integer
49   */
50  public function getNbDays()
51  {
52    return($this->nbDaysMonth);
53  }
54
55  /**
56   * add a log record
57   *
58   * Data have to be provided as an array with keys:
59   *      array(
60   *         'date'             => integer
61   *         'IPadress'         => string
62   *         'userId'           => integer
63   *         'catId'            => integer
64   *         'imageId'          => integer
65   *         'tagsId'           => string
66   *         'section'          => string
67   *         'userAgent'        => string
68   *         'uaBrowser'        => integer
69   *         'uaBrowserVersion' => integer
70   *         'uaEngine'         => integer
71   *         'uaEngineVersion'  => integer
72   *         'uaOS'             => integer
73   *         'uaOSVersion'      => integer
74   *         'uaType'           => integer
75   *         'screenSizeW'      => integer
76   *         'screenSizeH'      => integer
77   *      )
78   *
79   * missing values are set to default value
80   * country is defined automatically after buildIPCountry call; set to '' while
81   * call is not made
82   *
83   * @param Array $log : a record
84   * @return String : true if log was added, otherwise false
85   */
86  public function addLog($value)
87  {
88    if(is_array($value) and $this->dbHandle!=null)
89    {
90      // set default values if needed
91      if(!isset($value['date'])) $value['date']=time();
92      if(!isset($value['IPadress'])) $value['IPadress']='0.0.0.0';
93      if(!isset($value['userId'])) $value['userId']=0;
94      if(!isset($value['catId'])) $value['catId']=0;
95      if(!isset($value['imageId'])) $value['imageId']=0;
96      if(!isset($value['section'])) $value['section']='';
97      if(!isset($value['tagsId'])) $value['tagsId']='';
98      if(!isset($value['userAgent'])) $value['userAgent']='';
99      if(!isset($value['uaBrowser'])) $value['uaBrowser']=0;
100      if(!isset($value['uaBrowserVersion'])) $value['uaBrowserVersion']='';
101      if(!isset($value['uaEngine'])) $value['uaEngine']=0;
102      if(!isset($value['uaEngineVersion'])) $value['uaEngineVersion']='';
103      if(!isset($value['uaOS'])) $value['uaOS']=0;
104      if(!isset($value['uaOSVersion'])) $value['uaOSVersion']='';
105      if(!isset($value['uaType'])) $value['uaType']=0;
106      if(!isset($value['screenSizeW'])) $value['screenSizeW']=0;
107      if(!isset($value['screenSizeH'])) $value['screenSizeH']=0;
108
109      $value['IPadress']=self::IPBinaryEncode($value['IPadress']);
110
111      // insert log
112      $sql="INSERT INTO logs
113            (date, IPadress, country, userId, catId, imageId, tagsId, section,
114             userAgent, uaBrowser, uaBrowserVersion, uaEngine, uaEngineVersion,
115             uaOS, uaOSVersion, uaType, screenSizeW, screenSizeH)
116            VALUES (".$value['date'].", ".
117                      //"'".$this->dbHandle->escapeString($value['IPadress'])."', ".
118                      ":IP, ".
119                      "'', ".
120                      $value['userId'].", ".
121                      $value['catId'].", ".
122                      $value['imageId'].", ".
123                      "'".$value['tagsId']."', ".
124                      "'".$value['section']."', ".
125                      "'".$this->dbHandle->escapeString($value['userAgent'])."', ".
126                      $value['uaBrowser'].", ".
127                      "'".$value['uaBrowserVersion']."', ".
128                      $value['uaEngine'].", ".
129                      "'".$value['uaEngineVersion']."', ".
130                      $value['uaOS'].", ".
131                      "'".$value['uaOSVersion']."', ".
132                      $value['uaType'].", ".
133                      $value['screenSizeW'].", ".
134                      $value['screenSizeH']." );";
135//echo "$sql\n";
136      $sqlStm=$this->dbHandle->prepare($sql);
137      $sqlStm->bindValue(':IP', $value['IPadress'], SQLITE3_BLOB);
138      return($sqlStm->execute());
139    }
140    return(false);
141  }
142
143  /**
144   * return detailled logs
145   *
146   * $page: the page number asked; first page is 1=>lower value means to get all values
147   * $nbItemsPage: the number of items returned per; 0 means no limit
148   *
149   *
150   * in ASDF_GET_ROWS mode, each returned logs is an array:
151   *      array(
152   *         'date'             => integer
153   *         'IPadress'         => string
154   *         'userId'           => integer
155   *         'catId'            => integer
156   *         'imageId'          => integer
157   *         'tagsId'           => string
158   *         'section'          => string
159   *         'userAgent'        => string
160   *         'uaBrowser'        => integer
161   *         'uaBrowserVersion' => integer
162   *         'uaEngine'         => integer
163   *         'uaEngineVersion'  => integer
164   *         'uaOS'             => integer
165   *         'uaOSVersion'      => integer
166   *         'uaType'           => integer
167   *         'screenSizeW'      => integer
168   *         'screenSizeH'      => integer
169   *      )
170   *
171   * for each filtered item, are given an array:
172   *  array(
173   *   'operator' => '',
174   *   'value' => '',
175   *   'minValue' => '',
176   *   'maxValue' =>
177   *  )
178   *
179   * operator can take the following values:
180   *    '=', '>', '<', '>=', '<=', '!='
181   *        in this case, the index 'value' have to be set
182   *
183   *    'in'
184   *        in this case, the index 'value' have to be an array of needed value
185   *
186   *    'between'
187   *        in this case, the indexes 'minValue' and 'maxValue' have to be set
188   *
189   *
190   * filterable items are
191   *  'date'       (string) 'YYYY-MM-DD HH:II:SS' : '=', '>', '<', '>=', '<=', '!=', 'between'
192   *  'IPadress'   (string) 'xxx.xxx.xxx.xxx'     : '=', '!=', 'in', 'between'
193   *  'section'    (string)                       : '=', '!=', 'in'
194   *  'tagsId'     (integer)                      : '=', '!=', 'in'
195   *  'userId'     (integer)                      : '=', '!=', 'in'
196   *  'catId'      (integer)                      : '=', '!=', 'in'
197   *  'imageId'    (integer)                      : '=', '!=', 'in'
198   *  'uaBrowser'  (integer)                      : '=', '!=', 'in'
199   *  'uaEngine'   (integer)                      : '=', '!=', 'in'
200   *  'uaOS'       (integer)                      : '=', '!=', 'in'
201   *  'uaType'     (integer)                      : '=', '!=', 'in'
202   *  => version are not filterable, it's normal, it's not implemented :)
203   *     May be one day, if it's really interesting do to it...
204   *
205   * $order is an array allowing to set how data are sorted; column priority is set by
206   * the order of items in the array
207   * Each item of the array is an array with the following properties:
208   * Array(
209   *  'id'        => string (columnId)
210   *  'direction' => string ('A' for Asc, 'D' for Desc)
211   * )
212   *
213   * In the following example:
214   *  $order=Array(
215   *     Array('id' => 'uaBrowser', 'direction' => 'D'),
216   *     Array('id' => 'uaOS', 'direction' => 'A')
217   *  )
218   * the 'order by' clause will be: ORDER BY uaBrowser ASC, uaOS DESC
219   * => as for filter, version are not sortable
220   *
221   *
222   * @param Integer $mode: type of result needed
223   *                          . ASDF_GET_ROWS return an array of logs
224   *                          . ASDF_GET_COUNT return the number of logs
225   * @param Integer $page: page number
226   * @param Integer $nbItemsPage: number of items per page
227   * @param Array $filter : filters to apply
228   * @param Array $order: sort to apply
229   * @return
230   */
231  public function getLogs($mode=ASDF_GET_ROWS, $page=0, $nbItemsPage=0, $filter=array(), $order=array())
232  {
233    switch($mode)
234    {
235      case ASDF_GET_COUNT:
236        $returned=0;
237        break;
238      case ASDF_GET_ROWS:
239        $returned=array();
240        break;
241    }
242    if($this->dbHandle==null) return($returned);
243
244    // initialize filter
245    if(!is_array($filter)) $filter=array();
246
247    if(!isset($filter['date'])) $filter['date']=null;
248    if(!isset($filter['IPadress'])) $filter['IPadress']=null;
249    if(!isset($filter['section'])) $filter['section']=null;
250    if(!isset($filter['tagsId'])) $filter['tagsId']=null;
251    if(!isset($filter['userId'])) $filter['userId']=null;
252    if(!isset($filter['catId'])) $filter['catId']=null;
253    if(!isset($filter['imageId'])) $filter['imageId']=null;
254    if(!isset($filter['uaBrowser'])) $filter['uaBrowser']=null;
255    if(!isset($filter['uaEngine'])) $filter['uaEngine']=null;
256    if(!isset($filter['uaOS'])) $filter['uaOS']=null;
257    if(!isset($filter['uaType'])) $filter['uaType']=null;
258
259    $filter['date']=$this->checkDateFilter($filter['date']);
260    $filter['IPadress']=$this->checkIPFilter($filter['IPadress']);
261    // check filter values - getOperator check and 'clean' the filter
262    $filter['date']=$this->getOperator($filter['date'], 'date');
263    $filter['IPadress']=$this->getOperator($filter['IPadress'], 'IP');
264    $filter['section']=$this->getOperator($filter['section'], 'string');
265    $filter['tagsId']=$this->getOperator($filter['tagsId'], 'integer');
266    $filter['userId']=$this->getOperator($filter['userId'], 'integer');
267    $filter['catId']=$this->getOperator($filter['catId'], 'integer');
268    $filter['imageId']=$this->getOperator($filter['imageId'], 'integer');
269    $filter['uaBrowser']=$this->getOperator($filter['uaBrowser'], 'integer');
270    $filter['uaEngine']=$this->getOperator($filter['uaEngine'], 'integer');
271    $filter['uaOS']=$this->getOperator($filter['uaOS'], 'integer');
272    $filter['uaType']=$this->getOperator($filter['uaType'], 'integer');
273
274    // initialize order
275    $orderBy=array();
276    if(!is_array($order)) $order=array();
277    foreach($order as $sort)
278    {
279      if(isset($sort['id']) and isset($sort['direction']))
280      {
281        if(($sort['id']=='date' or
282            $sort['id']=='IPadress' or
283            $sort['id']=='section' or
284            $sort['id']=='tagsId' or
285            $sort['id']=='userId' or
286            $sort['id']=='catId' or
287            $sort['id']=='imageId' or
288            $sort['id']=='uaBrowser' or
289            $sort['id']=='uaEngine' or
290            $sort['id']=='uaOS' or
291            $sort['id']=='uaType') and
292           ($sort['direction']=='A' or
293            $sort['direction']=='D')
294          ) $orderBy[]=$sort;
295      }
296    }
297    // set default order if nothing available is provided
298    if(count($orderBy)==0)
299      $orderBy=array(
300        array('id'=>'date', 'direction'=>'D'),
301        array('id'=>'id', 'direction'=>'A')
302      );
303    // to optimize query, if date is the first field selected for order by,
304    // all other fields are removed; exception: if IPadress is the second one this
305    // field is kept
306    $tmp=$orderBy;
307    if($tmp[0]['id']=='date')
308    {
309      $orderBy=array($tmp[0]);
310      if($tmp[1]['id']=='IPadress')
311      {
312        $orderBy[]=$tmp[1];
313      }
314    }
315
316    //build ORDER BY clause
317    $orderBy=$this->buildOrderByClause($orderBy);
318
319    //build WHERE clause
320    $IPList=array();
321    $where=$this->buildWhereClause($filter,$IPList);
322
323    // build LIMIT clause
324    $limit=$this->buildLimitClause($page, $nbItemsPage);
325
326    // execute request
327    switch($mode)
328    {
329      case ASDF_GET_ROWS:
330          $sql="SELECT id, date, IPadress, country, userId, catId, imageId, tagsId, section,
331                       userAgent, uaBrowser, uaBrowserVersion, uaEngine, uaEngineVersion,
332                       uaOS, uaOSVersion, uaType, screenSizeW, screenSizeH
333                FROM logs $where $orderBy $limit;";
334
335          $sqlStm=$this->dbHandle->prepare($sql);
336          foreach($IPList as $num=>$IP)
337          {
338            $sqlStm->bindValue(':IP'.$num, $IP, SQLITE3_BLOB);
339          }
340
341          $result=$sqlStm->execute();
342          if($result)
343          {
344            while($row=$result->fetchArray(SQLITE3_ASSOC))
345            {
346              $row['IPadress']=self::IPBinaryDecode($row['IPadress']);
347              $returned[]=$row;
348            }
349          }
350        break;
351      case ASDF_GET_COUNT:
352          $sql="SELECT COUNT(id) AS nb
353                FROM logs $where;";
354
355          $sqlStm=$this->dbHandle->prepare($sql);
356          foreach($IPList as $num=>$IP)
357          {
358            $sqlStm->bindValue(':IP'.$num, $IP, SQLITE3_BLOB);
359          }
360
361          $result=$sqlStm->execute();
362          if($result)
363          {
364            while($row=$result->fetchArray(SQLITE3_ASSOC))
365            {
366              $returned=$row['nb'];
367            }
368          }
369        break;
370    }
371    return($returned);
372  }
373
374
375
376  /**
377   * returns stats from useragent strings (os, browser, engine, type)
378   *
379   * $page: the page number asked; first page is 1=>lower value means to get all values
380   * $nbItemsPage: the number of items returned per; 0 means no limit
381   *
382   *
383   * in ASDF_GET_ROWS mode, each returned logs is an array of asked fields
384   * at least, the following fields are always returned:
385   *  'nbVisits' => number of visits
386   *  'uaValue'  => value (meaning of this information can change)
387   *
388   *
389   * all fields are filterable, except 'nbVisits' that can't be filtered
390   *
391   * available fields values are:
392   *   'uaData'    => return the type of data; can get one of the following values
393   *                          UA_DATA_BROWSER: stat about browser
394   *                          UA_DATA_ENGINE: stat about engine
395   *                          UA_DATA_OS: stat about OS
396   *                          UA_DATA_BROWSER_TYPE: stat about browser type
397   *   'day'       => return detailled stat per day
398   *   'uaVersion' => return detailled stat per version (browser version, os version, ...)
399   *
400   * @param Integer $mode: type of result needed
401   *                          . ASDF_GET_ROWS return an array of logs
402   *                          . ASDF_GET_COUNT return the number of logs
403   * @param Integer $page: page number
404   * @param Integer $nbItemsPage: number of items per page
405   * @param Array $fields : additional fields to be returned
406   * @param Array $filter : filters to apply => see getLogs function for usage
407   * @param Array $order: sort to apply      => see getLogs function for usage; all fields can be sorted
408   * @return
409   */
410  public function getStatUserAgent($mode=ASDF_GET_ROWS, $page=0, $nbItemsPage=0, $fields=array(), $filter=array(), $order=array())
411  {
412    switch($mode)
413    {
414      case ASDF_GET_COUNT:
415        $returned=0;
416        break;
417      case ASDF_GET_ROWS:
418        $returned=array();
419        break;
420    }
421    if($this->dbHandle==null) return($returned);
422
423    $select=array('uaData', 'SUM(visits) AS nbVisits');
424    $groupBy=array('uaData');
425    // initialize fields list
426    foreach($fields as $field)
427    {
428      if($field=='uaValue' or
429         $field=='day' or
430         $field=='uaVersion')
431      {
432        $select[]=$field;
433        $groupBy[]=$field;
434      }
435    }
436
437    // initialize filter
438    if(!is_array($filter)) $filter=array();
439
440    if(!isset($filter['uaData'])) $filter['uaData']=null;
441    if(!isset($filter['uaValue'])) $filter['uaValue']=null;
442    if(!isset($filter['day'])) $filter['day']=null;
443    if(!isset($filter['uaVersion'])) $filter['uaVersion']=null;
444
445    // check filter values - getOperator check and 'clean' the filter
446    $filter['uaData']=$this->getOperator($filter['uaData'], 'integer');
447    $filter['uaValue']=$this->getOperator($filter['uaValue'], 'integer');
448    $filter['day']=$this->getOperator($filter['day'], 'integer');
449    $filter['uaVersion']=$this->getOperator($filter['uaVersion'], 'string');
450
451
452    // initialize order
453    $orderBy=array();
454    if(!is_array($order)) $order=array();
455    foreach($order as $sort)
456    {
457      if(isset($sort['id']) and isset($sort['direction']))
458      {
459        if((($sort['id']=='uaData' or
460             $sort['id']=='day' or
461             $sort['id']=='uaVersion' or
462             $sort['id']=='uaValue' ) and
463            in_array($sort['id'], $select) or
464             $sort['id']=='nbVisits') and
465           ($sort['direction']=='A' or
466            $sort['direction']=='D')
467          ) $orderBy[]=$sort;
468      }
469    }
470    // set default order if nothing available is provided
471    if(count($orderBy)==0)
472    {
473      if(in_array('day', $select))
474        $orderBy[]=array('id'=>'day', 'direction'=>'A');
475      $orderBy[]=array('id'=>'nbVisits', 'direction'=>'D');
476    }
477
478    // build SELECT & GROUP By clauses
479    $select="SELECT ".implode(',', $select);
480    $groupBy=(count($groupBy)>0)?" GROUP BY ".implode(',', $groupBy):'';
481
482    //build ORDER BY clause
483    $orderBy=$this->buildOrderByClause($orderBy);
484
485    //build WHERE clause
486    $IPList=array();
487    $where=$this->buildWhereClause($filter, $IPList);
488
489    // build LIMIT clause
490    $limit=$this->buildLimitClause($page, $nbItemsPage);
491
492    // execute request
493    switch($mode)
494    {
495      case ASDF_GET_ROWS:
496          $sql=$select." FROM statua ".$where.$groupBy.$orderBy.$limit;
497
498          $sqlStm=$this->dbHandle->prepare($sql);
499
500          $result=$sqlStm->execute();
501          if($result)
502          {
503            while($row=$result->fetchArray(SQLITE3_ASSOC))
504            {
505              $returned[]=$row;
506            }
507          }
508        break;
509      case ASDF_GET_COUNT:
510          $sql="SELECT COUNT(*) AS nb
511                FROM statua $where;";
512
513          $sqlStm=$this->dbHandle->prepare($sql);
514
515          $result=$sqlStm->execute();
516          if($result)
517          {
518            while($row=$result->fetchArray(SQLITE3_ASSOC))
519            {
520              $returned=$row['nb'];
521            }
522          }
523        break;
524    }
525    return($returned);
526  }
527
528
529  /**
530   * returns stats from IP
531   *
532   * $page: the page number asked; first page is 1=>lower value means to get all values
533   * $nbItemsPage: the number of items returned per; 0 means no limit
534   *
535   *
536   * in ASDF_GET_ROWS mode, each returned logs is an array of asked fields
537   * at least, the following fields are always returned:
538   *  'nbVisits' => number of visits
539   *
540   * all fields are filterable, except 'nbVisits' that can't be filtered
541   *
542   * available fields values are:
543   *   'IPadress' => return the IP address
544   *   'day'      => return detailled stat per day
545   *   'uaType'   => return detailled stat per browser type
546   *   'country'  => return detailled stat per country
547   *   'catId'    => return detailled stat per category
548   *
549   * @param Integer $mode: type of result needed
550   *                          . ASDF_GET_ROWS return an array of logs
551   *                          . ASDF_GET_COUNT return the number of logs
552   * @param Integer $page: page number
553   * @param Integer $nbItemsPage: number of items per page
554   * @param Array $fields : additional fields to be returned
555   * @param Array $filter : filters to apply => see getLogs function for usage
556   * @param Array $order: sort to apply      => see getLogs function for usage; all fields can be sorted
557   * @return
558   */
559  public function getStatIP($mode=ASDF_GET_ROWS, $page=0, $nbItemsPage=0, $fields=array(), $filter=array(), $order=array())
560  {
561    switch($mode)
562    {
563      case ASDF_GET_COUNT:
564        $returned=0;
565        break;
566      case ASDF_GET_ROWS:
567        $returned=array();
568        break;
569    }
570    if($this->dbHandle==null) return($returned);
571
572    $select=array('SUM(visits) AS nbVisits');
573    $groupBy=array();
574    // initialize fields list
575    foreach($fields as $field)
576    {
577      if($field=='IPadress' or
578         $field=='day' or
579         $field=='catId' or
580         $field=='country' or
581         $field=='uaType')
582      {
583        $select[]=$field;
584        $groupBy[]=$field;
585      }
586    }
587
588    // initialize filter
589    if(!is_array($filter)) $filter=array();
590
591    if(!isset($filter['IPadress'])) $filter['IPadress']=null;
592    if(!isset($filter['day'])) $filter['day']=null;
593    if(!isset($filter['uaType'])) $filter['uaType']=null;
594    if(!isset($filter['catId'])) $filter['catId']=null;
595    if(!isset($filter['country'])) $filter['country']=null;
596
597    $filter['IPadress']=$this->checkIPFilter($filter['IPadress']);
598    // check filter values - getOperator check and 'clean' the filter
599    $filter['IPadress']=$this->getOperator($filter['IPadress'], 'IP');
600    $filter['country']=$this->getOperator($filter['country'], 'string');
601    $filter['day']=$this->getOperator($filter['day'], 'integer');
602    $filter['uaType']=$this->getOperator($filter['uaType'], 'integer');
603    $filter['catId']=$this->getOperator($filter['catId'], 'integer');
604
605    // initialize order
606    $orderBy=array();
607    if(!is_array($order)) $order=array();
608    foreach($order as $sort)
609    {
610      if(isset($sort['id']) and isset($sort['direction']))
611      {
612        if((($sort['id']=='IPadress' or
613             $sort['id']=='catId' or
614             $sort['id']=='country' or
615             $sort['id']=='day' or
616             $sort['id']=='uaType' ) and
617            in_array($sort['id'], $select) or
618             $sort['id']=='nbVisits') and
619           ($sort['direction']=='A' or
620            $sort['direction']=='D')
621          ) $orderBy[]=$sort;
622      }
623    }
624    // set default order if nothing available is provided
625    if(count($orderBy)==0)
626    {
627      if(in_array('day', $select))
628        $orderBy[]=array('id'=>'day', 'direction'=>'A');
629      $orderBy[]=array('id'=>'nbVisits', 'direction'=>'D');
630    }
631
632    // build SELECT & GROUP By clauses
633    $select="SELECT ".implode(',', $select);
634    $groupBy=(count($groupBy)>0)?" GROUP BY ".implode(',', $groupBy):'';
635
636    //build ORDER BY clause
637    $orderBy=$this->buildOrderByClause($orderBy);
638
639    //build WHERE clause
640    $IPList=array();
641    $where=$this->buildWhereClause($filter, $IPList);
642
643    // build LIMIT clause
644    $limit=$this->buildLimitClause($page, $nbItemsPage);
645
646    // execute request
647    switch($mode)
648    {
649      case ASDF_GET_ROWS:
650          $sql=$select." FROM statip ".$where.$groupBy.$orderBy.$limit;
651
652          $sqlStm=$this->dbHandle->prepare($sql);
653          foreach($IPList as $num=>$IP)
654          {
655            $sqlStm->bindValue(':IP'.$num, $IP, SQLITE3_BLOB);
656          }
657
658          $result=$sqlStm->execute();
659          if($result)
660          {
661            while($row=$result->fetchArray(SQLITE3_ASSOC))
662            {
663              if(isset($row['IPadress']))
664                $row['IPadress']=self::IPBinaryDecode($row['IPadress']);
665              $returned[]=$row;
666            }
667          }
668        break;
669      case ASDF_GET_COUNT:
670          $sql="SELECT COUNT(*) AS nb
671                FROM statip $where;";
672
673          $sqlStm=$this->dbHandle->prepare($sql);
674          foreach($IPList as $num=>$IP)
675          {
676            $sqlStm->bindValue(':IP'.$num, $IP, SQLITE3_BLOB);
677          }
678
679          $result=$sqlStm->execute();
680          if($result)
681          {
682            while($row=$result->fetchArray(SQLITE3_ASSOC))
683            {
684              $returned=$row['nb'];
685            }
686          }
687        break;
688    }
689    return($returned);
690  }
691
692
693
694  /**
695   * returns stats from categories
696   *
697   * $page: the page number asked; first page is 1=>lower value means to get all values
698   * $nbItemsPage: the number of items returned per; 0 means no limit
699   *
700   *
701   * in ASDF_GET_ROWS mode, each returned logs is an array of asked fields
702   * at least, the following fields are always returned:
703   *  'catId'    => category Id
704   *  'nbVisits' => number of visits
705   *
706   * all fields are filterable, except 'nbVisits' that can't be filtered
707   *
708   * available fields values are:
709   *   'day'      => return detailled stat per day
710   *   'uaType'   => return detailled stat per browser type
711   *
712   * @param Integer $mode: type of result needed
713   *                          . ASDF_GET_ROWS return an array of logs
714   *                          . ASDF_GET_COUNT return the number of logs
715   * @param Integer $page: page number
716   * @param Integer $nbItemsPage: number of items per page
717   * @param Array $fields : additional fields to be returned
718   * @param Array $filter : filters to apply => see getLogs function for usage
719   * @param Array $order: sort to apply      => see getLogs function for usage; all fields can be sorted
720   * @return
721   */
722  public function getStatCat($mode=ASDF_GET_ROWS, $page=0, $nbItemsPage=0, $fields=array(), $filter=array(), $order=array())
723  {
724    switch($mode)
725    {
726      case ASDF_GET_COUNT:
727        $returned=0;
728        break;
729      case ASDF_GET_ROWS:
730        $returned=array();
731        break;
732    }
733    if($this->dbHandle==null) return($returned);
734
735    $select=array('catId', 'SUM(visits) AS nbVisits');
736    $groupBy=array('catId');
737    // initialize fields list
738    foreach($fields as $field)
739    {
740      if($field=='day' or
741         $field=='uaType')
742      {
743        $select[]=$field;
744        $groupBy[]=$field;
745      }
746    }
747
748    // initialize filter
749    if(!is_array($filter)) $filter=array();
750
751    if(!isset($filter['day'])) $filter['day']=null;
752    if(!isset($filter['uaType'])) $filter['uaType']=null;
753
754    // check filter values - getOperator check and 'clean' the filter
755    $filter['day']=$this->getOperator($filter['day'], 'integer');
756    $filter['uaType']=$this->getOperator($filter['uaType'], 'integer');
757
758
759    // initialize order
760    $orderBy=array();
761    if(!is_array($order)) $order=array();
762    foreach($order as $sort)
763    {
764      if(isset($sort['id']) and isset($sort['direction']))
765      {
766        if((($sort['id']=='day' or
767             $sort['id']=='uaType' ) and
768            in_array($sort['id'], $select) or
769             $sort['id']=='nbVisits') and
770           ($sort['direction']=='A' or
771            $sort['direction']=='D')
772          ) $orderBy[]=$sort;
773      }
774    }
775    // set default order if nothing available is provided
776    if(count($orderBy)==0)
777    {
778      if(in_array('day', $select))
779        $orderBy[]=array('id'=>'day', 'direction'=>'A');
780      $orderBy[]=array('id'=>'nbVisits', 'direction'=>'D');
781    }
782
783    // build SELECT & GROUP By clauses
784    $select="SELECT ".implode(',', $select);
785    $groupBy=(count($groupBy)>0)?" GROUP BY ".implode(',', $groupBy):'';
786
787    //build ORDER BY clause
788    $orderBy=$this->buildOrderByClause($orderBy);
789
790    //build WHERE clause
791    $IPList=array();
792    $where=$this->buildWhereClause($filter, $IPList);
793
794    // build LIMIT clause
795    $limit=$this->buildLimitClause($page, $nbItemsPage);
796
797    // execute request
798    switch($mode)
799    {
800      case ASDF_GET_ROWS:
801          $sql=$select." FROM statcategories ".$where.$groupBy.$orderBy.$limit;
802
803          $sqlStm=$this->dbHandle->prepare($sql);
804
805          $result=$sqlStm->execute();
806          if($result)
807          {
808            while($row=$result->fetchArray(SQLITE3_ASSOC))
809            {
810              $returned[]=$row;
811            }
812          }
813        break;
814      case ASDF_GET_COUNT:
815          $sql="SELECT COUNT(*) AS nb
816                FROM statcategories $where;";
817
818          $sqlStm=$this->dbHandle->prepare($sql);
819
820          $result=$sqlStm->execute();
821          if($result)
822          {
823            while($row=$result->fetchArray(SQLITE3_ASSOC))
824            {
825              $returned=$row['nb'];
826            }
827          }
828        break;
829    }
830    return($returned);
831  }
832
833
834
835
836  /**
837   * returns stats from images
838   *
839   *
840   * $page: the page number asked; first page is 1=>lower value means to get all values
841   * $nbItemsPage: the number of items returned per; 0 means no limit
842   *
843   *
844   * in ASDF_GET_ROWS mode, each returned logs is an array of asked fields
845   * at least, the following fields are always returned:
846   *  'imageId'  => image Id
847   *  'nbVisits' => number of visits
848   *
849   * all fields are filterable, except 'nbVisits' that can't be filtered
850   *
851   * available fields values are:
852   *   'day'      => return detailled stat per day
853   *   'uaType'   => return detailled stat per browser type
854   *   'catId'    => return detailled stat per categories (an image could be linked with more than one category)
855   *
856   * @param Integer $mode: type of result needed
857   *                          . ASDF_GET_ROWS return an array of logs
858   *                          . ASDF_GET_COUNT return the number of logs
859   * @param Integer $page: page number
860   * @param Integer $nbItemsPage: number of items per page
861   * @param Array $fields : additional fields to be returned
862   * @param Array $filter : filters to apply => see getLogs function for usage
863   * @param Array $order: sort to apply      => see getLogs function for usage; all fields can be sorted
864   * @return
865   */
866  public function getStatImages($mode=ASDF_GET_ROWS, $page=0, $nbItemsPage=0, $fields=array(), $filter=array(), $order=array())
867  {
868    switch($mode)
869    {
870      case ASDF_GET_COUNT:
871        $returned=0;
872        break;
873      case ASDF_GET_ROWS:
874        $returned=array();
875        break;
876    }
877    if($this->dbHandle==null) return($returned);
878
879    $select=array('imageId', 'SUM(visits) AS nbVisits');
880    $groupBy=array('imageId');
881    // initialize fields list
882    foreach($fields as $field)
883    {
884      if($field=='day' or
885         $field=='catId' or
886         $field=='uaType')
887      {
888        $select[]=$field;
889        $groupBy[]=$field;
890      }
891    }
892
893    // initialize filter
894    if(!is_array($filter)) $filter=array();
895
896    if(!isset($filter['day'])) $filter['day']=null;
897    if(!isset($filter['catId'])) $filter['catId']=null;
898    if(!isset($filter['uaType'])) $filter['uaType']=null;
899
900    // check filter values - getOperator check and 'clean' the filter
901    $filter['day']=$this->getOperator($filter['day'], 'integer');
902    $filter['catId']=$this->getOperator($filter['catId'], 'integer');
903    $filter['uaType']=$this->getOperator($filter['uaType'], 'integer');
904
905
906    // initialize order
907    $orderBy=array();
908    if(!is_array($order)) $order=array();
909    foreach($order as $sort)
910    {
911      if(isset($sort['id']) and isset($sort['direction']))
912      {
913        if((($sort['id']=='day' or
914             $sort['id']=='catId' or
915             $sort['id']=='uaType' ) and
916            in_array($sort['id'], $select) or
917             $sort['id']=='nbVisits') and
918           ($sort['direction']=='A' or
919            $sort['direction']=='D')
920          ) $orderBy[]=$sort;
921      }
922    }
923    // set default order if nothing available is provided
924    if(count($orderBy)==0)
925    {
926      if(in_array('day', $select))
927        $orderBy[]=array('id'=>'day', 'direction'=>'A');
928      $orderBy[]=array('id'=>'nbVisits', 'direction'=>'D');
929    }
930
931    // build SELECT & GROUP By clauses
932    $select="SELECT ".implode(',', $select);
933    $groupBy=(count($groupBy)>0)?" GROUP BY ".implode(',', $groupBy):'';
934
935    //build ORDER BY clause
936    $orderBy=$this->buildOrderByClause($orderBy);
937
938    //build WHERE clause
939    $IPList=array();
940    $where=$this->buildWhereClause($filter, $IPList);
941
942    // build LIMIT clause
943    $limit=$this->buildLimitClause($page, $nbItemsPage);
944
945    // execute request
946    switch($mode)
947    {
948      case ASDF_GET_ROWS:
949          $sql=$select." FROM statimages ".$where.$groupBy.$orderBy.$limit;
950
951          $sqlStm=$this->dbHandle->prepare($sql);
952
953          $result=$sqlStm->execute();
954          if($result)
955          {
956            while($row=$result->fetchArray(SQLITE3_ASSOC))
957            {
958              $returned[]=$row;
959            }
960          }
961        break;
962      case ASDF_GET_COUNT:
963          $sql="SELECT COUNT(*) AS nb
964                FROM statimages $where;";
965
966          $sqlStm=$this->dbHandle->prepare($sql);
967
968          $result=$sqlStm->execute();
969          if($result)
970          {
971            while($row=$result->fetchArray(SQLITE3_ASSOC))
972            {
973              $returned=$row['nb'];
974            }
975          }
976        break;
977    }
978    return($returned);
979  }
980
981
982
983
984
985
986  /**
987   * returns stats for a period
988   *
989   * $page: the page number asked; first page is 1=>lower value means to get all values
990   * $nbItemsPage: the number of items returned per; 0 means no limit
991   *
992   *
993   * each returned logs is an array of asked fields
994   * at least, the following fields are always returned:
995   *  'nbVisits' => number of visits
996   *
997   * all fields are filterable, except 'nbVisits' that can't be filtered
998   *
999   * available fields values are:
1000   *   'day'       => return detailled stat per day
1001   *   'catId'     => return detailled stat per category
1002   *
1003   * @param Integer $page: page number
1004   * @param Integer $nbItemsPage: number of items per page
1005   * @param Array $fields : additional fields to be returned
1006   * @param Array $filter : filters to apply => see getLogs function for usage
1007   * @param Array $order: sort to apply      => see getLogs function for usage; all fields can be sorted
1008   * @return
1009   */
1010  public function getStatPeriod($page=0, $nbItemsPage=0, $fields=array(), $filter=array(), $order=array())
1011  {
1012    $returned=array();
1013    if($this->dbHandle==null) return($returned);
1014
1015    /*
1016     * total: 'T' variables
1017     * categories: 'C' variables
1018     * images 'I' variables
1019     * ip adresses: 'A' variables
1020     */
1021    $select=array(
1022      'T' => array('"T" AS nfoType', 'SUM(visits) AS nbVisits'),
1023      'C' => array('"C" AS nfoType', 'SUM(visits) AS nbVisits'),
1024      'I' => array('"I" AS nfoType', 'SUM(visits) AS nbVisits'),
1025      'A' => array('"A" AS nfoType', 'COUNT(DISTINCT IPadress) AS nbVisits')
1026    );
1027
1028    $groupBy=array();
1029    // initialize fields list
1030    foreach($fields as $field)
1031    {
1032      if($field=='day')
1033      {
1034        $select['T'][]=$field;
1035        $select['C'][]=$field;
1036        $select['I'][]=$field;
1037        $select['A'][]=$field;
1038        $groupBy[]=$field;
1039      }
1040    }
1041
1042    // initialize filter
1043    if(!is_array($filter)) $filter=array();
1044    $filter['T']=array();
1045    $filter['C']=array();
1046    $filter['I']=array();
1047    $filter['A']=array();
1048
1049    if(!isset($filter['day'])) $filter['day']=null;
1050    if(!isset($filter['catId'])) $filter['catId']=null;
1051
1052    foreach(array('T', 'C', 'I', 'A') as $key)
1053    {
1054      $filter[$key]['day']=$this->getOperator($filter['day'], 'integer');
1055      if($key=='C' and $filter['catId']==null)
1056      {
1057        $filter[$key]['catId']=$this->getOperator(array('operator' => '>', 'value' => 0), 'integer');
1058      }
1059      else
1060      {
1061        $filter[$key]['catId']=$this->getOperator($filter['catId'], 'integer');
1062      }
1063    }
1064
1065    // initialize order
1066    $orderBy=array();
1067    if(!is_array($order)) $order=array();
1068    foreach($order as $sort)
1069    {
1070      if(isset($sort['id']) and isset($sort['direction']))
1071      {
1072        if(($sort['id']=='day' and
1073            in_array($sort['id'], $select['T']) or
1074             $sort['id']=='nbVisits') and
1075           ($sort['direction']=='A' or
1076            $sort['direction']=='D')
1077          ) $orderBy[]=$sort;
1078      }
1079    }
1080    // set default order if nothing available is provided
1081    if(count($orderBy)==0)
1082    {
1083      if(in_array('day', $select['T']))
1084        $orderBy[]=array('id'=>'day', 'direction'=>'A');
1085      $orderBy[]=array('id'=>'nbVisits', 'direction'=>'D');
1086    }
1087
1088    // build SELECT & GROUP By clauses
1089    foreach($select as $key => $val)
1090    {
1091      $select[$key]="SELECT ".implode(',', $val);
1092    }
1093    $groupBy=(count($groupBy)>0)?" GROUP BY ".implode(',', $groupBy):'';
1094
1095    //build ORDER BY clause
1096    $orderBy=$this->buildOrderByClause($orderBy);
1097
1098    //build WHERE clause
1099    $IPList=array();
1100    $where=array(
1101      'T' => $this->buildWhereClause($filter['T'], $IPList),
1102      'C' => $this->buildWhereClause($filter['C'], $IPList),
1103      'I' => $this->buildWhereClause($filter['I'], $IPList),
1104      'A' => $this->buildWhereClause($filter['A'], $IPList)
1105    );
1106
1107    // build LIMIT clause
1108    $limit=$this->buildLimitClause($page, $nbItemsPage);
1109
1110
1111    $sql=$select['T']." FROM statcategories ".$where['T'].$groupBy;
1112    $sql.=' UNION '.$select['C']." FROM statcategories ".$where['C'].$groupBy;
1113    $sql.=' UNION '.$select['I']." FROM statimages ".$where['I'].$groupBy;
1114    $sql.=' UNION '.$select['A']." FROM statip ".$where['A'].$groupBy;
1115    $sql.=$orderBy;  //.$limit => removed because the limit have to be set on the total result
1116
1117    $sqlStm=$this->dbHandle->prepare($sql);
1118
1119    $result=$sqlStm->execute();
1120    if($result)
1121    {
1122      $sqlResult=array();
1123      while($row=$result->fetchArray(SQLITE3_ASSOC))
1124      {
1125        $sqlResult[]=$row;
1126      }
1127
1128      /*
1129       * $returned have a row per period & info type T,C,I,A
1130       *
1131       * example:
1132       *   01 T 25
1133       *   01 C 10
1134       *   01 I 45
1135       *   01 A 4
1136       *   14 T 8
1137       *   14 C 6
1138       *   14 A 1
1139       *   28 T 1
1140       *   28 A 1
1141       *
1142       * the result is built as a table with:
1143       *  - info type in column
1144       *  - missing periods
1145       *
1146       * example:
1147       *   period   T   C   I   A
1148       *   01       25  10  45  4
1149       *   02       0   0   0   0
1150       *   03       0   0   0   0
1151       *   04       0   0   0   0
1152       *   ...
1153       *   14       8   6   0   1
1154       *   ...
1155       *   28       1   0   0   1
1156       */
1157
1158      // first step, build a period list
1159      if(in_array('day', $fields))
1160      {
1161        for($d=1;$d<=$this->nbDaysMonth;$d++)
1162        {
1163          $returned[$d]=array(
1164            'T' => 0,
1165            'C' => 0,
1166            'I' => 0,
1167            'A' => 0
1168          );
1169        }
1170      }
1171      else
1172      {
1173        $returned=array(
1174          0 => array( // no day => 0
1175                'T' => 0,
1176                'C' => 0,
1177                'I' => 0,
1178                'A' => 0
1179            )
1180        );
1181      }
1182
1183      // next step, fill the table
1184      foreach($sqlResult as $row)
1185      {
1186        if(isset($row['day']))
1187        {
1188          $d=$row['day'];
1189        }
1190        else
1191        {
1192          $d=0;
1193        }
1194
1195        $returned[$d][$row['nfoType']]=$row['nbVisits'];
1196      }
1197
1198    }
1199    return($returned);
1200  }
1201
1202
1203
1204
1205
1206
1207
1208  /**
1209   * set country for IPadress in statip table
1210   *
1211   * @return Boolean: true if ok, otherwise false
1212   */
1213  public function buildIPCountry()
1214  {
1215    if($this->dbHandle==null or $this->ipCountryFile=='') return(false);
1216
1217    $result=$this->dbHandle->exec("ATTACH '".$this->ipCountryFile."' AS ipCountry");
1218    if($result)
1219    {
1220      /* -----------------------------------------------------------------------
1221       * SQLite doesn't allow to update a table with data from another table
1222       * sub-query is very slow, so the method:
1223       *  1) create an indexed temp table with the same structure than statip
1224       *  2) fill the temp table with records from statip table where country is empty
1225       *  3) do a select, join the temp table and the IP country table; completed result
1226       *     replace the content of the temp table
1227       *  4) records from temp table replace the linked records of the statip table
1228       *  5) delete temp table
1229       * ----------------------------------------------------------------------- */
1230
1231      $sql="
1232        -- start a transaction, if something is wrong database won't be poluted
1233        BEGIN TRANSACTION;
1234
1235        --log build command
1236        REPLACE INTO main.info (domain, key, value)
1237          VALUES('log',
1238                 'buildIPCountry()',
1239                 '".date('Y-m-d H:i:s')."');
1240
1241        UPDATE info
1242        SET value=value+1
1243        WHERE domain = 'log'
1244          AND key = 'buildIPCountry-count';
1245
1246        -- drop temp table if exists
1247        DROP TABLE IF EXISTS tmpIp;
1248
1249        -- create a temp table with records without country code
1250        CREATE TEMPORARY TABLE tmpIp AS
1251          SELECT * FROM statip WHERE country='';
1252        -- create index to optimize next requests
1253        CREATE INDEX iIpTmp ON tmpIp ('IPadress');
1254        CREATE UNIQUE INDEX iIpTmp2 ON tmpIp ('uaType', 'IPadress', 'catId', 'day');
1255
1256        -- set country for each record of the temp table
1257        REPLACE INTO tmpIp (uaType, IPadress, catId, `day`, visits, country)
1258          SELECT si.uaType, si.IPadress, si.catId, si.day, si.visits, il.country
1259          FROM ipCountry.iplist il, tmpIp si
1260          WHERE si.IPadress BETWEEN il.rangeStart AND il.rangeEnd;
1261
1262        -- set country for each record of the final table (from temp table)
1263        REPLACE INTO statip (uaType, IPadress, catId, `day`, visits, country)
1264          SELECT si.uaType, si.IPadress, si.catId, si.day, si.visits, si.country
1265          FROM tmpIp si;
1266
1267        -- delete temp table
1268        DROP TABLE IF EXISTS tmpIp;
1269
1270        -- update the logs table for rows with unset country
1271        -- use a simple sub select here, assuming that it's quick enough for the update
1272        UPDATE logs
1273        SET country=(SELECT sip.country FROM statip sip WHERE logs.IPadress = sip.IPadress)
1274        WHERE country='';
1275
1276        -- commit changes
1277        COMMIT TRANSACTION;
1278      ";
1279      $returned=$this->dbHandle->exec($sql);
1280
1281      if(!$this->dbHandle->exec("DETACH ipCountry")) $returned=false;
1282
1283      return($returned);
1284    }
1285    return(false);
1286  }
1287
1288
1289  /**
1290   * check the database schema; update it if needed
1291   *
1292   * @return Boolean: true if OK, otherwise false
1293   */
1294  protected function checkSchema()
1295  {
1296    if(!parent::checkSchema()) return(false);
1297
1298    $version=$this->getInfoProperty('nfo', 'version');
1299
1300    switch($version)
1301    {
1302      case '00.00.00':
1303        // version 00.00.00
1304        //  file is just created...
1305        $result=$this->getDBInfo(ASDF_DB_TYPE_TABLE, 'logs', ASDF_DB_INFO);
1306        if(count($result)==0)
1307        {
1308          $this->dbHandle->exec(
1309              "CREATE TABLE 'logs' (
1310                  'id' INTEGER PRIMARY KEY,
1311                  'date' INTEGER,
1312                  'IPadress' BLOB,
1313                  'country' TEXT,
1314                  'userId' INTEGER,
1315                  'catId' INTEGER,
1316                  'imageId' INTEGER,
1317                  'tagsId' TEXT,
1318                  'section' TEXT,
1319                  'userAgent' TEXT,
1320                  'uaBrowser' INTEGER,
1321                  'uaBrowserVersion' TEXT,
1322                  'uaEngine' INTEGER,
1323                  'uaEngineVersion' TEXT,
1324                  'uaOS' INTEGER,
1325                  'uaOSVersion' TEXT,
1326                  'uaType' INTEGER,
1327                  'screenSizeW' INTEGER,
1328                  'screenSizeH' INTEGER
1329              );"
1330            );
1331          $this->dbHandle->exec("CREATE INDEX iDateIP ON logs ('date', 'IPadress');");
1332          $this->dbHandle->exec("CREATE INDEX iIPCountry ON logs ('IPadress', 'country');");
1333          $this->dbHandle->exec("CREATE INDEX iUAB ON logs ('uaType', 'uaBrowser', 'uaEngine');");
1334          $this->dbHandle->exec("CREATE INDEX iUAO ON logs ('uaOS');");
1335        }
1336
1337        $result=$this->getDBInfo(ASDF_DB_TYPE_TABLE, 'statCategories', ASDF_DB_INFO);
1338        if(count($result)==0)
1339        {
1340          $this->dbHandle->exec(
1341              "CREATE TABLE 'statCategories' (
1342                  'catId' INTEGER,
1343                  'uaType' INTEGER,
1344                  'day' INTEGER,
1345                  'visits' INTEGER
1346              );"
1347            );
1348          $this->dbHandle->exec("CREATE UNIQUE INDEX iCat ON statCategories ('catId', 'uaType', 'day');");
1349        }
1350
1351        $result=$this->getDBInfo(ASDF_DB_TYPE_TABLE, 'statImages', ASDF_DB_INFO);
1352        if(count($result)==0)
1353        {
1354          $this->dbHandle->exec(
1355              "CREATE TABLE 'statImages' (
1356                  'imageId' INTEGER,
1357                  'catId' INTEGER,
1358                  'uaType' INTEGER,
1359                  'day' INTEGER,
1360                  'visits' INTEGER
1361              );"
1362            );
1363          $this->dbHandle->exec("CREATE UNIQUE INDEX iImg ON statImages ('imageId', 'catId', 'uaType', 'day');");
1364        }
1365
1366        $result=$this->getDBInfo(ASDF_DB_TYPE_TABLE, 'statIP', ASDF_DB_INFO);
1367        if(count($result)==0)
1368        {
1369          $this->dbHandle->exec(
1370              "CREATE TABLE 'statIP' (
1371                  'uaType' INTEGER,
1372                  'IPadress' BLOB,
1373                  'catId' INTEGER,
1374                  'day' INTEGER,
1375                  'visits' INTEGER,
1376                  'country' TEXT
1377              );"
1378            );
1379          $this->dbHandle->exec("CREATE UNIQUE INDEX iIP ON statIP ('uaType', 'IPadress', 'catId', 'day');");
1380          $this->dbHandle->exec("CREATE INDEX iIPAdress ON statIP ('IPadress');");
1381        }
1382
1383        $result=$this->getDBInfo(ASDF_DB_TYPE_TABLE, 'statUA', ASDF_DB_INFO);
1384        if(count($result)==0)
1385        {
1386          $this->dbHandle->exec(
1387              "CREATE TABLE 'statUA' (
1388                  'uaData' INTEGER,
1389                  'uaValue' INTEGER,
1390                  'uaVersion' TEXT,
1391                  'day' INTEGER,
1392                  'visits' INTEGER
1393              );"
1394            );
1395          $this->dbHandle->exec("CREATE UNIQUE INDEX iUA ON statUA ('uaData', 'uaValue', 'uaVersion', 'day');");
1396        }
1397
1398        if($this->getDBInfo(ASDF_DB_TYPE_TRIGGER, 'insertLogs')==0)
1399        {
1400          $this->dbHandle->exec("
1401            CREATE TRIGGER insertLogs
1402            AFTER INSERT ON logs
1403            BEGIN
1404              INSERT OR IGNORE INTO statCategories (catId, uaType, day, visits)
1405              VALUES (new.catId, new.uaType, strftime('%d',new.date, 'unixepoch', 'localtime'), 0);
1406
1407              UPDATE statCategories
1408              SET visits = visits+1
1409              WHERE catId = new.catId
1410                AND uaType = new.uaType
1411                AND day = strftime('%d',new.date, 'unixepoch', 'localtime');
1412
1413              INSERT OR IGNORE INTO statIP (uaType, IPadress, catId, day, visits, country)
1414              VALUES (new.uaType, new.IPadress, new.catId, strftime('%d',new.date, 'unixepoch', 'localtime'), 0, '');
1415
1416              UPDATE statIP
1417              SET visits = visits+1
1418              WHERE uaType = new.uaType
1419                AND IPadress = new.IPadress
1420                AND catId = new.catId
1421                AND day = strftime('%d',new.date, 'unixepoch', 'localtime');
1422
1423              -- multiple insert values doesn't work? then using select+union
1424              INSERT OR IGNORE INTO statUA (uaData, uaValue, uaVersion, day, visits)
1425                SELECT 1, new.uaBrowser, new.uaBrowserVersion, strftime('%d',new.date, 'unixepoch', 'localtime'), 0
1426                  UNION
1427                SELECT 2, new.uaEngine, new.uaEngineVersion, strftime('%d',new.date, 'unixepoch', 'localtime'), 0
1428                  UNION
1429                SELECT 3, new.uaOS, new.uaOSVersion, strftime('%d',new.date, 'unixepoch', 'localtime'), 0
1430                  UNION
1431                SELECT 49, new.uaType, '', strftime('%d',new.date, 'unixepoch', 'localtime'), 0;
1432
1433              -- note: 49=0x0031=UA_DATA_BROWSER_TYPE value
1434
1435              UPDATE statUA
1436              SET visits = visits+1
1437              WHERE uaData = 1 AND uaValue = new.uaBrowser AND uaVersion=new.uaBrowserVersion AND day = strftime('%d',new.date, 'unixepoch', 'localtime')
1438                OR uaData = 2 AND uaValue = new.uaEngine AND uaVersion=new.uaEngineVersion AND day = strftime('%d',new.date, 'unixepoch', 'localtime')
1439                OR uaData = 3 AND uaValue = new.uaOS AND uaVersion=new.uaOSVersion AND day = strftime('%d',new.date, 'unixepoch', 'localtime')
1440                OR uaData = 49 AND uaValue = new.uaType AND day = strftime('%d',new.date, 'unixepoch', 'localtime');
1441
1442            END;
1443          ");
1444        }
1445        if($this->getDBInfo(ASDF_DB_TYPE_TRIGGER, 'insertLogsImg')==0)
1446        {
1447          $this->dbHandle->exec("
1448            CREATE TRIGGER insertLogsImg
1449            AFTER INSERT ON logs
1450            WHEN new.imageId > 0
1451            BEGIN
1452              INSERT OR IGNORE INTO statImages (imageId, catId, uaType, day, visits)
1453              VALUES (new.imageId, new.catId, new.uaType, strftime('%d',new.date, 'unixepoch', 'localtime'), 0);
1454
1455              UPDATE statImages
1456              SET visits = visits+1
1457              WHERE imageId = new.imageId
1458                AND catId = new.catId
1459                AND uaType = new.uaType
1460                AND day = strftime('%d',new.date, 'unixepoch', 'localtime');
1461            END;
1462          ");
1463        }
1464
1465        $this->setInfoProperty('nfo', 'version', '01.00.00');
1466        return(true);
1467        break;
1468      default:
1469        break;
1470    }
1471    return(false);
1472  }
1473
1474} // class
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484?>
Note: See TracBrowser for help on using the repository browser.