Advanced Search: External keys to hierarchical class selects sub-classes as in previous version

SVN:trunk[5675]
This commit is contained in:
Eric Espié
2018-04-16 16:35:20 +00:00
parent bd8e44f835
commit c485286114
15 changed files with 232 additions and 86 deletions

View File

@@ -27,16 +27,19 @@ use AttributeDate;
use AttributeDateTime;
use AttributeDefinition;
use AttributeEnum;
use AttributeExternalKey;
use Combodo\iTop\Application\Search\AjaxSearchException;
use Combodo\iTop\Application\Search\CriterionConversionAbstract;
use Combodo\iTop\Application\Search\SearchForm;
use DBObjectSearch;
use Exception;
use Expression;
use MetaModel;
class CriterionToOQL extends CriterionConversionAbstract
{
public static function Convert($aCriteria)
public static function Convert($oSearch, $aCriteria)
{
if (!empty($aCriteria['oql']))
{
@@ -44,6 +47,7 @@ class CriterionToOQL extends CriterionConversionAbstract
}
$aRef = explode('.', $aCriteria['ref']);
$aCriteria['code'] = $aRef[1];
for($i = 0; $i < count($aRef); $i++)
{
$aRef[$i] = '`'.$aRef[$i].'`';
@@ -77,7 +81,7 @@ class CriterionToOQL extends CriterionConversionAbstract
{
$sFct = $aMappedOperators[$sOperator];
return self::$sFct($sRef, $aCriteria);
return self::$sFct($oSearch, $sRef, $aCriteria);
}
$sValue = self::GetValue(self::GetValues($aCriteria), 0);
@@ -109,7 +113,7 @@ class CriterionToOQL extends CriterionConversionAbstract
return $aValues[$iIndex]['value'];
}
protected static function ContainsToOql($sRef, $aCriteria)
protected static function ContainsToOql($oSearch, $sRef, $aCriteria)
{
$aValues = self::GetValues($aCriteria);
$sValue = self::GetValue($aValues, 0);
@@ -119,7 +123,7 @@ class CriterionToOQL extends CriterionConversionAbstract
return "({$sRef} LIKE '%{$sValue}%')";
}
protected static function StartsWithToOql($sRef, $aCriteria)
protected static function StartsWithToOql($oSearch, $sRef, $aCriteria)
{
$aValues = self::GetValues($aCriteria);
$sValue = self::GetValue($aValues, 0);
@@ -129,7 +133,7 @@ class CriterionToOQL extends CriterionConversionAbstract
return "({$sRef} LIKE '{$sValue}%')";
}
protected static function EndsWithToOql($sRef, $aCriteria)
protected static function EndsWithToOql($oSearch, $sRef, $aCriteria)
{
$aValues = self::GetValues($aCriteria);
$sValue = self::GetValue($aValues, 0);
@@ -139,7 +143,7 @@ class CriterionToOQL extends CriterionConversionAbstract
return "({$sRef} LIKE '%{$sValue}')";
}
protected static function EqualsToOql($sRef, $aCriteria)
protected static function EqualsToOql($oSearch, $sRef, $aCriteria)
{
$aValues = self::GetValues($aCriteria);
$sValue = self::GetValue($aValues, 0);
@@ -149,7 +153,7 @@ class CriterionToOQL extends CriterionConversionAbstract
return "({$sRef} = '{$sValue}')";
}
protected static function RegexpToOql($sRef, $aCriteria)
protected static function RegexpToOql($oSearch, $sRef, $aCriteria)
{
$aValues = self::GetValues($aCriteria);
$sValue = self::GetValue($aValues, 0);
@@ -159,7 +163,7 @@ class CriterionToOQL extends CriterionConversionAbstract
return "({$sRef} REGEXP '{$sValue}')";
}
protected static function EmptyToOql($sRef, $aCriteria)
protected static function EmptyToOql($oSearch, $sRef, $aCriteria)
{
if (isset($aCriteria['widget']))
{
@@ -176,7 +180,7 @@ class CriterionToOQL extends CriterionConversionAbstract
return "({$sRef} = '')";
}
protected static function NotEmptyToOql($sRef, $aCriteria)
protected static function NotEmptyToOql($oSearch, $sRef, $aCriteria)
{
if (isset($aCriteria['widget']))
{
@@ -193,7 +197,14 @@ class CriterionToOQL extends CriterionConversionAbstract
return "({$sRef} != '')";
}
protected static function InToOql($sRef, $aCriteria)
/**
* @param DBObjectSearch $oSearch
* @param $sRef
* @param $aCriteria
*
* @return mixed|string
*/
protected static function InToOql($oSearch, $sRef, $aCriteria)
{
$sAttCode = $aCriteria['code'];
$sClass = $aCriteria['class'];
@@ -255,7 +266,7 @@ class CriterionToOQL extends CriterionConversionAbstract
}
}
}
} catch (\CoreException $e)
} catch (Exception $e)
{
}
@@ -271,28 +282,69 @@ class CriterionToOQL extends CriterionConversionAbstract
$sFilterOnUndefined = "ISNULL({$sRef})";
if (count($aValues) === 0)
{
return $sFilterOnUndefined;
$sCondition = $sFilterOnUndefined;
}
if (count($aInValues) == 1)
elseif (count($aInValues) == 1)
{
// Add 'AND 1' to group the 'OR' inside an AND list for OQL parsing
return "((({$sRef} = '$sInList') OR {$sFilterOnUndefined}) AND 1)";
$sCondition = "((({$sRef} = '$sInList') OR {$sFilterOnUndefined}) AND 1)";
}
else
{
// Add 'AND 1' to group the 'OR' inside an AND list for OQL parsing
$sCondition = "(({$sRef} IN ('$sInList') OR {$sFilterOnUndefined}) AND 1)";
}
}
elseif (count($aInValues) == 1)
{
$sCondition = "({$sRef} = '$sInList')";
}
else
{
$sCondition = "({$sRef} IN ('$sInList'))";
}
// Hierarchical keys
if (isset($oAttDef) && $oAttDef->IsExternalKey() && (!isset($aCriteria['is_hierarchical']) || ($aCriteria['is_hierarchical'] !== false)))
{
if ($oAttDef instanceof AttributeExternalKey)
{
$sTargetClass = $oAttDef->GetTargetClass();
}
else
{
/** @var AttributeExternalKey $oFinalAttDef */
$oFinalAttDef = $oAttDef->GetFinalAttDef();
$sTargetClass = $oFinalAttDef->GetTargetClass();
}
// Add 'AND 1' to group the 'OR' inside an AND list for OQL parsing
return "(({$sRef} IN ('$sInList') OR {$sFilterOnUndefined}) AND 1)";
try
{
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sTargetClass);
if ($sHierarchicalKeyCode !== false)
{
$oFilter = new DBObjectSearch($sTargetClass);
$sFilterAlias = $oFilter->GetClassAlias();
$sCondition = str_replace("$sRef", $sFilterAlias.'.id', $sCondition);
$oCondition = Expression::FromOQL($sCondition);
$oFilter->AddConditionExpression($oCondition);
$oHKFilter = new DBObjectSearch($sTargetClass);
$oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
// Use the 'below' operator by default
$oSearch->AddCondition_PointingTo($oHKFilter, $sAttCode);
$sCondition = '1';
}
} catch (Exception $e)
{
}
}
if (count($aInValues) == 1)
{
return "({$sRef} = '$sInList')";
}
return "({$sRef} IN ('$sInList'))";
return $sCondition;
}
protected static function BetweenDatesToOql($sRef, $aCriteria)
protected static function BetweenDatesToOql($oSearch, $sRef, $aCriteria)
{
$aOQL = array();
@@ -352,13 +404,14 @@ class CriterionToOQL extends CriterionConversionAbstract
}
/**
* @param DBObjectSearch $oSearch
* @param $sRef
* @param $aCriteria
*
* @return string
* @throws \Combodo\iTop\Application\Search\AjaxSearchException
*/
protected static function BetweenToOql($sRef, $aCriteria)
protected static function BetweenToOql($oSearch, $sRef, $aCriteria)
{
$aOQL = array();
@@ -411,7 +464,7 @@ class CriterionToOQL extends CriterionConversionAbstract
}
protected static function AllToOql($sRef, $aCriteria)
protected static function AllToOql($oSearch, $sRef, $aCriteria)
{
return "1";
}

View File

@@ -240,7 +240,7 @@ class CriterionToSearchForm extends CriterionConversionAbstract
* @param $aCurrCriterion
* @param $aMergedCriterion
*
* @return Current criteria or null if merged
* @return array Current criteria or null if merged
* @throws \Exception
*/
protected static function MergeDate($aPrevCriterion, $aCurrCriterion, &$aMergedCriterion)
@@ -295,7 +295,7 @@ class CriterionToSearchForm extends CriterionConversionAbstract
* @param $aCurrCriterion
* @param $aMergedCriterion
*
* @return Current criteria or null if merged
* @return array Current criteria or null if merged
* @throws \Exception
*/
protected static function MergeDateTime($aPrevCriterion, $aCurrCriterion, &$aMergedCriterion)
@@ -352,7 +352,7 @@ class CriterionToSearchForm extends CriterionConversionAbstract
* @param $aCurrCriterion
* @param $aMergedCriterion
*
* @return Current criteria or null if merged
* @return array Current criteria or null if merged
* @throws \Exception
*/
protected static function MergeNumeric($aPrevCriterion, $aCurrCriterion, &$aMergedCriterion)
@@ -514,16 +514,27 @@ class CriterionToSearchForm extends CriterionConversionAbstract
$oDate = new DateTime($sDate);
$sFirstDateValue = $oDate->format(AttributeDateTime::GetSQLFormat());
$sFirstDateLabel = AttributeDateTime::GetFormat()->Format($sFirstDateValue);
$aCriteria['values'][0] = array('value' => $sFirstDateValue, 'label' => "$sFirstDateLabel");
try
{
$sFirstDateLabel = AttributeDateTime::GetFormat()->Format($sFirstDateValue);
$aCriteria['values'][0] = array('value' => $sFirstDateValue, 'label' => "$sFirstDateLabel");
}
catch (Exception $e)
{
}
$oDate->add(DateInterval::createFromDateString('1 day'));
$oDate->sub(DateInterval::createFromDateString('1 second'));
$sLastDateValue = $oDate->format(AttributeDateTime::GetSQLFormat());
$sLastDateLabel = AttributeDateTime::GetFormat()->Format($sLastDateValue);
$aCriteria['values'][1] = array('value' => $sLastDateValue, 'label' => "$sLastDateLabel");
try
{
$sLastDateLabel = AttributeDateTime::GetFormat()->Format($sLastDateValue);
$aCriteria['values'][1] = array('value' => $sLastDateValue, 'label' => "$sLastDateLabel");
}
catch (Exception $e)
{
}
}
}
break;
@@ -634,6 +645,7 @@ class CriterionToSearchForm extends CriterionConversionAbstract
case '=':
// Same as IN
$aCriteria['operator'] = CriterionConversionAbstract::OP_IN;
unset($aCriteria['oql']);
break;
case 'IN':
// Nothing special to do

View File

@@ -47,22 +47,22 @@ class CriterionParser
*/
public static function Parse($sBaseOql, $aCriterion, $sHiddenCriteria = null)
{
$aExpression = array();
$aOr = $aCriterion['or'];
foreach($aOr as $aAndList)
{
$sExpression = self::ParseAndList($aAndList['and']);
if (!empty($sExpression))
{
$aExpression[] = $sExpression;
}
}
try
{
$oSearch = DBObjectSearch::FromOQL($sBaseOql);
$aExpression = array();
$aOr = $aCriterion['or'];
foreach($aOr as $aAndList)
{
$sExpression = self::ParseAndList($oSearch, $aAndList['and']);
if (!empty($sExpression))
{
$aExpression[] = $sExpression;
}
}
if (!empty($sHiddenCriteria))
{
$oHiddenCriteriaExpression = Expression::FromOQL($sHiddenCriteria);
@@ -85,13 +85,13 @@ class CriterionParser
return null;
}
private static function ParseAndList($aAnd)
private static function ParseAndList($oSearch, $aAnd)
{
$aExpression = array();
foreach($aAnd as $aCriteria)
{
$sExpression = CriterionToOQL::Convert($aCriteria);
$sExpression = CriterionToOQL::Convert($oSearch, $aCriteria);
if ($sExpression !== '1')
{
$aExpression[] = $sExpression;

View File

@@ -26,6 +26,8 @@ namespace Combodo\iTop\Application\Search;
use ApplicationContext;
use AttributeDefinition;
use AttributeExternalField;
use AttributeFriendlyName;
use AttributeSubItem;
use CMDBObjectSet;
use Combodo\iTop\Application\Search\CriterionConversion\CriterionToSearchForm;
use CoreException;
@@ -39,7 +41,6 @@ use IssueLog;
use MetaModel;
use TrueExpression;
use utils;
use ValueSetObjects;
use WebPage;
class SearchForm
@@ -395,7 +396,7 @@ class SearchForm
}
/**
* @param $oAttrDef
* @param \AttributeDefinition $oAttrDef
*
* @return array
*/
@@ -409,6 +410,7 @@ class SearchForm
}
else
{
/** @var \AttributeExternalKey $oAttrDef */
$sTargetClass = $oAttrDef->GetTargetClass();
}
try
@@ -441,6 +443,7 @@ class SearchForm
{
if (method_exists($oAttrDef, 'GetAllowedValuesAsObjectSet'))
{
/** @var DBObjectSet $oSet */
$oSet = $oAttrDef->GetAllowedValuesAsObjectSet();
$iCount = $oSet->Count();
if ($iCount > MetaModel::GetConfig()->Get('max_combo_length'))
@@ -489,6 +492,7 @@ class SearchForm
$aAndExpressions = Expression::Split($oORSubExpr, 'AND');
foreach($aAndExpressions as $oAndSubExpr)
{
/** @var Expression $oAndSubExpr */
if (($oAndSubExpr instanceof TrueExpression) || ($oAndSubExpr->Render() == 1))
{
continue;
@@ -535,7 +539,7 @@ class SearchForm
* @param $sClass
* @param $sClassAlias
* @param $sAttCode
* @param $oAttDef
* @param AttributeDefinition $oAttDef
* @param $aFields
* @param bool $bHasIndex
*
@@ -619,7 +623,7 @@ class SearchForm
}
/**
* @param $oSearch
* @param DBObjectSearch $oSearch
* @return array
*/
protected function GetDefaultCriterion($oSearch)
@@ -653,5 +657,4 @@ class SearchForm
return $aOrCriterion;
}
}