Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
funnelback_search_log_report_edit_fns.inc
1 <?php
17 require_once SQ_CORE_PACKAGE_PATH.'/report/report_edit_fns.inc';
18 require_once SQ_FUDGE_PATH.'/general/file_system.inc';
19 require_once SQ_LIB_PATH.'/html_form/html_form.inc';
20 require_once SQ_PACKAGES_PATH.'/funnelback/log_reports/funnelback_search_log_report/funnelback_log_iterator.inc';
21 
34 {
35 
36 
47  public function generateReport(&$job, &$step_data, $prefix)
48  {
49  $job_vars =& $job->_running_vars;
50 
51  // No report set, bail...
52  if (!isset($job_vars['report']) || is_null($job_vars['report'])) {
53  trigger_error('Warning Warning', E_USER_WARNING);
54  return FALSE;
55  }//end if
56 
57  // default to build the cache of the log
58  if (!isset($job_vars['mode'])) {
59  $job_vars['mode'] = 'cache';
60  }//end if
61 
62  // determine the mode
63  $job_vars['mode'] = (string) $job_vars['mode'];
64  switch ($job_vars['mode']) {
65  case 'cleanup':
66  $this->_maintainReport($job_vars);
67  break;
68 
69  case 'report':
70  $this->_generateReport($job_vars);
71  $job_vars['mode'] = 'cleanup';
72 
73  // Update progress - we are finished!
74  $step_data['percent_done'] = 100;
75  $step_data['complete'] = TRUE;
76  break;
77 
78  case 'total':
79  $status = $this->_generateTotals($job_vars);
80  $job_vars['mode'] = 'report';
81 
82  // Update progress
83  $step_data['percent_done'] = 70;
84  $step_data['complete'] = FALSE;
85  break;
86 
87  case 'cache':
88  default:
89  $status = $this->_generateCacheEntries($job_vars);
90 
91  // Update progress
92  if ($status === TRUE) {
93  $step_data['percent_done'] = 40;
94  $step_data['complete'] = FALSE;
95  } else if ($status === FALSE) {
96  $step_data['percent_done'] = 100;
97  $step_data['complete'] = TRUE;
98  }//end if
99  break;
100  }//end switch
101 
102  return TRUE;
103 
104  }//end generateReport()
105 
106 
117  private function _generateCacheEntries(&$job_vars)
118  {
119  // Find the logs to scan
120  if (isset($job_vars['logs'])) {
121  $meta['report'] = $job_vars['report'];
122  $logs = $job_vars['logs'];
123  ksort($logs);
124  } else {
125  // Nothing to do, bail bail bail
126  return FALSE;
127  }//end if
128 
129  // check for the iterator, otherwise grab the first iterator
130  if (!isset($job_vars['iterator'])) {
131  reset($logs);
132  $job_vars['current_collection'] = key($logs);
133  $log_file = $logs[$job_vars['current_collection']];
134  $job_vars['iterator'] = new Funnelback_Log_Iterator($log_file);
135  }//end if
136 
137  // next check if the iterator is at the end of the file, if it is proceed to the next log until the logs have run out
138  $progress = $job_vars['iterator']->getCurrentProgress();
139  $total = array_get_index($progress, 'total', 0);
140  $current = array_get_index($progress, 'current', $total);
141  if ($current >= $total && isset($job_vars['current_collection'])) {
142  // Finished with this log, remove entry and proceed to the next entry
143  unset($job_vars['logs'][$job_vars['current_collection']]);
144  unset($job_vars['current_collection']);
145  if (!empty($job_vars['logs'])) {
146  reset($job_vars['logs']);
147  $job_vars['current_collection'] = key($job_vars['logs']);
148  $log_file = $job_vars['logs'][$job_vars['current_collection']];
149  $job_vars['iterator'] = new Funnelback_Log_Iterator($log_file);
150  } else {
151  // All done, proceed to totalling
152  $job_vars['mode'] = 'total';
153  return TRUE;
154  }//end if
155  }//end if
156 
157  // Creating a cache entry for the current line
158  $rollover_period = $job_vars['report']->attr('rollover_period');
159  $line = $job_vars['iterator']->getNextEntry();
160  if (isset($line['line']) && !empty($line['line'])) {
161  $period = $this->_getPeriod($line['line']['date'], $rollover_period);
162  $path = $job_vars['report']->data_path.'/cache/'.$period;
163  $cache = Array();
164  $cache['ip'] = $line['line']['ip'];
165  $cache['date'] = $line['line']['date'];
166  $cache['query'] = $line['line']['query'];
167  $cache['full_matches'] = $line['line']['full_matches'];
168  $cache['partial_matches'] = $line['line']['partial_matches'];
169  $cache['collection'] = $job_vars['current_collection'];
170  $this->_generateCacheEntry($path, $cache);
171  }//end if
172 
173  return NULL;
174 
175  }//end _generateCacheEntries()
176 
177 
188  private function _generateTotals(&$job_vars)
189  {
190  $cache_date_entries = glob($job_vars['report']->data_path.'/cache/*');
191  foreach ($cache_date_entries as $cache_date_entry) {
192  $period = basename($cache_date_entry);
193  $path = $job_vars['report']->data_path.'/total/'.$period;
194  if (!is_dir($path)) {
195  create_directory($path);
196  }//end if
197  $collections = glob($cache_date_entry.'/*');
198  $collection_totals = Array();
199  foreach ($collections as $collection_path) {
200  $collection_id = basename($collection_path);
201  $cache_entries = glob($collection_path.'/*/*/*.cache');
202  foreach ($cache_entries as $cache_entry) {
203  $query = basename($cache_entry, '.cache');
204  $data = @unserialize(file_to_string($cache_entry));
205  $report_data = $this->_processTotals($data);
206  $actual_query = array_get_index($report_data, 'query', 0);
207  $collection_totals = $this->_combineTotals($collection_totals, Array($actual_query => $report_data));
208 
209  // Save the report data
210  if ($actual_query == '' && $query == 'blank') {
211  $hash = '00/00';
212  } else {
213  $hash = $this->_getQueryHash($query);
214  }//end if
215  $file = $path.'/'.$collection_id.'/'.$hash.'/'.$query.'.results';
216  if (!is_dir(dirname($file))) {
217  create_directory(dirname($file));
218  }//end if
219  string_to_file(serialize($report_data), $file);
220  }//end foreach
221 
222  // Save the collection totals
223  string_to_file(serialize($collection_totals), $path.'/'.$collection_id.'/'.$collection_id.'.results');
224  }//end foreach
225  }//end foreach
226 
227  return TRUE;
228 
229  }//end _generateTotals()
230 
231 
240  private function _generateReport(&$job_vars)
241  {
242  $total_entries = glob($job_vars['report']->data_path.'/total/*');
243  $path = $job_vars['report']->data_path.'/report/';
244  if (!is_dir($path)) {
245  create_directory($path);
246  }//end if
247  foreach ($total_entries as $total_date_entry) {
248  $period = basename($total_date_entry);
249  $report_date = $this->_generateReportDate($period);
250  $report_content = $this->_generateReportContents($job_vars, $total_date_entry);
251  file_put_contents($path.'report-'.date('d-m-Y', $report_date).'.html', $report_content);
252  }//end foreach
253 
254  }//end _generateReport()
255 
256 
266  private function _generateCacheEntry($path, $cache)
267  {
268  if (empty($cache)) {
269  return FALSE;
270  }//end if
271 
272  if (empty($cache['query'])) {
273  // Blank search
274  $query = 'blank';
275  $hash = '00/00';
276  } else {
277  $query = $cache['query'];
278  $hash = $this->_getQueryHash($this->_cleanQuery($query));
279  }//end if
280 
281  $path = $path.'/'.$cache['collection'].'/'.$hash;
282  if (!is_dir($path)) {
283  create_directory($path);
284  }//end if
285 
286  $filename = $this->_cleanQuery($query).'.cache';
287  $file = $path.'/'.$filename;
288 
289  // Check if writable
290  if (!is_writable(dirname($file))) {
291  return FALSE;
292  }//end if
293 
294  // Load up the cache file
295  if (file_exists($file)) {
296  $data = @unserialize(file_to_string($file));
297  } else {
298  $data = Array();
299  }//end if
300 
301  // Add in the new entry
302  $data[] = $cache;
303 
304  // Save
305  file_put_contents($file, serialize($data));
306 
307  return TRUE;
308 
309  }//end _generateCacheEntry()
310 
311 
322  private function _processTotals($data)
323  {
324  $report = Array();
325 
326  // Get the results
327  $report['queries'] = count($data);
328  $query = NULL;
329  foreach ($data as $line) {
330  // This should NOT happen, so just in case
331  if (is_null($query)) {
332  // First case, set the query to the first known query
333  $query = array_get_index($line, 'query', NULL);
334  } else {
335  // If current line doesn't match the first case, skip over
336  $check = array_get_index($line, 'query', '');
337  if ($check != $query) continue;
338  $report['query'] = $query;
339  }//end if
340  $min = array_get_index($report, 'min_results', NULL);
341  $max = array_get_index($report, 'max_results', NULL);
342  $avg = array_get_index($report, 'avg_results', NULL);
343  $date = array_get_index($line, 'date', NULL);
344  $full_matches = array_get_index($line, 'full_matches', 0);
345  $partial_matches = array_get_index($line, 'partial_matches', 0);
346  $total_matches = $full_matches + $partial_matches;
347  if (!isset($report['total_results'])) {
348  $report['total_results'] = $total_matches;
349  } else {
350  $report['total_results'] += $total_matches;
351  }//end if
352 
353  // Total stats
354  if (is_null($min)) {
355  $report['min_results'] = $total_matches;
356  } else {
357  $report['min_results'] = min($min, $total_matches);
358  }//end if
359  if (is_null($max)) {
360  $report['max_results'] = $total_matches;
361  } else {
362  $report['max_results'] = max($max, $total_matches);
363  }//end if
364  $report['avg_results'] = ((!empty($total_matches)) ? ($report['total_results'] / $report['queries']) : 0);
365  }//end foreach
366 
367  return $report;
368 
369  }//end _processTotals()
370 
371 
383  private function _combineTotals($collection, $query)
384  {
385  // Format a structure if not set
386  if (!isset($collection['total_fail'])) $collection['total_fail'] = 0;
387  if (!isset($collection['total_pass'])) $collection['total_pass'] = 0;
388  if (!isset($collection['total_queries'])) $collection['total_queries'] = 0;
389  if (!isset($collection['total_results'])) $collection['total_results'] = 0;
390 
391  foreach ($query as $query_term => $query_results) {
392  // Never seen this query term, define a new results structure for this query
393  if (empty($query_term)) $query_term = 0;
394  if (!isset($collection[$query_term])) {
395  $collection[$query_term] = Array();
396  }//end if
397 
398  // Combine the total statistics per query
399  $collection['total_queries'] += $query_results['queries'];
400  if (isset($query_results['total_results'])) {
401  $collection['total_results'] += $query_results['total_results'];
402  if (is_null(array_get_index($collection[$query_term], 'total_queries', NULL))) {
403  $collection[$query_term]['total_queries'] = $query_results['queries'];
404  } else {
405  $collection[$query_term]['total_queries'] += $query_results['queries'];
406  }//end if
407  if (is_null(array_get_index($collection[$query_term], 'total_results', NULL))) {
408  $collection[$query_term]['total_results'] = $query_results['total_results'];
409  } else {
410  $collection[$query_term]['total_results'] += $query_results['total_results'];
411  }//end if
412  $collection[$query_term]['total_avg_results'] = ((!empty($collection[$query_term]['total_queries'])) ? ($collection[$query_term]['total_results'] / $collection[$query_term]['total_queries']) : 0);
413  if (is_null(array_get_index($collection[$query_term], 'total_min_results', NULL))) {
414  $collection[$query_term]['total_min_results'] = $query_results['min_results'];
415  } else {
416  $collection[$query_term]['total_min_results'] = min($collection[$query_term]['total_min_results'], $query_results['min_results']);
417  }//end if
418  if (is_null(array_get_index($collection[$query_term], 'total_max_results', NULL))) {
419  $collection[$query_term]['total_max_results'] = $query_results['max_results'];
420  } else {
421  $collection[$query_term]['total_max_results'] = max($collection[$query_term]['total_max_results'], $query_results['max_results']);
422  }//end if
423  if (empty($query_results['total_results'])) {
424  $collection['total_fail']++;
425  if (is_null(array_get_index($collection[$query_term], 'total_fail', NULL))) {
426  $collection[$query_term]['total_fail'] = 1;
427  } else {
428  $collection[$query_term]['total_fail']++;
429  }//end if
430  } else {
431  $collection['total_pass']++;
432  if (is_null(array_get_index($collection[$query_term], 'total_pass', NULL))) {
433  $collection[$query_term]['total_pass'] = 1;
434  } else {
435  $collection[$query_term]['total_pass']++;
436  }//end if
437  }//end if
438  }//end if
439  }//end foreach
440 
441  return $collection;
442 
443  }//end _combineTotals()
444 
445 
454  private function _generateReportDate($period)
455  {
456  $period_type = substr($period, 0, 1);
457  $period_date = substr($period, 1);
458 
459  $period_type = (string) $period_type;
460  switch ($period_type) {
461  case 'W':
462  $year = substr($period_date, 0, 4);
463  $week = substr($period_date, 4);
464 
465  // Calculating the start of the week
466  $soy = strtotime('first monday january '.$year);
467  $soyw = date('W', $soy);
468  $days_diff = ($week - $soyw) * 7;
469  $sow = strtotime('+'.$days_diff.' days', $soy);
470  return mktime(0, 0, 0, date('m', $sow), date('d', $sow), $year);
471  break;
472 
473  case 'M':
474  $year = substr($period_date, 0, 4);
475  $month = substr($period_date, 4);
476  return mktime(0, 0, 0, $month, 1, $year);
477  break;
478 
479  case 'D':
480  $year = substr($period_date, 0, 4);
481  $month = substr($period_date, 4, 2);
482  $day = substr($period_date, 6, 2);
483  return mktime(0, 0, 0, $month, $day, $year);
484  break;
485 
486  default:
487  // Playing safe and returning the current date/time
488  return time();
489  break;
490  }//end switch
491 
492  }//end _generateReportDate()
493 
494 
504  private function _generateReportContents(&$job_vars, $path)
505  {
506  $overall = Array();
507  $contents = '';
508  $total_contents = '';
509  $collection_data_paths = glob($path.'/*');
510  foreach ($collection_data_paths as $collection_data_path) {
511  $collection_id = basename($collection_data_path);
512 
513  // Printing the collection header
514  $contents .= $this->_printCollectionHeader($collection_id);
515 
516  // Getting the totals/summary for the current collection
517  $totals = glob($collection_data_path.'/*/*/*.results');
518  $good = Array();
519  $fail = Array();
520  $failed_query_totals = Array();
521  $success_query_totals = Array();
522  $fail_limit = Array();
523  $good_limit = Array();
524  $row_limit = $job_vars['report']->attr('row_count');
525  foreach ($totals as $total) {
526  // This is the total for the current collection
527  // Working out the top XX results per good/fail
528  $filename = basename($total, '.results');
529  $query_totals = @unserialize(file_get_contents($total));
530  $query = array_get_index($query_totals, 'query', 0);
531  if (empty($query)) continue;
532  $query_results = array_get_index($query_totals, 'total_results', 0);
533  $query_queries = array_get_index($query_totals, 'queries', 0);
534  if (empty($query_results)) {
535  if (count($fail_limit) < $row_limit) {
536  // We have not reached the limit yet
537  $fail_limit[$query] = $query_queries;
538  $failed_query_totals[$query] = $query_totals;
539  } else {
540  // Reached the limit, see if we have made in it
541  reset($fail_limit);
542  $fail_threshold = end($fail_limit);
543  if ($query_queries > $fail_threshold) {
544  unset($failed_query_totals[key($fail_limit)]);
545  array_pop($fail_limit);
546  $fail_limit[$query] = $query_queries;
547  $failed_query_totals[$query] = $query_totals;
548  }//end if
549  }//end if
550  arsort($fail_limit);
551  } else {
552  if (count($good_limit) < $row_limit) {
553  // We have not reached the limit yet
554  $good_limit[$query] = $query_queries;
555  $success_query_totals[$query] = $query_totals;
556  } else {
557  // Reached the limit, see if we have made in it
558  reset($good_limit);
559  $good_threshold = end($good_limit);
560  if ($query_queries > $good_threshold) {
561  unset($success_query_totals[key($good_limit)]);
562  array_pop($good_limit);
563  $good_limit[$query] = $query_queries;
564  $success_query_totals[$query] = $query_totals;
565  }//end if
566  }//end if
567  arsort($good_limit);
568  }//end if
569  }//end foreach
570 
571  // Top XX failed results
572  foreach ($fail_limit as $query => $totals) {
573  $query_totals = $failed_query_totals[$query];
574  $line = $this->_formatLine($query_totals, FALSE);
575  if (!empty($line)) {
576  $fail[] = $line;
577  }//end if
578  $this->_combineOverallResults($query_totals, $overall);
579  }//end foreach
580 
581  // Top XX good results
582  foreach ($good_limit as $query => $totals) {
583  $query_totals = $success_query_totals[$query];
584  $line = $this->_formatLine($query_totals, TRUE);
585  if (!empty($line)) {
586  $good[] = $line;
587  }//end if
588  $this->_combineOverallResults($query_totals, $overall);
589  }//end foreach
590  $contents .= $this->_printQueryResults($good, $fail);
591  }//end foreach
592 
593  // Print overall results
594  $total_contents .= $this->_printCollectionHeader(FALSE);
595  $total_good = Array();
596  $total_fail = Array();
597  $total_good_limit = Array();
598  $total_fail_limit = Array();
599  $row_limit = $job_vars['report']->attr('row_count');
600  foreach ($overall as $query => $query_data) {
601  if (!is_array($query_data)) {
602  // Total stats for the collection
603  } else if ($query === 0) {
604  // Blank query searches
605  } else {
606  // Query stats for this collection
607  $query_data['query'] = $query;
608  $query_results = array_get_index($query_data, 'total_results', 0);
609  $query_queries = array_get_index($query_data, 'total_queries', 0);
610  if (empty($query_results)) {
611  if (count($total_fail_limit) < $row_limit) {
612  // Add to the Top XX
613  $total_fail_limit[$query] = $query_queries;
614  } else {
615  reset($total_fail_limit);
616  $threshold = end($total_fail_limit);
617  if ($query_queries > $threshold) {
618  array_pop($total_fail_limit);
619  $total_fail_limit[$query] = $query_queries;
620  }//end if
621  }//end if
622  arsort($total_fail_limit);
623  } else {
624  if (count($total_good_limit) < $row_limit) {
625  // Add to the Top XX
626  $total_good_limit[$query] = $query_queries;
627  } else {
628  reset($total_good_limit);
629  $threshold = end($total_good_limit);
630  if ($query_queries > $threshold) {
631  array_pop($total_good_limit);
632  $total_good_limit[$query] = $query_queries;
633  }//end if
634  }//end if
635  arsort($total_good_limit);
636  }//end if
637  }//end if
638  }//end foreach
639 
640  arsort($total_fail_limit);
641  foreach ($total_fail_limit as $query => $total) {
642  $query_data = $overall[$query];
643  $query_data['query'] = $query;
644  $line = $this->_formatLine($query_data, FALSE, TRUE);
645  if (!empty($line)) {
646  $total_fail[] = $line;
647  }//end if
648  }//end foreach
649 
650  arsort($total_good_limit);
651  foreach ($total_good_limit as $query => $total) {
652  $query_data = $overall[$query];
653  $query_data['query'] = $query;
654  $line = $this->_formatLine($query_data, TRUE, TRUE);
655  if (!empty($line)) {
656  $total_good[] = $line;
657  }//end if
658  }//end foreach
659  $total_contents .= $this->_printQueryResults($total_good, $total_fail);
660 
661  // Combine
662  $contents = $contents.$total_contents;
663 
664  return $contents;
665 
666  }//end _generateReportContents()
667 
668 
678  private function _combineOverallResults($query_totals, &$overall)
679  {
680  $query = array_get_index($query_totals, 'query', NULL);
681  if (!is_null($query) && !empty($query)) {
682  if (!isset($overall[$query])) $overall[$query] = Array();
683  foreach ($query_totals as $key => $value) {
684  if ($key == 'query') continue;
685 
686  // The maths...
687  if ($key == 'avg_results') {
688  // This is done later
689  } else if ($key == 'min_results') {
690  $overall_total = array_get_index($overall[$query], 'total_min_results', 0);
691  $overall[$query]['total_min_results'] = min($overall_total, $value);
692  } else if ($key == 'max_results') {
693  $overall_total = array_get_index($overall[$query], 'total_max_results', 0);
694  $overall[$query]['total_max_results'] = max($overall_total, $value);
695  } else {
696  // Everything else, just calculate
697  $overall_key = ((strpos($key, 'total_') === 0) ? $key : 'total_'.$key);
698  $overall_total = array_get_index($overall[$query], $overall_key, 0);
699  $overall[$query][$overall_key] = $overall_total + $value;
700  }//end if
701  }//end foreach
702 
703  // Finally, update the averages
704  $total_results = array_get_index($query_totals, 'total_results', 0);
705  $overall_results = array_get_index($overall[$query], 'total_results', 0);
706  $total_queries = array_get_index($query_totals, 'queries', 0);
707  $overall_queries = array_get_index($overall[$query], 'total_queries', 0);
708  if (!empty($total_queries) && !empty($overall_queries)) {
709  $new_average = ($total_results + $overall_results) / ($total_queries + $overall_queries);
710  $overall[$query]['total_avg_results'] = $new_average;
711  }//end if
712  }//end if
713 
714  }//end _combineOverallResults()
715 
716 
725  private function _printCollectionHeader($collection_id)
726  {
727  if ($collection_id === FALSE) {
728  // The total header
729  $header = '<br /><strong>Totals</strong>';
730  } else {
731  $fm = $GLOBALS['SQ_SYSTEM']->am->getSystemAsset('funnelback_manager');
732  $name = $fm->getCollectionName($collection_id);
733  if (empty($name)) {
734  $header = '<br /><strong>Collection "'.$collection_id.'"</strong>';
735  } else {
736  $header = '<br /><strong>Collection: '.$name.'</strong>';
737  }//end if
738  }//end if
739 
740  return $header;
741 
742  }//end _printCollectionHeader()
743 
744 
754  private function _formatLine($data, $type=TRUE, $total=FALSE)
755  {
756  $query = array_get_index($data, 'query', NULL);
757  if (is_null($query)) return '';
758  ob_start();
759  if ($total) {
760  ?>
761  <tr>
762  <td class="sq-backend-table-cell"><?php echo $query; ?></td>
763  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo array_get_index($data, 'total_queries', 0); ?></td>
764  <?php if ($type) { ?>
765  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo array_get_index($data, 'total_results', 0); ?></td>
766  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo round(array_get_index($data, 'total_avg_results', 0), 2); ?></td>
767  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo array_get_index($data, 'total_min_results', 0); ?></td>
768  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo array_get_index($data, 'total_max_results', 0); ?></td>
769  <?php } ?>
770  </tr>
771  <?php
772  } else {
773  ?>
774  <tr>
775  <td class="sq-backend-table-cell"><?php echo $query; ?></td>
776  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo array_get_index($data, 'queries', 0); ?></td>
777  <?php if ($type) { ?>
778  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo array_get_index($data, 'total_results', 0); ?></td>
779  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo round(array_get_index($data, 'avg_results', 0), 2); ?></td>
780  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo array_get_index($data, 'min_results', 0); ?></td>
781  <td class="sq-backend-table-cell" style="width: 25px;"><?php echo array_get_index($data, 'max_results', 0); ?></td>
782  <?php } ?>
783  </tr>
784  <?php
785  }//end if
786  $line = ob_get_contents();
787  ob_end_clean();
788 
789  return $line;
790 
791  }//end _formatLine()
792 
793 
803  private function _printQueryResults($good, $fail)
804  {
805  ob_start();
806  ?>
807  <br />
808  <table class="sq-backend-table">
809  <tr>
810  <td class="sq-backend-table-header" style="width: 200px"><?php echo translate('fnb_log_popular_queries'); ?></td>
811  <td class="sq-backend-table-header"><?php echo translate('fnb_log_total_queries'); ?></td>
812  <td class="sq-backend-table-header"><?php echo translate('fnb_log_total_results'); ?></td>
813  <td class="sq-backend-table-header"><?php echo translate('fnb_log_avg_results'); ?></td>
814  <td class="sq-backend-table-header"><?php echo translate('lowest'); ?></td>
815  <td class="sq-backend-table-header"><?php echo translate('highest'); ?></td>
816  </tr>
817  <?php echo (!empty($good) ? implode("\n", $good) : '<td class="sq-backend-table-cell" colspan="6">'.translate('fnb_log_no_successful_queries').'</td>'); ?>
818  </table>
819 
820  <table class="sq-backend-table">
821  <tr>
822  <td class="sq-backend-table-header" style="width: 200px"><?php echo translate('fnb_log_failed_queries'); ?></td>
823  <td class="sq-backend-table-header"><?php echo translate('fnb_log_total_failed_queries'); ?></td>
824  </tr>
825  <?php echo (!empty($fail) ? implode("\n", $fail) : '<td class="sq-backend-table-cell" colspan="2">'.translate('fnb_log_no_failed_queries').'</td>'); ?>
826  </table>
827  <br />
828  <?php
829  $line = ob_get_contents();
830  ob_end_clean();
831 
832  return $line;
833 
834  }//end _printQueryResults()
835 
836 
845  private function _cleanQuery($query)
846  {
847  $invalid = Array('#', '&', ';', '`', '|', '*', '?', '~', '<', '>', '^', '(', ')', '[', ']', '{', '}', '$');
848  $query = str_replace($invalid, '', $query);
849  $query = str_replace(' ', '', $query);
850  $query = str_replace('"', '', $query);
851  $query = str_replace("'", '', $query);
852  $query = str_replace('.', '_', $query);
853  $query = trim($query);
854 
855  return $query;
856 
857  }//end _cleanQuery()
858 
859 
869  private function _getPeriod($date, $type)
870  {
871  $type = (string) $type;
872  switch ($type) {
873  case 'daily':
874  $period = 'D'.date('Ymd', $date);
875  break;
876 
877  case 'monthly':
878  $period = 'M'.date('Ym', $date);
879  break;
880 
881  case 'weekly':
882  default:
883  $period = 'W'.date('YW', $date);
884  break;
885  }//end switch
886 
887  return $period;
888 
889  }//end _getPeriod()
890 
891 
900  private function _getQueryHash($query)
901  {
902  $hash = Array();
903 
904  if (strlen($query) <= 4) {
905  // The Query is less than 4 chars, so pad it up
906  $query = str_pad($query, 4, 'a');
907  }//end if
908 
909  // Hashing up based on the first 4 chars
910  $hash_bits = str_split(substr($query, 0, 4), 2);
911  foreach ($hash_bits as $bit) {
912  $bit = (string) $bit;
913  do {
914  $hash_part = 0;
915  for ($i=0; $i<strlen($bit); $i++) {
916  $hash_part += ord($bit{$i});
917  }//end foreach
918  $bit = (string) $hash_part;
919  } while ($hash_part < 100);
920  $hash[] = (int) $hash_part;
921  }//end foreach
922 
923  if (!empty($hash) && count($hash) == 2) {
924  return implode('/', $hash);
925  } else {
926  return 'na';
927  }//end if
928 
929  }//end _getQueryHash()
930 
931 
940  private function _maintainReport(&$job_vars)
941  {
942  $data_path = $job_vars['report']->data_path;
943 
944  $type = $job_vars['report']->attr('rollover_period');
945  $type = (string) $type;
946  $match = strtoupper(substr($type, 0, 1));
947  switch ($type) {
948  case 'daily':
949  $valid = Array(
950  date('Ymd', strtotime('-2 days')),
951  date('Ymd', strtotime('-1 day')),
952  date('Ymd'),
953  );
954  break;
955 
956  case 'monthly':
957  $valid = Array(
958  date('Ym', strtotime('-1 month')),
959  date('Ym'),
960  );
961  break;
962 
963  case 'weekly':
964  default:
965  $valid = Array(
966  date('YW', strtotime('-1 week')),
967  date('YW'),
968  );
969  break;
970  }//end switch
971 
972  // Create base directories
973  $base_directories = Array('cache', 'total', 'report');
974  foreach ($base_directories as $dir) {
975  create_directory($data_path.'/'.$dir);
976  }//end foreach
977 
978  // Clean cache files
979  $cache_files = glob($data_path.'/cache/*');
980  foreach ($cache_files as $cache_dir) {
981  $cache_file = basename($cache_dir);
982  // Invalid cache files
983  $cache_match = strtoupper(substr($cache_file, 0, 1));
984  if ($cache_match != $match) {
985  delete_directory($cache_dir);
986  }//end if
987 
988  // Too old
989  $date_match = substr($cache_file, 1);
990  if (!in_array($date_match, $valid)) {
991  delete_directory($cache_dir);
992  }//end if
993  }//end foreach
994 
995  // Clean total files
996  $total_files = glob($data_path.'/total/*');
997  foreach ($total_files as $total_dir) {
998  $total_file = basename($total_dir);
999  // Invalid total files
1000  $total_match = strtoupper(substr($total_file, 0, 1));
1001  if ($total_match != $match) {
1002  delete_directory($total_dir);
1003  }//end if
1004 
1005  // Too old
1006  $date_match = substr($total_file, 1);
1007  if (!in_array($date_match, $valid)) {
1008  delete_directory($total_dir);
1009  }//end if
1010  }//end foreach
1011 
1012  }//end _maintainReport()
1013 
1014 
1023  private function _getLatest(&$asset)
1024  {
1025  $latest = FALSE;
1026  $path = $asset->data_path.'/report';
1027  $reports = glob($path.'/report-*.html');
1028  foreach ($reports as $report) {
1029  $report_name = basename($report, '.html');
1030  $report_date = strtotime(str_replace('report-', '', str_replace('_', '-', $report_name)));
1031  if ($latest === FALSE || $report_date > $latest) {
1032  $latest = $report_date;
1033  }//end if
1034  }//end foreach
1035 
1036  return $latest;
1037 
1038  }//end _getLatest()
1039 
1040 
1050  private function _getReport(&$asset, $date)
1051  {
1052  $date = date('d-m-Y', $date);
1053  $report_path = $asset->data_path.'/report/report-'.$date.'.html';
1054  if (!file_exists($report_path)) {
1055  $report_path = '';
1056  }//end if
1057 
1058  return $report_path;
1059 
1060  }//end _getReport()
1061 
1062 
1073  public function paintReport(&$asset, &$o, $prefix)
1074  {
1075  $printed = FALSE;
1076  $latest = $this->_getLatest($asset);
1077  $all_reports_raw = glob($asset->data_path.'/report/report-*.html');
1078  $all_reports = Array();
1079  foreach ($all_reports_raw as $report_path) {
1080  $report_name = basename($report_path);
1081  $report_date = strtotime(str_replace('.html', '', str_replace('report-', '', str_replace('_', '-', $report_name))));
1082  if ($report_date !== FALSE) {
1083  if ($report_date == $latest) {
1084  $all_reports[$report_date] = translate('current');
1085  $all_reports[$report_date] = translate('fb_sch_log_report_report_item', date('d-m-Y', $report_date));
1086  } else {
1087  $all_reports[$report_date] = translate('fb_sch_log_report_report_item', date('d-m-Y', $report_date));
1088  }//end if
1089  }//end if
1090  }//end foreach
1091 
1092  $selected = array_get_index($_POST, $prefix.'_select_report', '');
1093 
1094  if (!empty($all_reports)) {
1095  krsort($all_reports);
1096  combo_box($prefix.'_select_report', $all_reports, FALSE, $selected);
1097  submit_button($prefix.'submit_report', translate('select_report'));
1098  echo '<br />';
1099  }//end if
1100 
1101  // Show the selected (or latest if none selected)
1102  if (array_key_exists($selected, $all_reports)) {
1103  include_once($asset->data_path.'/report/report-'.date('d-m-Y', $selected).'.html');
1104  $printed = TRUE;
1105  } else {
1106  if ($latest !== FALSE) {
1107  $report_path = $this->_getReport($asset, $latest);
1108  if (is_file($report_path)) {
1109  include_once($report_path);
1110  $printed = TRUE;
1111  }//end if
1112  }//end if
1113  }//end if
1114 
1115  // No reports printed... show something
1116  if ($printed === FALSE) {
1117  echo translate('fb_sch_log_report_generate_at_next_rotation');
1118  }//end if
1119 
1120  }//end paintReport()
1121 
1122 
1133  public function paintRegenerate(&$asset, &$o, $prefix)
1134  {
1135  $generated_user = $asset->attr('generated_user');
1136  if (empty($generated_user)) {
1137  echo translate('report_not_generated').'<br />';
1138  } else {
1139  echo '<p>';
1140  echo ' <b>'.translate('report_generated').'</b><br />';
1141  echo ' '.translate('date').': '.$asset->attr('generated_date');
1142  echo ' <br />';
1143  echo ' '.translate('user').': '.$asset->attr('generated_user');
1144  echo '</p>';
1145  }
1146 
1147  return FALSE;
1148 
1149  }//end paintRegenerate()
1150 
1151 
1152 }//end class
1153 
1154 ?>