Advanced Search: 'between' for numeric criteria

SVN:b1162[5487]
This commit is contained in:
Eric Espié
2018-03-21 13:12:13 +00:00
parent 114a340527
commit b05b41c7cc
4 changed files with 127 additions and 12 deletions

View File

@@ -25,6 +25,7 @@ namespace Combodo\iTop\Application\Search\CriterionConversion;
use AttributeDateTime;
use AttributeDefinition;
use Combodo\iTop\Application\Search\AjaxSearchException;
use Combodo\iTop\Application\Search\CriterionConversionAbstract;
use Combodo\iTop\Application\Search\SearchForm;
use DateInterval;
@@ -56,6 +57,7 @@ class CriterionToOQL extends CriterionConversionAbstract
self::OP_NOT_EMPTY => 'NotEmptyToOql',
self::OP_BETWEEN_DAYS => 'BetweenDaysToOql',
self::OP_BETWEEN_HOURS => 'BetweenHoursToOql',
self::OP_BETWEEN => 'BetweenToOql',
self::OP_IN => 'InToOql',
self::OP_ALL => 'AllToOql',
);
@@ -126,6 +128,7 @@ class CriterionToOQL extends CriterionConversionAbstract
{
return "ISNULL({$sRef})";
}
return "({$sRef} = '')";
}
@@ -165,15 +168,18 @@ class CriterionToOQL extends CriterionConversionAbstract
return "1";
}
// more selected values than remaining so use NOT IN
else if (count($aValues) > (count($aAllowedValues) / 2))
else
{
foreach($aValues as $aValue)
if (count($aValues) > (count($aAllowedValues) / 2))
{
unset($aAllowedValues[$aValue['value']]);
}
$sInList = implode("','", array_keys($aAllowedValues));
foreach($aValues as $aValue)
{
unset($aAllowedValues[$aValue['value']]);
}
$sInList = implode("','", array_keys($aAllowedValues));
return "({$sRef} NOT IN ('$sInList'))";
return "({$sRef} NOT IN ('$sInList'))";
}
}
}
}
@@ -283,6 +289,65 @@ class CriterionToOQL extends CriterionConversionAbstract
return $sOQL;
}
/**
* @param $sRef
* @param $aCriteria
*
* @return string
* @throws \Combodo\iTop\Application\Search\AjaxSearchException
*/
protected static function BetweenToOql($sRef, $aCriteria)
{
$aOQL = array();
$aValues = self::GetValues($aCriteria);
if (count($aValues) != 2)
{
return "1";
}
if (isset($aValues[0]['value']))
{
$sStartNum = trim($aValues[0]['value']);
if (is_numeric($sStartNum))
{
$aOQL[] = "({$sRef} >= '$sStartNum')";
}
else
{
if (!empty($sStartNum))
{
throw new AjaxSearchException("'$sStartNum' is not a numeric value", 400);
}
}
}
if (isset($aValues[1]['value']))
{
$sEndNum = trim($aValues[1]['value']);
if (is_numeric($sEndNum))
{
$aOQL[] = "({$sRef} <= '$sEndNum')";
}
else
{
if (!empty($sEndNum))
{
throw new AjaxSearchException("'$sEndNum' is not a numeric value", 400);
}
}
}
$sOQL = implode(' AND ', $aOQL);
if (empty($sOQL))
{
$sOQL = "1";
}
return $sOQL;
}
protected static function AllToOql($sRef, $aCriteria)
{

View File

@@ -108,6 +108,7 @@ class CriterionToSearchForm extends CriterionConversionAbstract
$aMergeFctByWidget = array(
AttributeDefinition::SEARCH_WIDGET_TYPE_DATE => 'MergeDate',
AttributeDefinition::SEARCH_WIDGET_TYPE_DATE_TIME => 'MergeDateTime',
AttributeDefinition::SEARCH_WIDGET_TYPE_NUMERIC => 'MergeNumeric',
);
$aPrevCriterion = null;
@@ -151,7 +152,7 @@ class CriterionToSearchForm extends CriterionConversionAbstract
* @param $aCurrCriterion
* @param $aMergedCriterion
*
* @return null
* @return Current criteria or null if merged
* @throws \Exception
*/
protected static function MergeDate($aPrevCriterion, $aCurrCriterion, &$aMergedCriterion)
@@ -199,6 +200,49 @@ class CriterionToSearchForm extends CriterionConversionAbstract
return null;
}
/**
* @param $aPrevCriterion
* @param $aCurrCriterion
* @param $aMergedCriterion
*
* @return Current criteria or null if merged
* @throws \Exception
*/
protected static function MergeNumeric($aPrevCriterion, $aCurrCriterion, &$aMergedCriterion)
{
$sPrevOperator = $aPrevCriterion['operator'];
$sCurrOperator = $aCurrCriterion['operator'];
if (($sPrevOperator != '<=') || ($sCurrOperator != '>='))
{
$aMergedCriterion[] = $aPrevCriterion;
return $aCurrCriterion;
}
// Merge into 'between' operation.
$sLastNum = $aPrevCriterion['values'][0]['value'];
$sFirstNum = $aCurrCriterion['values'][0]['value'];
$aCurrCriterion['values'] = array();
$aCurrCriterion['values'][] = array('value' => $sFirstNum, 'label' => $sFirstNum);
$aCurrCriterion['values'][] = array('value' => $sLastNum, 'label' => $sLastNum);
$aCurrCriterion['oql'] = "({$aPrevCriterion['oql']} AND {$aCurrCriterion['oql']})";
$aCurrCriterion['label'] = $aPrevCriterion['label'].' '.Dict::S('Expression:Operator:AND', 'AND').' '.$aCurrCriterion['label'];
$aCurrCriterion['operator'] = 'between';
$aMergedCriterion[] = $aCurrCriterion;
return null;
}
/**
* @param $aPrevCriterion
* @param $aCurrCriterion
* @param $aMergedCriterion
*
* @return Current criteria or null if merged
* @throws \Exception
*/
protected static function MergeDateTime($aPrevCriterion, $aCurrCriterion, &$aMergedCriterion)
{
$sPrevOperator = $aPrevCriterion['operator'];

View File

@@ -34,6 +34,7 @@ abstract class CriterionConversionAbstract
const OP_IN = 'IN';
const OP_BETWEEN_DAYS = 'between_days';
const OP_BETWEEN_HOURS = 'between_hours';
const OP_BETWEEN = 'between';
const OP_ALL = 'all';
}

View File

@@ -312,12 +312,17 @@ class CriterionConversionTest extends ItopDataTestCase
$aNewCriterion = array();
foreach($aAndCriterion as $aCriteria)
{
if (($aCriteria['widget'] == \AttributeDefinition::SEARCH_WIDGET_TYPE_STRING)
|| ($aCriteria['widget'] == \AttributeDefinition::SEARCH_WIDGET_TYPE_DATE_TIME)
|| ($aCriteria['widget'] == \AttributeDefinition::SEARCH_WIDGET_TYPE_ENUM))
if ($aCriteria['widget'] != \AttributeDefinition::SEARCH_WIDGET_TYPE_RAW)
{
unset($aCriteria['oql']);
$aField = $aFields['zlist'][$aCriteria['ref']];
if (isset($aFields['zlist'][$aCriteria['ref']]))
{
$aField = $aFields['zlist'][$aCriteria['ref']];
}
else
{
$aField = $aFields['others'][$aCriteria['ref']];
}
$aCriteria['code'] = $aField['code'];
$aCriteria['class'] = $aField['class'];
}
@@ -353,7 +358,7 @@ class CriterionConversionTest extends ItopDataTestCase
'Date between 3' => array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 00:00:00' >= start_date"),
'Date between 4' => array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 01:00:00' > start_date"),
'Date between 5' => array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-02 00:00:00' > start_date"),
'Num between 1' => array('OQL' => "SELECT Server WHERE nb_u >= 0 AND 1 >= nb_u"),
);
}
}