[17737] | 1 | <?php |
---|
| 2 | /* ----------------------------------------------------------------------------- |
---|
| 3 | Plugin : EStat |
---|
| 4 | Author : Grum |
---|
| 5 | email : grum@piwigo.org |
---|
| 6 | website : http://www.grum.fr |
---|
| 7 | |
---|
| 8 | << May the Little SpaceFrog be with you ! >> |
---|
| 9 | ------------------------------------------------------------------------------ |
---|
| 10 | See main.inc.php for release information |
---|
| 11 | |
---|
| 12 | EStat_root : common classe for admin and public classes |
---|
| 13 | |
---|
| 14 | --------------------------------------------------------------------------- */ |
---|
| 15 | include_once(PHPWG_PLUGINS_PATH.'GrumPluginClasses/classes/CommonPlugin.class.inc.php'); |
---|
| 16 | include_once(ESTAT_LIB.'statDB.class.inc.php'); |
---|
| 17 | include_once(ESTAT_LIB.'statDBGlobal.class.inc.php'); |
---|
| 18 | include_once(ESTAT_LIB.'statDBMonth.class.inc.php'); |
---|
| 19 | include_once(ESTAT_LIB.'statDBCountry.class.inc.php'); |
---|
| 20 | |
---|
| 21 | class EStat_root extends CommonPlugin |
---|
| 22 | { |
---|
| 23 | const DATA_DIRECTORY='plugins/EStat/data/'; |
---|
| 24 | const EXPORT_DIRECTORY='plugins/EStat/export/'; |
---|
| 25 | const FILE_MONTH='ES-M'; |
---|
| 26 | const FILE_GLOBAL='ES-G'; |
---|
| 27 | const FILE_COUNTRY='ES-IPCountry'; |
---|
| 28 | |
---|
| 29 | public $countryCodes=array( |
---|
| 30 | 'AD','AE','AF','AG','AI','AL','AM','AO','AQ','AR','AS','AT','AU','AW','AX','AZ', |
---|
| 31 | 'BA','BB','BD','BE','BF','BG','BH','BI','BJ','BL','BM','BN','BO','BQ','BR','BS','BT','BV','BW','BY','BZ', |
---|
| 32 | 'CA','CC','CD','CF','CG','CH','CI','CK','CL','CM','CN','CO','CR','CU','CV','CW','CX','CY','CZ', |
---|
| 33 | 'DE','DJ','DK','DM','DO','DZ', |
---|
| 34 | 'EC','EE','EG','EH','ER','ES','ET', |
---|
| 35 | 'FI','FJ','FK','FM','FO','FR', |
---|
| 36 | 'GA','GB','GD','GE','GF','GG','GH','GI','GL','GM','GN','GP','GQ','GR','GS','GT','GU','GW','GY', |
---|
| 37 | 'HK','HM','HN','HR','HT','HU', |
---|
| 38 | 'ID','IE','IL','IM','IN','IO','IQ','IR','IS','IT', |
---|
| 39 | 'JE','JM','JO','JP', |
---|
| 40 | 'KE','KG','KH','KI','KM','KN','KP','KR','KW','KY','KZ', |
---|
| 41 | 'LA','LB','LC','LI','LK','LR','LS','LT','LU','LV','LY', |
---|
| 42 | 'MA','MC','MD','ME','MF','MG','MH','MK','ML','MM','MN','MO','MP','MQ','MR','MS','MT','MU','MV','MW','MX','MY','MZ', |
---|
| 43 | 'NA','NC','NE','NF','NG','NI','NL','NO','NP','NR','NU','NZ', |
---|
| 44 | 'OM', |
---|
| 45 | 'PA','PE','PF','PG','PH','PK','PL','PM','PN','PR','PS','PT','PW','PY', |
---|
| 46 | 'QA', |
---|
| 47 | 'RE','RO','RS','RU','RW', |
---|
| 48 | 'SA','SB','SC','SD','SE','SG','SH','SI','SJ','SK','SL','SM','SN','SO','SR','SS','ST','SV','SX','SY','SZ', |
---|
| 49 | 'TC','TD','TF','TG','TH','TJ','TK','TL','TM','TN','TO','TR','TT','TV','TW','TZ', |
---|
| 50 | 'UA','UG','UM','US','UY','UZ', |
---|
| 51 | 'VA','VC','VE','VG','VI','VN','VU', |
---|
| 52 | 'WF','WS', |
---|
| 53 | 'XA', |
---|
| 54 | 'YE','YT', |
---|
| 55 | 'ZA','ZM','ZW' |
---|
| 56 | ); |
---|
| 57 | |
---|
| 58 | protected $fileStatDir=''; |
---|
[17758] | 59 | protected $fileExportDir=''; |
---|
[17737] | 60 | |
---|
| 61 | public function __construct($prefixeTable, $filelocation) |
---|
| 62 | { |
---|
| 63 | $this->setPluginName('EStat'); |
---|
| 64 | $this->setPluginNameFiles("estat"); |
---|
| 65 | parent::__construct($prefixeTable, $filelocation); |
---|
[17758] | 66 | $this->loadConfig(); |
---|
[17737] | 67 | $this->section_name=$this->getPluginNameFiles(); |
---|
[17758] | 68 | $this->setFileStatDir(); |
---|
[17737] | 69 | } |
---|
| 70 | |
---|
| 71 | /** |
---|
| 72 | * initialize default values |
---|
| 73 | */ |
---|
| 74 | public function initConfig() |
---|
| 75 | { |
---|
[17758] | 76 | global $user; |
---|
| 77 | |
---|
| 78 | $lang=''; |
---|
| 79 | if(isset($user['language'])) $lang=$user['language']; |
---|
| 80 | |
---|
| 81 | switch($lang) |
---|
| 82 | { |
---|
| 83 | case 'fr_FR': |
---|
| 84 | $csvExport=array( |
---|
| 85 | 'export.csv.separator' => ';', |
---|
| 86 | 'export.csv.decimalDot' => ',' |
---|
| 87 | ); |
---|
| 88 | break; |
---|
| 89 | default: |
---|
| 90 | $csvExport=array( |
---|
| 91 | 'export.csv.separator' => ',', |
---|
| 92 | 'export.csv.decimalDot' => '.' |
---|
| 93 | ); |
---|
| 94 | break; |
---|
| 95 | } |
---|
| 96 | |
---|
[17737] | 97 | $this->config=array( |
---|
[17758] | 98 | 'installed' => '00.00.00', |
---|
[17737] | 99 | 'plugin.newInstall' => 'y', |
---|
| 100 | 'plugin.active' => 'n', |
---|
| 101 | 'plugin.historyImported' => 'n', |
---|
| 102 | 'plugin.ipCountryBuild' => 'n', |
---|
[17758] | 103 | 'plugin.pathKey' => '', // key to be used to know path where are stored the SQLite files |
---|
[17737] | 104 | |
---|
| 105 | 'build.delay' => '+24hours', // delay between 2 consolidation |
---|
| 106 | 'build.start' => '2:30:00', // consolidation can be done from |
---|
| 107 | 'build.end' => '6:30:00', // build.start hour to build.end hour |
---|
| 108 | 'compress.public' => 'n', // compress file in public session |
---|
[17862] | 109 | 'compress.method' => 'gz', // none, gz |
---|
[17737] | 110 | |
---|
[17862] | 111 | 'global.itemPerPage' => 150, |
---|
[17737] | 112 | |
---|
[17758] | 113 | 'export.csv.separator' => $csvExport['export.csv.separator'], |
---|
| 114 | 'export.csv.decimalDot' => $csvExport['export.csv.decimalDot'], |
---|
| 115 | 'export.csv.useQuotes' => 'y', |
---|
| 116 | 'export.csv.lineFeed' => 'unix', |
---|
| 117 | 'export.ods.fileTitle' => '', |
---|
| 118 | 'export.ods.keywords' => '', |
---|
| 119 | |
---|
[17737] | 120 | 'logs.reverseDNS' => 'n', |
---|
| 121 | 'logs.ipCountry' => 'y' |
---|
| 122 | ); |
---|
| 123 | } |
---|
| 124 | |
---|
| 125 | /** |
---|
| 126 | * return admin link |
---|
| 127 | * @param String $mode: if equal 'ajax' return url for ajax call |
---|
| 128 | * @return String: url |
---|
| 129 | */ |
---|
| 130 | public function getAdminLink($mode='') |
---|
| 131 | { |
---|
| 132 | switch($mode) |
---|
| 133 | { |
---|
| 134 | case 'ajax': |
---|
| 135 | return('plugins/'.basename(dirname($this->getFileLocation())).'/estat_ajax.php'); |
---|
| 136 | break; |
---|
| 137 | case 'ajaxExport': |
---|
| 138 | return('plugins/'.basename(dirname($this->getFileLocation())).'/estat_ajax_export.php'); |
---|
| 139 | break; |
---|
| 140 | default: |
---|
| 141 | return(parent::getAdminLink()); |
---|
| 142 | break; |
---|
| 143 | } |
---|
| 144 | } |
---|
| 145 | |
---|
| 146 | |
---|
| 147 | |
---|
| 148 | /** |
---|
| 149 | * checks files that need to be consolidated |
---|
| 150 | * pack them if needed |
---|
| 151 | * |
---|
| 152 | * @param Boolean $force: force consolidation if true, otherwise let system to determinate if needed |
---|
| 153 | * @param Boolean $pack: pack files if needed |
---|
| 154 | * @return Boolean: true if at least one consolidation was applied, otherwise false |
---|
| 155 | */ |
---|
| 156 | protected function checkBuildStatPeriod($force=false, $pack=true) |
---|
| 157 | { |
---|
| 158 | $build=false; |
---|
| 159 | $currentTime=date('H:i:s'); |
---|
| 160 | $currentDateTime=strtotime($this->config['build.delay']); |
---|
| 161 | $currentYearMonth=date('Ym'); |
---|
| 162 | |
---|
| 163 | |
---|
| 164 | $dbStatG=new StatDBGlobal($this->fileStatDir, self::FILE_GLOBAL); |
---|
| 165 | $dbStatG->open(ASDF_OPEN_WRITE); |
---|
| 166 | |
---|
| 167 | // check if current period exist in global file |
---|
| 168 | $dbStatG->checkFilePeriod(substr($currentYearMonth, 0,4), substr($currentYearMonth,4,2)); |
---|
| 169 | |
---|
| 170 | // get list of files to build |
---|
| 171 | $fileList=$dbStatG->getFilesList(ASDF_EXIST_PACKED|ASDF_EXIST_UNPACKED, ASDF_BUILD_MISSING); |
---|
| 172 | |
---|
| 173 | foreach($fileList as $file) |
---|
| 174 | { |
---|
| 175 | $file['month']=sprintf('%02d', $file['month']); |
---|
| 176 | |
---|
| 177 | if($force or |
---|
| 178 | ($currentDateTime>=$file['lastBuilt'] and |
---|
| 179 | $currentTime>=$this->config['build.start'] and |
---|
| 180 | $currentTime<=$this->config['build.end'])) |
---|
| 181 | { |
---|
| 182 | if($dbStatG->buildStatPeriod($this->fileStatDir, self::FILE_MONTH, $file['year'], $file['month'])) |
---|
| 183 | $build=true; |
---|
| 184 | |
---|
| 185 | if($pack and //pack only if asked |
---|
| 186 | $file['packed']==0 and //packed size=0 -> not packed |
---|
| 187 | $file['year'].$file['month']!=$currentYearMonth) //don't pack current file! |
---|
| 188 | { |
---|
| 189 | $dbStatM=new StatDBMonth($this->fileStatDir, self::FILE_MONTH, $file['year'], $file['month']); |
---|
| 190 | if($dbStatM->pack()) |
---|
| 191 | { |
---|
| 192 | $packedFileName=$dbStatM->getFileName(ASDF_EXIST_PACKED, true); |
---|
| 193 | if($packedFileName!='') |
---|
| 194 | $dbStatG->updatePackedSize($file['year'], $file['month'], filesize($packedFileName)); |
---|
| 195 | $dbStatM->delete(ASDF_DELETE_UNPACKED); |
---|
| 196 | } |
---|
| 197 | } |
---|
| 198 | } |
---|
| 199 | } |
---|
| 200 | |
---|
| 201 | $dbStatG->close(); |
---|
| 202 | |
---|
| 203 | return($build); |
---|
| 204 | } |
---|
| 205 | |
---|
| 206 | |
---|
| 207 | /** |
---|
| 208 | * Returns the needed informations to process the data migration |
---|
| 209 | * |
---|
| 210 | * Returned information is an array: |
---|
| 211 | * array( |
---|
| 212 | * 'nbLogs' => number of logs |
---|
| 213 | * 'idMax' => maximum id in HISTORY table |
---|
| 214 | * 'idMin' => minimum id in HISTORY table |
---|
| 215 | * 'dateMax' => maximum date in HISTORY table |
---|
| 216 | * 'dateMin' => minimum date in HISTORY table |
---|
| 217 | * 'periods' => array of periods to process |
---|
| 218 | * key=period (yyyy-mm) |
---|
| 219 | * value=number of events for the period |
---|
| 220 | * |
---|
| 221 | * @return Array |
---|
| 222 | */ |
---|
| 223 | protected function getPiwigoHistoryInfo() |
---|
| 224 | { |
---|
| 225 | $data=array( |
---|
| 226 | 'nbLogs' => 0, |
---|
| 227 | 'idMax' => 0, |
---|
| 228 | 'idMin' => 0, |
---|
| 229 | 'dateMax' => '', |
---|
| 230 | 'dateMin' => '', |
---|
| 231 | 'periods' => array() |
---|
| 232 | ); |
---|
| 233 | |
---|
| 234 | $sql="SELECT COUNT(id), MIN(id), MAX(id), MIN(`date`), MAX(`date`) |
---|
| 235 | FROM ".HISTORY_TABLE; |
---|
| 236 | $result=pwg_query($sql); |
---|
| 237 | if($result) |
---|
| 238 | { |
---|
| 239 | if($tmp=pwg_db_fetch_row($result)) |
---|
| 240 | { |
---|
| 241 | $data['nbLogs']=$tmp[0]; |
---|
| 242 | $data['idMin']=$tmp[1]; |
---|
| 243 | $data['idMax']=$tmp[2]; |
---|
| 244 | $data['dateMin']=$tmp[3]; |
---|
| 245 | $data['dateMax']=$tmp[4]; |
---|
| 246 | |
---|
| 247 | $sql="SELECT COUNT(id) AS nbEvents, YEAR(`date`) AS periodYear, MONTH(`date`) AS periodMonth |
---|
| 248 | FROM ".HISTORY_TABLE." |
---|
| 249 | GROUP BY periodYear, periodMonth |
---|
| 250 | ORDER BY periodYear, periodMonth;"; |
---|
| 251 | |
---|
| 252 | $result=pwg_query($sql); |
---|
| 253 | if($result) |
---|
| 254 | { |
---|
| 255 | while($row=pwg_db_fetch_assoc($result)) |
---|
| 256 | { |
---|
| 257 | $data['periods'][sprintf('%04d-%02d', $row['periodYear'], $row['periodMonth'])]=$row['nbEvents']; |
---|
| 258 | } |
---|
| 259 | } |
---|
| 260 | } |
---|
| 261 | } |
---|
| 262 | return($data); |
---|
| 263 | } |
---|
| 264 | |
---|
| 265 | |
---|
[17758] | 266 | |
---|
| 267 | |
---|
| 268 | |
---|
| 269 | /** |
---|
| 270 | * set the value for $fileStatDir & $fileExportDir |
---|
| 271 | * $rootPath is the root path where are stored the SQLite data files |
---|
| 272 | * example: (...)/local/plugins/EStat/Data/ |
---|
| 273 | * |
---|
| 274 | * This path is known is public and can be found by everyone. To forbid the |
---|
| 275 | * download of files stored in this directory, a random key is added in the |
---|
| 276 | * path |
---|
| 277 | * example: (...)/local/plugins/EStat/Data-ABCDEF0123456789/ |
---|
| 278 | * |
---|
| 279 | * The random key is stored in config file: |
---|
| 280 | * . if key is not set, try to find the directory |
---|
| 281 | * . if key is set but directory doesn't exist, try to find the directory |
---|
| 282 | * . if there's no key and no directory found, the key is created and saved |
---|
| 283 | * |
---|
| 284 | * the $fileStatDir provide the complete path with the key |
---|
| 285 | * the $fileExportDir path gets the same key than $fileStatDir |
---|
| 286 | * |
---|
| 287 | * @return String: $fileStatDir value |
---|
| 288 | */ |
---|
| 289 | protected function setFileStatDir() |
---|
| 290 | { |
---|
| 291 | $rootPath=GPCCore::getPiwigoSystemPath().'/'.PWG_LOCAL_DIR.self::DATA_DIRECTORY; |
---|
| 292 | |
---|
| 293 | $path=substr($rootPath,0,-1).'-'.$this->config['plugin.pathKey']; |
---|
| 294 | if(file_exists($path) and $this->config['plugin.pathKey']!='') |
---|
| 295 | { |
---|
| 296 | $this->fileStatDir=$path; |
---|
| 297 | $this->fileExportDir=GPCCore::getPiwigoSystemPath().'/'.PWG_LOCAL_DIR.substr(self::EXPORT_DIRECTORY,0,-1).'-'.$this->config['plugin.pathKey'].'/'; |
---|
| 298 | return($this->fileStatDir); |
---|
| 299 | } |
---|
| 300 | |
---|
| 301 | // key is empty or directory doesn't exist, try to find the diretory |
---|
| 302 | $path=$this->findDirectory(substr($rootPath,0,-1).'-'); |
---|
| 303 | if(file_exists($path)) |
---|
| 304 | { |
---|
| 305 | $this->fileStatDir=$path; |
---|
| 306 | $path=explode('-', basename($path)); // /xxx/xxx/xxx/data-abcdef012 => array('data', 'abcdef012') |
---|
| 307 | $this->config['plugin.pathKey']=$path[1]; |
---|
| 308 | $this->saveConfig(); |
---|
| 309 | $this->fileExportDir=GPCCore::getPiwigoSystemPath().'/'.PWG_LOCAL_DIR.substr(self::EXPORT_DIRECTORY,0,-1).'-'.$this->config['plugin.pathKey'].'/'; |
---|
| 310 | return($this->fileStatDir); |
---|
| 311 | } |
---|
| 312 | |
---|
| 313 | // no directory found, create the key |
---|
| 314 | $this->config['plugin.pathKey']=strtoupper(md5(date('Ymd-His').rand(0,65536))); |
---|
| 315 | $this->saveConfig(); |
---|
| 316 | $this->fileStatDir=substr($rootPath,0,-1).'-'.$this->config['plugin.pathKey']; |
---|
| 317 | $this->fileExportDir=GPCCore::getPiwigoSystemPath().'/'.PWG_LOCAL_DIR.substr(self::EXPORT_DIRECTORY,0,-1).'-'.$this->config['plugin.pathKey'].'/'; |
---|
| 318 | return($this->fileStatDir); |
---|
| 319 | } |
---|
| 320 | |
---|
| 321 | /** |
---|
| 322 | * try to find a directory in the $path |
---|
| 323 | * exemple: |
---|
| 324 | * $path = /local/plugins/EStat/Data- |
---|
| 325 | * => try to find all directory macthing with /local/plugins/EStat/Data-* |
---|
| 326 | * |
---|
| 327 | * @param String $path: |
---|
| 328 | * @return String: found path or empty string if nothing is found |
---|
| 329 | */ |
---|
| 330 | private function findDirectory($path) |
---|
| 331 | { |
---|
| 332 | $dirname=dirname($path); |
---|
| 333 | if(!file_exists($dirname)) return(''); |
---|
| 334 | $baseName=baseName($path); |
---|
| 335 | $dirContent=scandir($dirname); |
---|
| 336 | foreach($dirContent as $file) |
---|
| 337 | { |
---|
| 338 | if($file!='.' and $file!='..' and is_dir($dirname.'/'.$file) and strpos($file, $baseName)!==false) |
---|
| 339 | { |
---|
| 340 | return($dirname.'/'.$file); |
---|
| 341 | } |
---|
| 342 | } |
---|
| 343 | return(''); |
---|
| 344 | } |
---|
| 345 | |
---|
| 346 | |
---|
| 347 | |
---|
| 348 | |
---|
[17737] | 349 | /* |
---|
| 350 | * ------------------------------------------------------------------------- |
---|
| 351 | * -- functions used by the ajax classes |
---|
| 352 | * ------------------------------------------------------------------------- |
---|
| 353 | */ |
---|
| 354 | |
---|
| 355 | |
---|
| 356 | |
---|
| 357 | /** |
---|
| 358 | * generic function to consolidate a list of Id in a list with distinct Id |
---|
| 359 | * |
---|
| 360 | * the &$table parameter is an array with predefined keys * |
---|
| 361 | * |
---|
| 362 | * @param Array &$table : the table were to put result |
---|
| 363 | * @param String $key : the key (of the table) where result have to be put |
---|
| 364 | * @param String $sql : SQL request to produce the id list |
---|
| 365 | */ |
---|
| 366 | protected function prepareIdList(&$table, $key, $sql) |
---|
| 367 | { |
---|
| 368 | $result=pwg_query($sql); |
---|
| 369 | if($result) |
---|
| 370 | { |
---|
| 371 | while($row=pwg_db_fetch_assoc($result)) |
---|
| 372 | { |
---|
| 373 | $table[$key][$row['id']]=$row; |
---|
| 374 | } |
---|
| 375 | } |
---|
| 376 | } |
---|
| 377 | |
---|
| 378 | /** |
---|
| 379 | * generic function to prepare a list of unique IP adress with the following |
---|
| 380 | * informations: |
---|
| 381 | * - reverse DNS (if asked) |
---|
| 382 | * - country |
---|
| 383 | * returned keys are IP adress, associated value is an array |
---|
| 384 | * ip => array('rdns' => reverseDNS, 'country' => country_code) |
---|
| 385 | * |
---|
| 386 | * @param Array &$table : the table were to put result |
---|
| 387 | * @param Array $items : array of IP adress |
---|
| 388 | * @param Boolean $force : if true, force to produce the reversed DNS address |
---|
| 389 | */ |
---|
| 390 | protected function getIpInfos(&$table, $items, $force=false) |
---|
| 391 | { |
---|
| 392 | $dbCountry=new StatDBCountry($this->fileStatDir, self::FILE_COUNTRY); |
---|
| 393 | $dbCountry->open(ASDF_OPEN_READ); |
---|
| 394 | |
---|
| 395 | foreach($items as $IP) |
---|
| 396 | { |
---|
| 397 | $table['IPadress'][$IP]=array( |
---|
| 398 | 'rdns' => '', |
---|
| 399 | 'country' => $dbCountry->getIpCountry($IP, false) |
---|
| 400 | ); |
---|
| 401 | |
---|
| 402 | if($force or $this->config['logs.reverseDNS']=='y') |
---|
| 403 | $table['IPadress'][$IP]=gethostbyaddr($IP); |
---|
| 404 | } |
---|
| 405 | $dbCountry->close(); |
---|
| 406 | } |
---|
| 407 | |
---|
| 408 | |
---|
| 409 | |
---|
| 410 | /** |
---|
| 411 | * return the label associated to the id, or a default value if nothing is |
---|
| 412 | * found |
---|
| 413 | * |
---|
| 414 | * @param Array $table: array of label |
---|
| 415 | * @param string $key: type of id |
---|
| 416 | * @param string $id: id for which the label have to be retrieved |
---|
| 417 | * @param string $default: default value to return if no label found |
---|
| 418 | * @return string: label |
---|
| 419 | */ |
---|
| 420 | protected function getId($table, $key, $id, $default='', $field='name') |
---|
| 421 | { |
---|
| 422 | if(is_array($id)) |
---|
| 423 | { |
---|
| 424 | $tmp=array(); |
---|
| 425 | foreach($id as $val) |
---|
| 426 | { |
---|
| 427 | $tmp[]=$this->getId($table, $key, $val, $default, $field); |
---|
| 428 | } |
---|
| 429 | return(implode(',', $tmp)); |
---|
| 430 | } |
---|
| 431 | elseif(isset($table[$key]) and isset($table[$key][$id]) and isset($table[$key][$id][$field])) |
---|
| 432 | { |
---|
| 433 | return($table[$key][$id][$field]); |
---|
| 434 | } |
---|
| 435 | else return($default); |
---|
| 436 | } |
---|
| 437 | |
---|
| 438 | |
---|
| 439 | /** |
---|
| 440 | * build a filter of category id; for each given id, the childrens are selected |
---|
| 441 | * too |
---|
| 442 | * |
---|
| 443 | * @param Array $catId: category id list |
---|
| 444 | * @return Array |
---|
| 445 | */ |
---|
| 446 | protected function buildCatIdFilter($catId) |
---|
| 447 | { |
---|
| 448 | $returned=array(); |
---|
| 449 | |
---|
| 450 | if(!is_array($catId)) return($returned); |
---|
| 451 | |
---|
| 452 | $where=array(); |
---|
| 453 | foreach($catId as $id) |
---|
| 454 | { |
---|
| 455 | $where[]="FIND_IN_SET('$id', uppercats)"; |
---|
| 456 | } |
---|
| 457 | $sql="SELECT DISTINCT id |
---|
| 458 | FROM ".CATEGORIES_TABLE." |
---|
| 459 | WHERE ".implode(' OR ', $where); |
---|
| 460 | $tmpResult=pwg_query($sql); |
---|
| 461 | if($tmpResult) |
---|
| 462 | { |
---|
| 463 | $tmp=array(); |
---|
| 464 | while($row=pwg_db_fetch_row($tmpResult)) |
---|
| 465 | { |
---|
| 466 | $tmp[]=$row[0]; |
---|
| 467 | } |
---|
| 468 | $returned=array('operator' => 'in', 'value' => $tmp); |
---|
| 469 | } |
---|
| 470 | return($returned); |
---|
| 471 | } |
---|
| 472 | |
---|
[17758] | 473 | } //class |
---|
[17737] | 474 | |
---|
| 475 | |
---|
| 476 | |
---|
| 477 | |
---|
| 478 | /* |
---|
| 479 | * ------------------------------------------------------------------------------------------------ |
---|
| 480 | * -- classes used for ajax -- |
---|
| 481 | * ------------------------------------------------------------------------------------------------ |
---|
| 482 | */ |
---|
| 483 | |
---|
| 484 | |
---|
| 485 | /** |
---|
| 486 | * this class is used to build list of unique Id |
---|
| 487 | */ |
---|
| 488 | class EStat_IdList |
---|
| 489 | { |
---|
| 490 | protected $listItems=array(); |
---|
| 491 | |
---|
| 492 | public function __construct($items) |
---|
| 493 | { |
---|
| 494 | if(is_array($items)) $this->init($items); |
---|
| 495 | } |
---|
| 496 | |
---|
| 497 | public function __destruct() |
---|
| 498 | { |
---|
| 499 | } |
---|
| 500 | |
---|
| 501 | /** |
---|
| 502 | * initialize the names of identifiers pool |
---|
| 503 | * for example, init(array('album', 'image')) to declare a pool for 'album' id |
---|
| 504 | * and another pool for 'image' id |
---|
| 505 | * |
---|
| 506 | * @param Array $items: array of names |
---|
| 507 | */ |
---|
| 508 | public function init($items) |
---|
| 509 | { |
---|
| 510 | $this->listItems=array(); |
---|
| 511 | foreach($items as $item) |
---|
| 512 | { |
---|
| 513 | $this->listItems[$item]=array(); |
---|
| 514 | } |
---|
| 515 | } |
---|
| 516 | |
---|
| 517 | /** |
---|
| 518 | * add items in the pool |
---|
| 519 | * |
---|
| 520 | * $items is an array of (key => value) |
---|
| 521 | * for example: |
---|
| 522 | * addItems( |
---|
| 523 | * 'album' => 1, |
---|
| 524 | * 'album' => 2, |
---|
| 525 | * 'album' => 1, |
---|
| 526 | * 'image' => 236 |
---|
| 527 | * ); |
---|
| 528 | * |
---|
| 529 | * will be (internaly) stored as |
---|
| 530 | * listItems( |
---|
| 531 | * 'album' => array(1,2), |
---|
| 532 | * 'image' => array(236) |
---|
| 533 | * ); |
---|
| 534 | * |
---|
| 535 | * @param Array $items |
---|
| 536 | */ |
---|
| 537 | public function addItems($items) |
---|
| 538 | { |
---|
| 539 | if(is_array($items)) |
---|
| 540 | { |
---|
| 541 | foreach($items as $key => $item) |
---|
| 542 | { |
---|
| 543 | $this->add($key, $item); |
---|
| 544 | } |
---|
| 545 | } |
---|
| 546 | } |
---|
| 547 | |
---|
| 548 | /** |
---|
| 549 | * return the associated list of item for an identifier |
---|
| 550 | * for example: |
---|
| 551 | * getItems('album') |
---|
| 552 | * will return: |
---|
| 553 | * array(1,2) |
---|
| 554 | * |
---|
| 555 | * @param Array $item: identifier |
---|
| 556 | * @return Array |
---|
| 557 | */ |
---|
| 558 | public function getItems($item) |
---|
| 559 | { |
---|
| 560 | if(isset($this->listItems[$item])) |
---|
| 561 | { |
---|
| 562 | return(array_keys($this->listItems[$item])); |
---|
| 563 | } |
---|
| 564 | else |
---|
| 565 | { |
---|
| 566 | return(array()); |
---|
| 567 | } |
---|
| 568 | } |
---|
| 569 | |
---|
| 570 | /** |
---|
| 571 | * add an item for an identifier |
---|
| 572 | * |
---|
| 573 | * @param string $key: identifier |
---|
| 574 | * @param string $item: value to add |
---|
| 575 | */ |
---|
| 576 | private function add($key, $item) |
---|
| 577 | { |
---|
| 578 | if(is_array($item)) |
---|
| 579 | { |
---|
| 580 | foreach($item as $val) |
---|
| 581 | { |
---|
| 582 | $this->add($key, $val); |
---|
| 583 | } |
---|
| 584 | return(true); |
---|
| 585 | } |
---|
| 586 | |
---|
| 587 | if($item!='' and isset($this->listItems[$key]) and !isset($this->listItems[$key][$item])) |
---|
| 588 | { |
---|
| 589 | $this->listItems[$key][$item]=''; |
---|
| 590 | } |
---|
| 591 | } |
---|
| 592 | } // class EStat_IdList |
---|
| 593 | |
---|
| 594 | |
---|
| 595 | |
---|
| 596 | |
---|
| 597 | |
---|
| 598 | |
---|
| 599 | |
---|
| 600 | |
---|
| 601 | class ReverseIP |
---|
| 602 | { |
---|
| 603 | protected $ipList=array(); |
---|
| 604 | protected $ipFile=''; |
---|
| 605 | |
---|
| 606 | /** |
---|
| 607 | * add an IP adress in the list, by default there's no browser type set |
---|
| 608 | * for the IP adress |
---|
| 609 | * @param String $IP: IP adress |
---|
| 610 | * @param Integer $type: if not set, value is defined automatically |
---|
| 611 | */ |
---|
| 612 | public function addIP($IP, $type=null) |
---|
| 613 | { |
---|
| 614 | if(!isset($this->ipList[$IP])) |
---|
| 615 | $this->ipList[$IP]=UA_BROWSER_TYPE_UNKNOWN; //$this->fromReverseDNS(gethostbyaddr($IP)); |
---|
| 616 | } |
---|
| 617 | |
---|
| 618 | /** |
---|
| 619 | * return IP browser type |
---|
| 620 | * @param String $IP: IP adress |
---|
| 621 | * @return Integer: -1 if IP adress not exists |
---|
| 622 | */ |
---|
| 623 | public function getIP($IP) |
---|
| 624 | { |
---|
| 625 | if(!isset($this->ipList[$IP])) return(-1); |
---|
| 626 | return($this->ipList[$IP]); |
---|
| 627 | } |
---|
| 628 | |
---|
| 629 | /** |
---|
| 630 | * set IP type |
---|
| 631 | * |
---|
| 632 | * @param String $IP: IP adress |
---|
| 633 | * @param Integer $type: type of browser |
---|
| 634 | * @return Integer: type set, -1 if an error occurs |
---|
| 635 | */ |
---|
| 636 | public function setIP($IP, $type) |
---|
| 637 | { |
---|
| 638 | if(!isset($this->ipList[$IP])) return(-1); |
---|
| 639 | if($this->ipList[$IP]==-1) $this->ipList[$IP]=$type; |
---|
| 640 | return($this->ipList[$IP]); |
---|
| 641 | } |
---|
| 642 | |
---|
| 643 | /** |
---|
| 644 | * delete the temporary ip file |
---|
| 645 | */ |
---|
| 646 | public function deleteIPFile() |
---|
| 647 | { |
---|
| 648 | if(file_exists($this->ipFile)) |
---|
| 649 | unlink($this->ipFile); |
---|
| 650 | } |
---|
| 651 | |
---|
| 652 | /** |
---|
| 653 | * load an IP file in memory |
---|
| 654 | * |
---|
| 655 | * @param String $file: file to load |
---|
| 656 | * @return Boolean: true or false |
---|
| 657 | */ |
---|
| 658 | public function loadIPFile($file) |
---|
| 659 | { |
---|
| 660 | $this->ipFile=$file; |
---|
| 661 | if(!file_exists($file)) return(false); |
---|
| 662 | $this->ipList=array(); |
---|
| 663 | |
---|
| 664 | $fHandle=fopen($this->ipFile, 'r'); |
---|
| 665 | if($fHandle) |
---|
| 666 | { |
---|
| 667 | $tmp=fread($fHandle, filesize($this->ipFile)); |
---|
| 668 | fclose($fHandle); |
---|
| 669 | $this->ipList=unserialize($tmp); |
---|
| 670 | return(true); |
---|
| 671 | } |
---|
| 672 | return(false); |
---|
| 673 | } |
---|
| 674 | |
---|
| 675 | /** |
---|
| 676 | * save IP list on a file |
---|
| 677 | * |
---|
| 678 | * @param String $file: file to load |
---|
| 679 | * @return Boolean: true or false |
---|
| 680 | */ |
---|
| 681 | public function saveIPFile() |
---|
| 682 | { |
---|
| 683 | if($this->ipFile=='') return(false); |
---|
| 684 | $fHandle=fopen($this->ipFile, 'w'); |
---|
| 685 | if($fHandle) |
---|
| 686 | { |
---|
| 687 | fwrite($fHandle, serialize($this->ipList)); |
---|
| 688 | fclose($fHandle); |
---|
| 689 | return(true); |
---|
| 690 | } |
---|
| 691 | return(false); |
---|
| 692 | } |
---|
| 693 | |
---|
| 694 | /** |
---|
| 695 | * try to know from a reversed DNS adress if visitor is a crawler or not |
---|
| 696 | * |
---|
| 697 | * @param String $revDNS: a reversed DNS IP address |
---|
| 698 | * @return Integer: UA_BROWSER_TYPE_UNKNOWN or UA_BROWSER_TYPE_CRAWLER |
---|
| 699 | */ |
---|
| 700 | public function fromReverseDNS($revDNS) |
---|
| 701 | { |
---|
| 702 | $returned=UA_BROWSER_TYPE_UNKNOWN; |
---|
| 703 | |
---|
| 704 | if(preg_match('/\s*([a-z]*(?:bot|spyder|crawl|crawler|spider)[a-z]*)/i', $revDNS)) |
---|
| 705 | $returned=UA_BROWSER_TYPE_CRAWLER; |
---|
| 706 | |
---|
| 707 | return($returned); |
---|
| 708 | } |
---|
| 709 | } // class ReverseIP |
---|
| 710 | |
---|
| 711 | |
---|
| 712 | |
---|
| 713 | ?> |
---|