* improved conditions for BaseType to accept conditions in addition to explicit field names

this allows for better flag matching i.e. [(flags & 0x4) = 0]
  furthermore it is now possible to group conditions to a subset with a different link

* hasDiffCategories() -> hasDiffFields(array $fields)
  now returns a bitmask of the array keys what field does diff
This commit is contained in:
Sarjuuk
2013-04-20 15:33:05 +02:00
parent 4d626472b1
commit b6c0fa1b89
4 changed files with 104 additions and 45 deletions

View File

@@ -18,8 +18,10 @@ abstract class BaseType
protected $matchQuery = ''; protected $matchQuery = '';
/* /*
* condition as array [field, value, operator] * condition as array [expression, value, operator]
* field: must match fieldname; 1: select everything * expression: str - must match fieldname;
* int - impl. 1: select everything
* array - another condition array
* value: str - operator defaults to: LIKE %<val>% * value: str - operator defaults to: LIKE %<val>%
* int - operator defaults to: = <val> * int - operator defaults to: = <val>
* array - operator defaults to: IN (<val>) * array - operator defaults to: IN (<val>)
@@ -31,9 +33,20 @@ abstract class BaseType
* defines LIMIT * defines LIMIT
* *
* example: * example:
* array(['id', 45], ['name', 'test', '!'], 'OR', 5) * array(
* ['id', 45],
* ['name', 'test', '!'],
* [
* 'AND',
* ['flags', 0xFF, '&'],
* ['flags2', 0xF, '&'],
* ]
* [['mask', 0x3, '&'], 0]
* 'OR',
* 5
* )
* results in * results in
* WHERE id = 45 OR name NOT LIKE %test% LIMIT 5; * WHERE ((`id` = 45) OR (`name` NOT LIKE "%test%") OR ((`flags` & 255) AND (`flags2` & 15)) OR ((`mask` & 3) = 0)) LIMIT 5
*/ */
public function __construct($conditions = [], $applyFilter = false) public function __construct($conditions = [], $applyFilter = false)
{ {
@@ -56,31 +69,43 @@ abstract class BaseType
return; return;
} }
foreach ($conditions as $c) $resolveCondition = function ($c, $supLink) use (&$resolveCondition)
{ {
$field = ''; $subLink = '';
$op = '';
$val = '';
if (is_array($c)) foreach ($c as $foo)
{ {
if ($c[0] == '1') if ($foo === 'AND')
{ $subLink = ' AND ';
$sql[] = '1'; else if ($foo === 'OR') // nessi-bug: if (0 == 'OR') was true once... w/e
continue; $subLink = ' OR ';
} }
else if ($c[0])
// need to manually set link for subgroups to be recognized as condition set
if ($subLink)
{ {
$field = '`'.implode('`.`', explode('.', Util::sqlEscape($c[0]))).'`'; $sql = [];
foreach ($c as $foo)
if (is_array($foo))
$sql[] = $resolveCondition($foo, $supLink);
return '('.implode($subLink, $sql).')';
} }
else else
continue; {
if ($c[0] == '1')
return '1';
else if (is_array($c[0]))
$field = $resolveCondition($c[0], $supLink);
else if ($c[0])
$field = '`'.implode('`.`', explode('.', Util::sqlEscape($c[0]))).'`';
if (is_array($c[1])) if (is_array($c[1]))
{ {
$val = implode(',', Util::sqlEscape($c[1])); $val = implode(',', Util::sqlEscape($c[1]));
if (!$val) if ($val === '')
continue; return null;
$op = (isset($c[2]) && $c[2] == '!') ? 'NOT IN' : 'IN'; $op = (isset($c[2]) && $c[2] == '!') ? 'NOT IN' : 'IN';
$val = '('.$val.')'; $val = '('.$val.')';
@@ -88,8 +113,8 @@ abstract class BaseType
else if (is_string($c[1])) else if (is_string($c[1]))
{ {
$val = Util::sqlEscape($c[1]); $val = Util::sqlEscape($c[1]);
if (!$val) if ($val === '')
continue; return null;
$op = (isset($c[2]) && $c[2] == '!') ? 'NOT LIKE' : 'LIKE'; $op = (isset($c[2]) && $c[2] == '!') ? 'NOT LIKE' : 'LIKE';
$val = '"%'.$val.'%"'; $val = '"%'.$val.'%"';
@@ -100,20 +125,38 @@ abstract class BaseType
$val = Util::sqlEscape($c[1]); $val = Util::sqlEscape($c[1]);
} }
else // null for example else // null for example
continue; return null;
if (isset($c[2]) && $c[2] != '!') if (isset($c[2]) && $c[2] != '!')
$op = $c[2]; $op = $c[2];
$sql[] = $field.' '.$op.' '.$val; if (isset($field) && isset($op) && isset($val))
} return '('.$field.' '.$op.' '.$val.')';
else if (is_string($c))
$linking = $c == 'AND' ? ' AND ' : ' OR ';
else if (is_int($c))
$limit = $c > 0 ? ' LIMIT '.$c : '';
else else
continue; // ignore other possibilities return null;
} }
};
foreach ($conditions as $i => $c)
{
switch(getType($c))
{
case 'array':
break;
case 'string':
case 'integer':
case 'double':
if (is_string($c))
$linking = $c == 'AND' ? ' AND ' : ' OR ';
else
$limit = $c > 0 ? ' LIMIT '.$c : '';
default:
unset($conditions[$i]);
}
}
foreach ($conditions as $c)
if ($x = $resolveCondition($c, $linking))
$sql[] = $x;
// todo: add strings propperly without them being escaped by simpleDB..? // todo: add strings propperly without them being escaped by simpleDB..?
$this->setupQuery = str_replace('[filter]', $this->filter && $this->filter->buildQuery() ? $this->filter->getQuery().' AND ' : NULL, $this->setupQuery); $this->setupQuery = str_replace('[filter]', $this->filter && $this->filter->buildQuery() ? $this->filter->getQuery().' AND ' : NULL, $this->setupQuery);
@@ -211,18 +254,34 @@ abstract class BaseType
trait listviewHelper trait listviewHelper
{ {
public function hasDiffCategories() public function hasDiffFields($fields)
{ {
if (!is_array($fields))
return 0x0;
$base = [];
$result = 0x0;
$this->reset(); $this->reset();
$curCat = $this->getField('category'); foreach ($fields as $k => $str)
if ($curCat === null) $base[$str] = $this->getField($str);
return false;
while ($this->iterate()) while ($this->iterate())
if ($curCat != $this->getField('category')) {
return true; foreach ($fields as $k => $str)
{
if ($base[$str] != $this->getField($str))
{
$result |= 1 << $k;
unset($fields[$k]);
}
}
return false; if (empty($fields)) // all fields diff .. return early
return $result;
}
return $result;
} }
public function hasAnySource() public function hasAnySource()
@@ -304,7 +363,7 @@ class Lang
public static function getStances($stanceMask) public static function getStances($stanceMask)
{ {
$stanceMask &= 0x1F84F213E; // clamp to available stances/forms.. $stanceMask &= 0xFC27909F; // clamp to available stances/forms..
$tmp = []; $tmp = [];
$i = 1; $i = 1;

View File

@@ -99,7 +99,7 @@ if (!$smarty->loadCache($cacheKey, $pageData))
$pageData['params'] = ['tabs' => false]; $pageData['params'] = ['tabs' => false];
// if we are have different cats display field // if we are have different cats display field
if ($acvList->hasDiffCategories()) if ($acvList->hasDiffFields(['category']))
$pageData['params']['visibleCols'] = "$['category']"; $pageData['params']['visibleCols'] = "$['category']";
// create note if search limit was exceeded // create note if search limit was exceeded

View File

@@ -31,7 +31,7 @@ if (!$smarty->loadCache($cacheKey, $pageData))
) )
); );
if (!$pets->hasDiffCategories()) if (($mask = $pets->hasDiffFields(['type'])) == 0x0)
$pageData['params']['hiddenCols'] = "$['type']"; $pageData['params']['hiddenCols'] = "$['type']";
$pets->reset(); $pets->reset();

View File

@@ -30,7 +30,7 @@ if (!$smarty->loadCache($cacheKey, $pageData))
) )
); );
if ($titles->hasDiffCategories()) if ($titles->hasDiffFields(['category']))
$pageData['params']['visibleCols'] = "$['category']"; $pageData['params']['visibleCols'] = "$['category']";
if (!$titles->hasAnySource()) if (!$titles->hasAnySource())