Add table filter system
This commit is contained in:
committed by
Chris Morgan
parent
13fe229774
commit
b2adeab95a
191
include/db_filter.php
Normal file
191
include/db_filter.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Classes for managing SQL filters (parts of SQL queries)
|
||||
*
|
||||
* Copyright 2008 BitSplash Software LLC
|
||||
* Copyright 2008 Alexander N. Sørnes <alex@thehandofagony.com>
|
||||
*
|
||||
*/
|
||||
|
||||
define('FILTER_LIKE', 1);
|
||||
define('FILTER_EQUALS', 2);
|
||||
define('FILTER_GREATER_THAN', 3);
|
||||
define('FILTER_LESS_THAN', 4);
|
||||
define('FILTER_NOT_EQUALS', 5);
|
||||
define('FILTER_NOT_LIKE', 6);
|
||||
|
||||
/* A filter as part of an SQL query, such as something = 'somevalue' */
|
||||
class Filter
|
||||
{
|
||||
private $sColumn; // The table column the filter is for
|
||||
private $iType; // The type of filter, like EQUALS, LIKE
|
||||
private $sData; // What the column is to be compared to */
|
||||
|
||||
public function Filter($sColumn, $iType, $sData)
|
||||
{
|
||||
$this->sColumn = $sColumn;
|
||||
$this->iType = $iType;
|
||||
$this->sData = $sData;
|
||||
}
|
||||
|
||||
public function getColumn()
|
||||
{
|
||||
return $this->sColumn;
|
||||
}
|
||||
|
||||
public function setData($sData)
|
||||
{
|
||||
$this->sData = $sData;
|
||||
}
|
||||
|
||||
public function getOperatorId()
|
||||
{
|
||||
return $this->iType;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
return $this->sData;
|
||||
}
|
||||
|
||||
public function getOperator()
|
||||
{
|
||||
switch($this->iType)
|
||||
{
|
||||
case FILTER_LIKE:
|
||||
return 'LIKE';
|
||||
case FILTER_EQUALS:
|
||||
return '=';
|
||||
case FILTER_LESS_THAN:
|
||||
return '<';
|
||||
case FILTER_GREATER_THAN:
|
||||
return '>';
|
||||
case FILTER_NOT_EQUALS:
|
||||
return '!=';
|
||||
case FILTER_NOT_LIKE:
|
||||
return 'NOT LIKE';
|
||||
|
||||
default:
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
|
||||
public function getFilter()
|
||||
{
|
||||
$sOp = $this->getOperator();
|
||||
|
||||
return "{$this->sColumn} $sOp '{$this->sData}'";
|
||||
}
|
||||
}
|
||||
|
||||
/* Class handling tables where the user can filter contents */
|
||||
class FilterSet
|
||||
{
|
||||
private $aFilters; // Array of filters for this table
|
||||
|
||||
public function FilterSet($sTableName = '')
|
||||
{
|
||||
$this->aFilters = array();
|
||||
|
||||
if($sTableName)
|
||||
$this->loadTable($sTableName);
|
||||
}
|
||||
|
||||
public function loadTable($sTableName)
|
||||
{
|
||||
$sQuery = "SELECT * FROM $sTableName";
|
||||
$hResult = query_appdb($sQuery);
|
||||
|
||||
while($oRow = mysql_fetch_object($hResult))
|
||||
{
|
||||
$this->addFilterObject(new Filter($oRow->sColumn, $oRow->iType, $oRow->sData));
|
||||
}
|
||||
}
|
||||
|
||||
public function saveTable($sTableName)
|
||||
{
|
||||
$hResult = query_appdb("DROP TABLE IF EXISTS $sTableName");
|
||||
|
||||
$hResult = query_appdb("CREATE TABLE $sTableName (
|
||||
sColumn VARCHAR(255) NOT NULL,
|
||||
iType INT(3) NOT NULL,
|
||||
sData VARCHAR(255) NOT NULL DEFAULT ''
|
||||
)");
|
||||
|
||||
if(!$hResult)
|
||||
return false;
|
||||
|
||||
$bSuccess = true;
|
||||
foreach($this->aFilters as $oFilter)
|
||||
{
|
||||
$hResult = query_appdb("INSERT INTO $sTableName (sColumn,iType,sData)
|
||||
VALUES('{$oFilter->getColumn()}','{$oFilter->getOperatorId()}','{$oFilter->getData()}')");
|
||||
if(!$hResult)
|
||||
$bSuccess = false;
|
||||
}
|
||||
return $bSuccess;
|
||||
}
|
||||
|
||||
public function addFilterObject(Filter $oFilter)
|
||||
{
|
||||
$this->aFilters[] = $oFilter;
|
||||
}
|
||||
|
||||
public function AddFilter($sColumn, $iType, $sData)
|
||||
{
|
||||
$this->aFilters[] = new Filter($sColumn, $iType, $sData);
|
||||
}
|
||||
|
||||
public function getFilterCount()
|
||||
{
|
||||
return sizeof($this->aFilters);
|
||||
}
|
||||
|
||||
public function getFilters()
|
||||
{
|
||||
return $this->aFilters;
|
||||
}
|
||||
|
||||
public function getWhereClause()
|
||||
{
|
||||
$sFilter = '';
|
||||
for($i = 0; $i < sizeof($this->aFilters); $i++)
|
||||
{
|
||||
$oFilter = $this->aFilters[$i];
|
||||
|
||||
$sFilter .= $oFilter->getFilter();
|
||||
|
||||
if($i < sizeof($this->aFilters) - 1)
|
||||
$sFilter .= ' AND ';
|
||||
}
|
||||
|
||||
return $sFilter;
|
||||
}
|
||||
|
||||
function getQuery($sTable, $iLimit = 0)
|
||||
{
|
||||
$sWhere = $this->getFilterCount() ? 'WHERE '.$this->getWhereClause() : '';
|
||||
$sQuery = "SELECT * FROM $sTable $sWhere";
|
||||
|
||||
$iLimit = mysql_real_escape_string($iLimit);
|
||||
|
||||
if($iLimit)
|
||||
$sQuery .= " LIMIT 0,$iLimit";
|
||||
|
||||
return $sQuery;
|
||||
}
|
||||
|
||||
function getMatchedItems($sTable, $iLimit = 0)
|
||||
{
|
||||
return query_appdb($this->getQuery($sTable, $iLimit));
|
||||
}
|
||||
|
||||
function getMatchedItemsCount($sTable)
|
||||
{
|
||||
return mysql_num_rows($this->getMatchedItems($sTable));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
251
include/db_filter_ui.php
Normal file
251
include/db_filter_ui.php
Normal file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* User interface for the SQL filter classes
|
||||
*
|
||||
* Copyright 2008 BitSplash Software LLC
|
||||
* Copyright 2008 Alexander N. Sørnes <alex@thehandofagony.com>
|
||||
*
|
||||
*/
|
||||
|
||||
require_once('db_filter.php');
|
||||
|
||||
/* Info describing an available filter: what column it applies to,
|
||||
and what comparison options are available */
|
||||
class FilterInfo
|
||||
{
|
||||
private $sColumn;
|
||||
private $sDisplayName;
|
||||
private $aTypes; // Available filters for this column
|
||||
|
||||
public function FilterInfo($sColumn, $sDisplayName, $aTypes)
|
||||
{
|
||||
$this->sColumn = $sColumn;
|
||||
$this->sDisplayName = $sDisplayName;
|
||||
$this->aTypes = $aTypes;
|
||||
}
|
||||
|
||||
public function getColumn()
|
||||
{
|
||||
return $this->sColumn;
|
||||
}
|
||||
|
||||
public function getDisplayName()
|
||||
{
|
||||
return $this->sDisplayName;
|
||||
}
|
||||
|
||||
public function getTypes()
|
||||
{
|
||||
return $this->aTypes;
|
||||
}
|
||||
|
||||
public static function getOpName($iOpId)
|
||||
{
|
||||
switch($iOpId)
|
||||
{
|
||||
case FILTER_EQUALS:
|
||||
return 'equal to';
|
||||
case FILTER_LIKE:
|
||||
return 'like';
|
||||
case FILTER_NOT_LIKE:
|
||||
return 'not like';
|
||||
case FILTER_NOT_EQUALS:
|
||||
return 'not equal to';
|
||||
case FILTER_LESS_THAN:
|
||||
return 'less than';
|
||||
case FILTER_GREATER_THAN:
|
||||
return 'greater than';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Class handling tables where the user can filter contents */
|
||||
class FilterInterface
|
||||
{
|
||||
private $aFilterInfo;
|
||||
private $oFilterSet;
|
||||
|
||||
public function FilterInterface($sTableName = '')
|
||||
{
|
||||
$this->aFilterInfo = array();
|
||||
$this->oFilterSet = new FilterSet(mysql_real_escape_string($sTableName));
|
||||
}
|
||||
|
||||
public function AddFilterObject(Filter $oFilter)
|
||||
{
|
||||
$this->oFilterSet->AddFilterObject($oFilter);
|
||||
}
|
||||
|
||||
public function setFilterSet(FilterSet $oSet)
|
||||
{
|
||||
$this->oFilterSet = $oSet;
|
||||
}
|
||||
|
||||
/* Convenience function to add a filter option */
|
||||
public function AddFilterInfo($sColumn, $sDisplayName, $aTypes)
|
||||
{
|
||||
$this->aFilterInfo[$sColumn] = new FilterInfo($sColumn, $sDisplayName, $aTypes);
|
||||
}
|
||||
|
||||
public function getItemEditor($iId, Filter $oFilter)
|
||||
{
|
||||
$sColumn = $oFilter->getColumn();
|
||||
$oColumn = $this->aFilterInfo[$sColumn];
|
||||
|
||||
$sId = ($iId == -1) ? '' : $iId;
|
||||
$shEditor = $oColumn->getDisplayName();
|
||||
|
||||
$shEditor .= " <select name='i{$sColumn}Op$sId'>";
|
||||
|
||||
if($iId == -1)
|
||||
{
|
||||
$sText = 'select';
|
||||
$sSel = " selected='selected'";
|
||||
} else
|
||||
{
|
||||
$sSel = '';
|
||||
$sText = 'remove';
|
||||
}
|
||||
|
||||
$shEditor .= "<option value='0'$sSel>-- $sText --</option>";
|
||||
|
||||
foreach($oColumn->getTypes() as $iType)
|
||||
{
|
||||
if($oFilter->getOperatorId() == $iType)
|
||||
$sSel = " selected='selected'";
|
||||
else
|
||||
$sSel = '';
|
||||
$shEditor .= "<option value='$iType'$sSel>".$oColumn->getOpName($iType).'</option><br />';
|
||||
}
|
||||
|
||||
$shEditor .= '</select> ';
|
||||
|
||||
$shEditor .= "<input type='text' value=\"{$oFilter->getData()}\" name='s{$sColumn}Data$sId' size='30' />";
|
||||
|
||||
return $shEditor;
|
||||
}
|
||||
|
||||
public function getEditor()
|
||||
{
|
||||
$shEditor = '';
|
||||
$aCounts = array();
|
||||
|
||||
$shEditor .= 'Add new filter<br />';
|
||||
foreach($this->aFilterInfo as $oOption)
|
||||
{
|
||||
$oDummyFilter = new Filter($oOption->getColumn(), 0, '');
|
||||
$shEditor .= $this->getItemEditor(-1, $oDummyFilter);
|
||||
$shEditor .= '<br />';
|
||||
}
|
||||
|
||||
if(sizeof($this->oFilterSet->getFilters()))
|
||||
$shEditor .= '<br />Active filters<br />';
|
||||
foreach($this->oFilterSet->getFilters() as $oFilter)
|
||||
{
|
||||
$sColumn = $oFilter->getColumn();
|
||||
|
||||
if(!array_key_exists($sColumn, $aCounts))
|
||||
$aCounts[$sColumn] = 0;
|
||||
|
||||
$shEditor .= $this->getItemEditor($aCounts[$sColumn], $oFilter);
|
||||
$shEditor .= '<br />';
|
||||
|
||||
$aCounts[$sColumn]++;
|
||||
}
|
||||
|
||||
return $shEditor;
|
||||
}
|
||||
|
||||
public function getFilterInfo()
|
||||
{
|
||||
return $this->aFilterInfo;
|
||||
}
|
||||
|
||||
/* Reads all input related to filters for the given table column */
|
||||
public function readInputForColumn($aClean, FilterInfo $oOption)
|
||||
{
|
||||
$aReturn = array();
|
||||
|
||||
for($i = 0; array_key_exists('i'.$oOption->getColumn()."Op$i", $aClean); $i++)
|
||||
{
|
||||
$sData = mysql_real_escape_string($aClean["s{$oOption->getColumn()}Data$i"]);
|
||||
$iOp = $aClean["i{$oOption->getColumn()}Op$i"];
|
||||
|
||||
if(!$iOp)
|
||||
continue;
|
||||
|
||||
$oFilter = new Filter($oOption->getColumn(), $iOp, $sData);
|
||||
$aReturn[] = $oFilter;
|
||||
}
|
||||
|
||||
if(array_key_exists('i'.$oOption->getColumn()."Op", $aClean))
|
||||
{
|
||||
$i = sizeof($aReturn);
|
||||
$sData = $aClean["s{$oOption->getColumn()}Data"];
|
||||
$iOp = $aClean["i{$oOption->getColumn()}Op"];
|
||||
|
||||
if($iOp)
|
||||
{
|
||||
$oFilter = new Filter($oOption->getColumn(), $iOp, $sData);
|
||||
$aReturn[] = $oFilter;
|
||||
}
|
||||
}
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/* Reads an input array get enabled filters from form data.
|
||||
The given TableFilterSet defines available options */
|
||||
public function readInput($aClean)
|
||||
{
|
||||
foreach($this->getFilterInfo() as $oOption)
|
||||
{
|
||||
foreach($this->readInputForColumn($aClean, $oOption) as $oNewFilter)
|
||||
$this->AddFilterObject($oNewFilter);
|
||||
}
|
||||
}
|
||||
|
||||
public function loadTable($sTableName)
|
||||
{
|
||||
$this->oFilterSet->loadTable(mysql_real_escape_string($sTableName));
|
||||
}
|
||||
|
||||
public function saveTable($sTableName)
|
||||
{
|
||||
$this->oFilterSet->saveTable(mysql_real_escape_string($sTableName));
|
||||
}
|
||||
|
||||
public function getFilterCount()
|
||||
{
|
||||
return $this->oFilterSet->getFilterCount();
|
||||
}
|
||||
|
||||
public function getTable($sTable, $iLimit = 0)
|
||||
{
|
||||
$hResult = $this->oFilterSet->getMatchedItems($sTable, $iLimit);
|
||||
|
||||
if(!$hResult)
|
||||
return;
|
||||
|
||||
echo 'Selected '.$this->oFilterSet->getMatchedItemsCount($sTable).' rows<br><br>';
|
||||
|
||||
$oTable = new Table();
|
||||
|
||||
while($aRow = mysql_fetch_row($hResult))
|
||||
{
|
||||
$oRow = new TableRow();
|
||||
|
||||
foreach($aRow as $sCell)
|
||||
{
|
||||
$oRow->AddTextCell($sCell);
|
||||
}
|
||||
|
||||
$oTable->AddRow($oRow);
|
||||
}
|
||||
|
||||
return $oTable->getString();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user