Restructure Reporter's Query Functionality. Mostly rewritten, much easier to use for other purposes (hint: coming soon). Still buggy, but we'll fix it as we go.

This commit is contained in:
robert%accettura.com 2005-10-26 03:21:17 +00:00
Родитель 4cb6404743
Коммит 886da04a8f
4 изменённых файлов: 440 добавлений и 198 удалений

Просмотреть файл

@ -0,0 +1,13 @@
<?php
require_once($config['base_path'].'/includes/contrib/adodb/adodb.inc.php');
class db extends ADOConnection
{
function NewADOConnection(){
$db = NewADOConnection($config['db_dsn']);
$db->debug = true;
if (!$db) die("Connection failed");
return $db;
}
}
?>

Просмотреть файл

@ -120,6 +120,9 @@ function strMiddleReduceWordSensitive($string, $max = 50, $rep = '[...]') {
function resolveProblemTypes($q){
global $problemTypes;
if ($q > sizeof($problemTypes)){
return "Unknown";
}
return $problemTypes[$q];
}
@ -130,201 +133,6 @@ function resolveBehindLogin($q){
return "No";
}
function navigation($pre_href='?page=', $post_href='', $num_items=0, $items_per_page=25, $active=1, $nearby=5, $threshold=100){
// Original From: http://www.phpbuilder.com/snippet/detail.php?type=snippet&id=866
// License: GNU General Public License
// Info: 1336 2.0.1 10/19/02 18:01 mp96brbj
/*
The main function:
Returns HTML string with a navigation bar, easily styled with CSS.
Returns false if no navigation bar was necessary (if everything
could fit on one page).
$pre_href = everyhing in the links' HREF before the active page's number.
$post_href = everyhing *after* the active page's number.
$num_items = total number of items available.
$items_per_page = well, d'uh!
$active = the active page's number.
$nearby = minimum number of nearby pages to $active to display.
$threshold = the smaller the number, the more restrictive the
selection of links will be when $total is very high. This is to
conserve space.
These default settings limit the number of links to a maximum
of about 20.
*/
// &//8230; is the ellipse character: "..."
$space = '<span class="spacer"> &#8230; '."\n\t".'</span>';
// There's no point in printing this string if there are no items,
// Or if they all fit on one page.
if ($num_items > 0 && $num_items > $items_per_page)
{
// STEP 1:
// Force variables into certain values.
// $items_per_page can't be smaller than 1!
// Also, avoid division by zero later on.
$items_per_page = max($items_per_page, 1);
// Calculate the number of listing pages.
$total = ceil($num_items/$items_per_page);
// $active can't be higher than $total or smaller than 1!
$active = max( min($active,$total), 1);
// STEP 2:
// Do the rest.
// Get the sequence of pages to show links to.
$pages = navigationSequence($total, $active, $nearby, $threshold);
// Print a descriptive string.
$first = ($active-1)*$items_per_page + 1;
$last = min($first+$items_per_page-1, $num_items);
if ($first == $last)
$listing = $first;
else
// &//8211; is the EN dash, the proper hyphen to use.
$listing = $first.' - '.$last;
$r = '<p class="navigation">'."\n\tShowing $listing of $num_items<br />\n";
// Initialize the list of links.
$links = array();
// Add "previous" link.
if ($active > 1 && $total > 1)
$links[] = '<a href="'.$pre_href.($active-1).$post_href.
'" class="prev" title="Previous">&laquo;</a>';
// Decide how the each link should be presented.
for($i=0; $i<sizeof($pages); $i++)
{
// Current link.
$curr = $pages[$i];
// See if we should any $spacer in connection to this link.
if ($i>0 AND $i<sizeof($pages)-1)
{
$prev = $pages[$i-1];
$next = $pages[$i+1];
// See if we should any $spacer *before* this link.
// (Don't add one if the last link is already a spacer.)
if ($prev < $curr-1 AND $links[sizeof($links)-1] != $space)
$links[] = $space;
}
// Add the link itself!
// If the link is not the active page, link it.
if ($curr != $active)
$links[] = '<a href="'.$pre_href.$curr.$post_href.'">'.$curr.'</a>';
// Else don't link it.
else
$links[] = '<strong class="active">'.$active.'</strong>';
if ($i>0 AND $i<sizeof($pages)-1)
{
// See if we should any $spacer *after* this link.
// (Don't add one if the last link is already a spacer.)
if ($next > $curr+1 AND $links[sizeof($links)-1] != $space)
$links[] = $space;
}
}
// Add "next" link.
if ($active < $total && $total > 1)
$links[] = '<a href="'.$pre_href.($active+1).$post_href.
'" class="next" title="Next">&raquo;</a>';
// Put it all together.
$r .= "\t".implode($links, "\n\t")."\n</p>\n";
$r = str_replace("\n\t".$space."\n\t", $space, $r);
return $r;
}
else
return false;
}
function navigationSequence($total=1, $active=1, $nearby=5, $threshold=100){
// Original From: http://www.phpbuilder.com/snippet/detail.php?type=snippet&id=866
// License: GNU General Public License
// Info: 1336 2.0.1 10/19/02 18:01 mp96brbj
// STEP 1:
// Force minimum and maximum values.
$total = (int)max($total, 1);
$active = (int)min( max($active,1), $total);
$nearby = (int)max($nearby, 2);
$threshold = (int)max($threshold, 1);
// STEP 2:
// Initialize $pages.
// Array where each key is a page.
// That way we can easily overwrite duplicate keys, without
// worrying about the order of elements.
// Begin by adding the first, the active and the final page.
$pages = array(1=>1, $active=>1, $total=>1);
// STEP 3:
// Add nearby pages.
for ($diff=1; $diff<$nearby+1; $diff++)
{
$pages[min( max($active-$diff,1), $total)] = 1;
$pages[min( max($active+$diff,1), $total)] = 1;
}
// STEP 4:
// Add distant pages.
// What are the greatest and smallest distances between page 1
// and active page, or between active page and final page?
$biggest_diff = max($total-$active, $active);
$smallest_diff = min($total-$active, $active);
// The lower $factor is, the bigger jumps (and ergo fewer pages)
// there will be between the distant pages.
$factor = 0.75;
// If we think there will be too many distant pages to list,
// reduce $factor.
while(pow($total*max($smallest_diff,1), $factor) > $threshold)
$factor *= 0.9;
// Add a page between $active and the farthest end (both upwards
// and downwards). Then add a page between *that* page and
// active. And so on, until we touch the nearby pages.
for ($diff=round($biggest_diff*$factor); $diff>$nearby; $diff=round($diff*$factor))
{
// Calculate the numbers.
$lower = $active-$diff;
$higher = $active+$diff;
// Round them to significant digits (for readability):
// Significant digits should be half or less than half of
// the total number of digits, but at least 2.
$lower = round($lower, -floor(max(strlen($lower),2)/2));
$higher = round($higher, -floor(max(strlen($higher),2)/2));
// Maxe sure they're within the valid range.
$lower = min(max($lower, 1),$total);
$higher = min(max($higher, 1),$total);
// Add them.
$pages[$lower] = 1;
$pages[$higher] = 1;
}
// STEP 5:
// Convert the keys into values and sort them.
$return = array_keys($pages);
sort($return);
return $return;
}
function printheaders(){
$now = date("D M j G:i:s Y T");
@ -341,4 +149,4 @@ function strip_all_tags($input){
}
return $input;
}
?>
?>

Просмотреть файл

@ -0,0 +1,383 @@
<?php
require_once($config['base_path'].'/includes/contrib/adodb/adodb.inc.php');
class query
{
function query(){}
function getQueryInputs(){
global $config;
// approved "selectable" and "queryable" fields
$approved_selects = array('count' /*special */,
'host_id',
'host_hostname',
'report_id',
'report_url',
'report_host_id',
'report_problem_type',
'report_description',
'report_behind_login',
'report_useragent',
'report_platform',
'report_oscpu',
'report_language',
'report_gecko',
'report_buildconfig',
'report_product',
/* 'report_email',
'report_ip',
*/ 'report_file_date'
);
$approved_wheres = array('host_hostname',
'report_id',
'report_url',
'report_problem_type',
'report_description',
'report_behind_login',
'report_useragent',
'report_platform',
'report_oscpu',
'report_gecko',
'report_language',
'report_gecko',
'report_buildconfig',
'report_product',
'report_file_date'
);
/*******************
* ASCDESC
*******************/
if (strtolower($_GET['ascdesc']) == 'asc' || strtolower($_GET['ascdesc']) == 'asc'){
$ascdesc = $_GET['ascdesc'];
} else {
$ascdesc = 'desc';
}
/*******************
* ORDER BY
*******************/
if (isset($_GET['orderby']) && in_array($_GET['orderby'], $approved_wheres)) {
$orderby = $_GET['orderby'];
} else {
$orderby = 'report_file_date';
}
// no default, since we sub order later on
/*******************
* SHOW (really "Limit")
*******************/
if (!$_GET['show']){
$show = $config['show'];
} else {
$show = $_GET['show'];
}
// no more than 200 results per page
if (!$_GET['show'] > 200){
$show = 200;
}
/*******************
* PAGE (really other part of "Limit"
*******************/
if (!$_GET['page']){
$page = 1;
} else {
$page = $_GET['page'];
}
/*******************
* Count
*******************/
if (isset($_GET['count'])){
$count = 'host_id'; // XX limitation for now
}
// if nothing... it's nothing
/*******************
* SELECT
*******************/
$selected = array();
/*
If user defines what to select and were not counting, just
use their input.
*/
if ($_GET['selected'] && !isset($_GET['count'])){
foreach($_GET['selected'] as $selectedChild){
$selected[$selectedChild] = $config['fields'][$selectedChild];
}
} else {
// Otherwise, we do it for them
$selected = array('report_id' => 'Report ID', 'host_hostname' => 'Host');
}
// If we are counting, we need to add A column for it
if (isset($_GET['count'])){
// set the count variable
$selected['count'] = 'Number';
unset($selected['report_id']);
// Hardcode host_id
$_GET['count'] = 'host_id'; // XXX we just hardcode this (just easier for now, and all people will be doing).
// XX NOTE: We don't escape count below because 'host_id' != `host_id`.
//Sort by
if (!isset($orderby)){ //XXX this isn't ideal, but nobody will sort by date (pointless and not an option)
$orderby = 'count';
}
}
else {
if(!isset($selected['report_id'])){
$selected['report_id'] = "Report ID";
$artificialReportID = true;
}
// $selected['report_file_date'] = "Date";
}
/*******************
* WHERE
*******************/
$where = array();
reset($_GET);
while (list($column, $value) = each($_GET)) {
/* To help prevent stupidity with columns, we only add
it to the WHERE statement if it's passes as a column
we allow. Others simly don't make sense, or we don't
allow them for security purposes.
*/
if (in_array($column, $approved_wheres)){
// these are our various ways of saying "no value"
if (($value != -1) && ($value != null) && ($value != '0')){
// if there's a wildcard (%,_) we should use 'LIKE', otherwise '='
if ((strpos($value, "%") === false) && (strpos($value, "_") === false)){
$operator = "=";
} else {
$operator = "LIKE";
}
// Add to query
if (in_array($column, $approved_wheres)){
$where[] = array($column, $operator, $value);
}
}
}
}
return array('selected' => $selected,
'where' => $where,
'orderby' => $orderby,
'ascdesc' => $ascdesc,
'show' => $show,
'page' => $page,
'count' => $count,
'artificialReportID' => $artificialReportID
);
}
function doQuery($select, $where, $orderby, $ascdesc, $show, $page, $count){
global $db;
$db->debug = true;
/************
* SELECT
************/
$sql_select = 'SELECT ';
foreach($select as $select_child => $select_child_title){
// we don't $db->quote here since unless it's in our approved array (exactly), we drop it anyway. i.e. report_id is on our list, 'report_id' is not.
// we sanitize on our own
if ($select_child == 'count'){
$sql_select .= 'COUNT( '.$count.' ) AS count';
$orderby = 'COUNT';
} else {
$sql_select .= $select_child;
}
$sql_select .= ', ';
}
if(sizeof($select) > 0){
$sql_select = substr($sql_select, 0, -2);
$sql_select = $sql_select.' ';
}
/************
* FROM
************/
$sql_from = 'FROM `report`, `host`';
/************
* WHERE
************/
$sql_where = 'WHERE ';
foreach($where as $where_child){
$sql_where .= $where_child[0].' '.$where_child[1].' '.$db->quote($where_child[2]).' AND ';
}
// Dates ar special
// if the user didn't delete the default YYYY-MM-DD mask, we do it for them
if ($_GET['report_file_date_start'] == 'YYYY-MM-DD'){
$_GET['report_file_date_start'] = null;
}
if ($_GET['report_file_date_end'] == 'YYYY-MM-DD'){
$_GET['report_file_date_end'] = null;
}
if (($_GET['report_file_date_start'] != null) || ($_GET['report_file_date_end'] != null)){
// if we have both, we do a BETWEEN
if ($_GET['report_file_date_start'] && $_GET['report_file_date_end']){
$sql_where .= "(report_file_date BETWEEN ".$db->quote($_GET['report_file_date_start'])." and ".$db->quote($_GET['report_file_date_end']).") AND ";
}
// if we have only a start, then we do a >
else if ($_GET['report_file_date_start']){
$sql_where .= "report_file_date > ".$db->quote($_GET['report_file_date_start'])." AND ";
}
// if we have only a end, we do a <
else if ($_GET['report_file_date_end']){
$sql_where .= "report_file_date < ".$db->quote($_GET['report_file_date_end'])." AND ";
}
}
if(sizeof(trim($sql_where)) <= 0){
$sql_where .= ' AND ';
}
$sql_where .= 'host.host_id = report_host_id ';
/************
* OrderBy
************/
if($orderby){
$sql_orderby = 'ORDER BY '.$orderby.' ';
}
/*******************
* Count
*******************/
if (isset($_GET['count'])){
$sql_groupby = 'GROUP BY host_id DESC ';
}
$sql = $sql_select." \r".$sql_from." \r".$sql_where." \r".$sql_groupby.$sql_orderby.$ascdesc." \r".$sql_subOrder;
// Calculate Start
$start = ($page-1)*$show;
/**************
* QUERY
**************/
$dbQuery = $db->SelectLimit($sql,$show,$start,$inputarr=false);
if ($dbQuery){
while (!$dbQuery->EOF) {
$dbResult[] = $dbQuery->fields;
$dbQuery->MoveNext();
}
}
/**************
* Count Total
**************/
if($dbQuery){
$totalQuery = $db->Execute("SELECT COUNT(*)
FROM `report`, `host`
$sql_where");
$totalResults = $totalQuery->fields['COUNT(*)'];
}
return array('data' => $dbResult, 'totalResults' => $totalResults);
}
function continuityParams($query_input){
reset($query_input['where']);
foreach($query_input['where'] as $node => $item){
if($item[0] == 'report_id' && $query_input['artificialReportID']){
} else {
if(!is_numeric($item[2])){
$continuity_params .= $item[0].'='.$item[2];
} else {
$continuity_params .= $item[0].'='.urlencode($item[2]);
}
$continuity_params .= '&amp;';
}
}
foreach($query_input['selected'] as $selected_node => $selected_item){
if($selected_node == 'report_id' && $query_input['artificialReportID']){
} else {
$continuity_params .= 'selected%5B%5D='.$selected_node.'&amp;';
}
}
if($query_input['count']){
$continuity_params .= '&amp;count=on';
}
return $continuity_params;
}
function columnHeaders($query_input, $continuity_params){
$columnCount = 0;
$column[$columnCount]['text'] = 'Detail';
$columnCount++;
foreach($query_input['selected'] as $title_name => $title){
if($title_name == 'report_id' && $query_input['artificialReportID']){
} else {
$column[$columnCount]['text'] = $title;
$o_orderby = $title_name;
if ($query_input['ascdesc'] == 'desc'){
$o_ascdesc = 'asc';
} else {
$o_ascdesc = 'desc';
}
$column[$columnCount]['url'] = '?'.$continuity_params.'&amp;orderby='.$o_orderby.'&amp;ascdesc='.$o_ascdesc;
$columnCount++;
}
}
return $column;
}
function outputHTML($result, $query_input){
// Continuity
$continuity_params = $this->continuityParams($query_input);
// Columns
$columnHeaders = $this->columnHeaders($query_input, $continuity_params);
// Data
$data = array();
$rowNum = 0;
if(sizeof($result['data']) > 0){
foreach($result['data'] as $row){
$colNum = 0;
// Prepend if new_front;
$data[$rowNum][0]['text'] = 'Detail';
if (isset($row['count'])){
$data[$rowNum][0]['url'] = '/query/?host_hostname='.$row['host_hostname'];
}
else {
$data[$rowNum][0]['url'] = '/report/?report_id='.$row['report_id'];
}
$colNum++;
foreach($row as $cellName => $cellData){
if($cellName == 'report_id' && $query_input['artificialReportID']){
} else {
$data[$rowNum][$colNum]['text'] = $cellData;
}
$colNum++;
}
$rowNum++;
}
}
return array('columnHeaders' => $columnHeaders, 'data' => $data);
}
function outputXML(){}
function outputCSV(){}
function outputXLS(){}
function outputRSS(){}
}
?>

Просмотреть файл

@ -3,7 +3,7 @@
<table id="query_table">
<tr class="header">
{section name=mysec loop=$column}
<th>{if $column[mysec].url != null}<a href="{$column[mysec].url}">{/if}{$column[mysec].title}{if $column[mysec].url != null}</a>{/if}</th>
<th>{if $column[mysec].url != null}<a href="{$column[mysec].url}">{/if}{$column[mysec].text}{if $column[mysec].url != null}</a>{/if}</th>
{/section}
</tr>
{section name=mysec2 loop=$row}
@ -14,5 +14,43 @@
</tr>
{/section}
</table>
<div class="navigation">{$navigation}</div>
<div class="navigation">
{strip}
{math equation="($count/$show)" assign="totalPages"}
{if $page > 1}
<a href="?{$continuityParams}&amp;page=1">&lt;</a>
{/if}
{if ($page+20) > $totalPages}
{math equation="$page-($totalPages-($page-20))" assign="start"}
{math equation="$totalPages" assign="max"}
{else}
{math equation="$page" assign="start"}
{math equation="$page+20" assign="max"}
{/if}
{section name=pagelisting start=$start loop=$max step=1}
&nbsp; <a href="?{$continuityParams}&amp;page={$smarty.section.pagelisting.index}">{$smarty.section.pagelisting.index}</a>
{/section}
{if $page+20 < $count/$show}
&nbsp; <a href="?{$continuityParams}&amp;page={$totalPages}">&gt;</a>
{/if}
{/strip}
{*
<hr />
<pre>
Count: {$count}
Page: {$page}
Show: {$show}
TotPage: {$totalPages}
</pre>
*}
</div>
{/if}