diff --git a/include/application.php b/include/application.php
index 64f3cc6..4b13adf 100644
--- a/include/application.php
+++ b/include/application.php
@@ -949,10 +949,20 @@ class Application {
$sExtraTables = '';
$sWhereFilter = $oFilters ? $oFilters->getWhereClause() : '';
- if($sWhereFilter)
+ $aOptions = $oFilters ? $oFilters->getOptions() : array('onlyDownloadable' => 'false');
+
+ if($sWhereFilter || $aOptions['onlyDownloadable'] == 'true')
{
$sExtraTables = ',appVersion';
- $sWhereFilter = " AND appVersion.appId = appFamily.appId AND $sWhereFilter";
+ if($sWhereFilter)
+ $sWhereFilter = " AND $sWhereFilter";
+ $sWhereFilter = " AND appVersion.state = 'accepted' AND appVersion.appId = appFamily.appId $sWhereFilter";
+ }
+
+ if($aOptions['onlyDownloadable'] == 'true')
+ {
+ $sExtraTables .= ',appData';
+ $sWhereFilter .= " AND appData.type = 'downloadurl' AND appData.versionId = appVersion.versionId AND appData.state = 'accepted'";
}
/* Should we add a limit clause to the query? */
if($iRows || $iStart)
@@ -1025,6 +1035,7 @@ class Application {
$oFilter->AddFilterInfo('appVersion.rating', 'Rating', array(FILTER_EQUALS, FILTER_LESS_THAN, FILTER_GREATER_THAN), FILTER_VALUES_ENUM, array('Platinum', 'Gold', 'Silver', 'Bronze', 'Garbage'));
$oFilter->AddFilterInfo('appFamily.catId', 'Category', array(FILTER_EQUALS), FILTER_VALUES_ENUM, $aCatIds, $aCatNames);
$oFilter->AddFilterInfo('appVersion.license', 'License', array(FILTER_EQUALS), FILTER_VALUES_ENUM, $aLicenses);
+ $oFilter->AddFilterInfo('onlyDownloadable', 'Only show downloadable apps', array(FILTER_OPTION_BOOL), FILTER_VALUES_OPTION_BOOL, array('false','true'));
return $oFilter;
}
@@ -1167,10 +1178,20 @@ class Application {
{
$sExtraTables = '';
$sWhereFilter = $oFilters ? $oFilters->getWhereClause() : '';
- if($sWhereFilter)
+ $aOptions = $oFilters ? $oFilters->getOptions() : array('onlyDownloadable' => 'false');
+
+ if($sWhereFilter || $aOptions['onlyDownloadable'] == 'true')
{
$sExtraTables = ',appVersion';
- $sWhereFilter = " AND appVersion.appId = appFamily.appId AND $sWhereFilter";
+ if($sWhereFilter)
+ $sWhereFilter = " AND $sWhereFilter";
+ $sWhereFilter = " AND appVersion.appId = appFamily.appId $sWhereFilter";
+ }
+
+ if($aOptions['onlyDownloadable'] == 'true')
+ {
+ $sExtraTables .= ',appData';
+ $sWhereFilter .= " AND appData.type = 'downloadurl' AND appData.versionId = appVersion.versionId";
}
if($sState != 'accepted' && !application::canEdit())
diff --git a/include/db_filter.php b/include/db_filter.php
index e5a556d..09fa909 100644
--- a/include/db_filter.php
+++ b/include/db_filter.php
@@ -14,7 +14,7 @@ define('FILTER_GREATER_THAN', 3);
define('FILTER_LESS_THAN', 4);
define('FILTER_NOT_EQUALS', 5);
define('FILTER_NOT_LIKE', 6);
-define('FILTER_ENUM', 7);
+define('FILTER_OPTION_BOOL', 7);
/* A filter as part of an SQL query, such as something = 'somevalue' */
class Filter
@@ -72,8 +72,13 @@ class Filter
}
}
- public function getFilter()
+ /* Gets an SQL expression representing the current filter, for use in a WHERE clause */
+ public function getExpression()
{
+ /* We let callers handle options themselves, so don't include them in the WHERE clause */
+ if($this->iType == FILTER_OPTION_BOOL)
+ return '';
+
$sOp = $this->getOperator();
return "{$this->sColumn} $sOp '{$this->sData}'";
@@ -150,18 +155,18 @@ class FilterSet
public function getWhereClause()
{
- $sFilter = '';
+ $aFilters = array();
for($i = 0; $i < sizeof($this->aFilters); $i++)
{
$oFilter = $this->aFilters[$i];
- $sFilter .= $oFilter->getFilter();
+ $sThisFilter = $oFilter->getExpression();
- if($i < sizeof($this->aFilters) - 1)
- $sFilter .= ' AND ';
+ if($sThisFilter)
+ $aFilters[] = $sThisFilter;
}
- return $sFilter;
+ return implode($aFilters, ' AND ');
}
function getQuery($sTable, $iLimit = 0)
diff --git a/include/db_filter_ui.php b/include/db_filter_ui.php
index ed2f270..a301d5b 100644
--- a/include/db_filter_ui.php
+++ b/include/db_filter_ui.php
@@ -13,6 +13,7 @@ require_once('db_filter.php');
define(FILTER_VALUES_NORMAL, 1);
define(FILTER_VALUES_ENUM, 2);
define(FILTER_VALUES_BOOL, 3);
+define(FILTER_VALUES_OPTION, 4);
/* Info describing an available filter: what column it applies to,
and what comparison options are available */
@@ -158,6 +159,37 @@ class FilterInterface
return $shEditor;
}
+ public function getOptionBoolEditor($iId, Filter $oFilter)
+ {
+ $sColumn = $this->escapeChars($oFilter->getColumn());
+ $oColumn = $this->aFilterInfo[$oFilter->getColumn()];
+ $sId = ($iId == -1) ? '' : $iId;
+
+ $aTypes = $oColumn->getTypes();
+ $iOp = $aTypes[0];
+
+ if($iId == -1)
+ {
+ /* The first entry in the list of choices is the default */
+ $aValues = $oColumn->getValueTypeData();
+ $sData = $aValues[0];
+ } else
+ {
+ $sData = $oFilter->getData();
+ }
+
+ $shRet = "";
+
+ if($sData == 'true')
+ $sChecked = ' checked="checked"';
+ else
+ $sChecked = '';
+
+ $shRet .= "";
+ $shRet .= ' '.$oColumn->getDisplayName();
+
+ return $shRet;
+ }
public function getItemEditor($iId, Filter $oFilter)
{
@@ -295,21 +327,12 @@ class FilterInterface
public function getEditor()
{
- $shEditor = '';
+ $shNewItemsEditor = '';
+ $shCurrentItemsEditor = '';
$aCounts = array();
- $shEditor .= 'Add new filter (You don’t have to fill out all rows.)
';
- foreach($this->aFilterInfo as $oOption)
- {
- $oDummyFilter = new Filter($oOption->getColumn(), 0, '');
- $aTypes = $oOption->getTypes();
-
- $shEditor .= $this->getItemEditor(-1, $oDummyFilter);
- $shEditor .= '
';
- }
-
if(sizeof($this->oFilterSet->getFilters()))
- $shEditor .= '
Active filters
';
+ $shCurrentItemsEditor .= '
Active filters
';
foreach($this->oFilterSet->getFilters() as $oFilter)
{
$sColumn = $oFilter->getColumn();
@@ -317,13 +340,33 @@ class FilterInterface
if(!array_key_exists($sColumn, $aCounts))
$aCounts[$sColumn] = 0;
- $shEditor .= $this->getItemEditor($aCounts[$sColumn], $oFilter);
- $shEditor .= '
';
+ if($oFilter->getOperatorId() == FILTER_OPTION_BOOL)
+ $shCurrentItemsEditor .= $this->getOptionBoolEditor($aCounts[$sColumn], $oFilter);
+ else
+ $shCurrentItemsEditor .= $this->getItemEditor($aCounts[$sColumn], $oFilter);
+ $shCurrentItemsEditor .= '
';
$aCounts[$sColumn]++;
}
- return $shEditor;
+ $shNewItemsEditor .= 'Add new filter (You don’t have to fill out all rows.)
';
+ foreach($this->aFilterInfo as $oOption)
+ {
+ $oDummyFilter = new Filter($oOption->getColumn(), 0, '');
+ $aTypes = $oOption->getTypes();
+
+ if($oOption->getValueType() == FILTER_VALUES_OPTION_BOOL)
+ {
+ if(!array_key_exists($oOption->getColumn(), $aCounts))
+ $shNewItemsEditor .= $this->getOptionBoolEditor(-1, $oDummyFilter);
+ } else
+ {
+ $shNewItemsEditor .= $this->getItemEditor(-1, $oDummyFilter);
+ }
+ $shNewItemsEditor .= '
';
+ }
+
+ return $shNewItemsEditor.$shCurrentItemsEditor;
}
public function getFilterInfo()
@@ -335,11 +378,12 @@ class FilterInterface
public function readInputForColumn($aClean, FilterInfo $oOption)
{
$aReturn = array();
+ $bChangedOption = false;
for($i = 0; array_key_exists('i'.$this->escapeChars($oOption->getColumn())."Op$i", $aClean); $i++)
{
$sColumn = $this->escapeChars($oOption->getColumn());
- $sData = query_escape_string($aClean["s{$sColumn}Data$i"]);
+ $sData = query_escape_string(getInput("s{$sColumn}Data$i", $aClean));
$iOp = $aClean["i{$sColumn}Op$i"];
if(!$iOp)
@@ -347,6 +391,20 @@ class FilterInterface
$oFilter = new Filter($oOption->getColumn(), $iOp, $sData);
+ /* Only show an option as an active filter if it has been changed
+ from the default */
+ if($oOption->getValueType() == FILTER_VALUES_OPTION_BOOL)
+ {
+ /* The default option is the first entry in the list of choices */
+ $aChoices = $oOption->getValueTypeData();
+ $sDefault = $aChoices[0];
+ if(!$sData)
+ $sData = 'false';
+ if($sData == $sDefault)
+ continue;
+ $bChangedOption = true;
+ }
+
$aReturn[] = $oFilter;
}
@@ -357,7 +415,8 @@ class FilterInterface
$sData = $aClean["s{$sColumn}Data"];
$iOp = $aClean["i{$sColumn}Op"];
- if($iOp && $sData)
+
+ if($iOp && $sData && ($oOption->getValueType() != FILTER_VALUES_OPTON_BOOL || !$bChangedOoption))
{
$oFilter = new Filter($oOption->getColumn(), $iOp, $sData);
$aReturn[] = $oFilter;
@@ -393,6 +452,29 @@ class FilterInterface
return $this->oFilterSet->getFilterCount();
}
+ /* Returns an array of options, where the keys are the columns and the members
+ are the settings themselves */
+ public function getOptions()
+ {
+ $aOptions = array();
+ foreach($this->oFilterSet->getFilters() as $oFilter)
+ {
+ if($oFilter->getOperatorId() == FILTER_OPTION_BOOL)
+ $aOptions[$oFilter->getColumn()] = $oFilter->getData();
+ }
+ foreach($this->aFilterInfo as $oFilterInfo)
+ {
+ if($oFilterInfo->getValueType() == FILTER_VALUES_OPTION_BOOL &&
+ !array_key_exists($oFilterInfo->getColumn(), $aOptions))
+ {
+ $aTypes = $oFilterInfo->getTypes();
+ $sDefault = $aTypes[0];
+ $aOptions[$oFilterInfo->getColumn()] = $sDefault;
+ }
+ }
+ return $aOptions;
+ }
+
public function getWhereClause()
{
return $this->oFilterSet->getWhereClause();
diff --git a/include/objectManager.php b/include/objectManager.php
index f565185..0ae6113 100644
--- a/include/objectManager.php
+++ b/include/objectManager.php
@@ -1220,7 +1220,7 @@ class ObjectManager
}
/* Make an objectManager URL based on the object and optional parameters */
- public function makeUrl($sAction = false, $iId = false, $sTitle = false)
+ public function makeUrl($sAction = false, $iId = false, $sTitle = false, $bOmitFilters = false)
{
$sUrl = APPDB_ROOT."objectManager.php?";
@@ -1253,7 +1253,10 @@ class ObjectManager
$sUrl .= "&iPage=".$this->oMultiPage->iPage;
}
- if($this->oFilters)
+ /* Some times it is necessary to omit the filter data, for instance when using
+ makeUrl() to form the action element of a form tag. This is because having
+ filter data present may prevent clearing a filter */
+ if($this->oFilters && !$bOmitFilters)
$sUrl .= $this->oFilters->getUrlData();
if($this->oSortInfo && $this->oSortInfo->sCurrentSort)
@@ -1338,9 +1341,9 @@ class ObjectManager
/* Show filter info */
if($this->oFilters)
{
- echo "