1 | <?php |
---|
2 | |
---|
3 | require_once('statDB.class.inc.php'); |
---|
4 | |
---|
5 | /** |
---|
6 | * specific class for SQLite monthly stat managment |
---|
7 | */ |
---|
8 | class 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 | ?> |
---|