mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Advanced Search: External keys to hierarchical class selects sub-classes as in previous version
SVN:trunk[5675]
This commit is contained in:
@@ -238,8 +238,11 @@ abstract class AttributeDefinition
|
||||
|
||||
/**
|
||||
* Check the validity of the given value
|
||||
*
|
||||
* @param DBObject $oHostObject
|
||||
* @param string An error if any, null otherwise
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckValue(DBObject $oHostObject, $value)
|
||||
{
|
||||
@@ -252,7 +255,8 @@ abstract class AttributeDefinition
|
||||
{
|
||||
return "";
|
||||
// e.g: return array("Site", "infrid", "name");
|
||||
}
|
||||
}
|
||||
|
||||
public function GetFinalAttDef()
|
||||
{
|
||||
return $this;
|
||||
|
||||
@@ -1005,7 +1005,7 @@ class DBObjectSearch extends DBSearch
|
||||
|
||||
public function GetCriteria() {return $this->m_oSearchCondition;}
|
||||
public function GetCriteria_FullText() {throw new Exception("Removed GetCriteria_FullText");}
|
||||
protected function GetCriteria_PointingTo($sKeyAttCode = "")
|
||||
public function GetCriteria_PointingTo($sKeyAttCode = "")
|
||||
{
|
||||
if (empty($sKeyAttCode))
|
||||
{
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
* echo "Ok, '$sOQL' is a valid query";
|
||||
* }
|
||||
*/
|
||||
if (!class_exists('CoreException', false))
|
||||
{
|
||||
class CoreException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
//if (!class_exists('CoreException', false))
|
||||
//{
|
||||
// class CoreException extends Exception
|
||||
// {
|
||||
//
|
||||
// }
|
||||
//}
|
||||
|
||||
require_once(__DIR__.'/expression.class.inc.php');
|
||||
require_once(__DIR__.'/oqlquery.class.inc.php');
|
||||
|
||||
@@ -530,11 +530,14 @@ class BinaryExpression extends Expression
|
||||
return parent::GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef);
|
||||
}
|
||||
|
||||
$aCriteriaLeft = $oLeftExpr->GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef);
|
||||
$aCriteriaRight = $oRightExpr->GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef);
|
||||
|
||||
if ($bReverseOperator)
|
||||
{
|
||||
$aCriteriaRight = $oRightExpr->GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef);
|
||||
// $oAttDef can be different now
|
||||
$oAttDef = $oRightExpr->GetAttDef($oSearch->GetJoinedClasses());
|
||||
$aCriteriaLeft = $oLeftExpr->GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef);
|
||||
|
||||
$aCriteria = array_merge($aCriteriaRight, $aCriteriaLeft);
|
||||
// switch left and right expressions so reverse the operator
|
||||
// Note that the operation is the same so < becomes > and not >=
|
||||
@@ -559,6 +562,11 @@ class BinaryExpression extends Expression
|
||||
}
|
||||
else
|
||||
{
|
||||
$aCriteriaLeft = $oLeftExpr->GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef);
|
||||
// $oAttDef can be different now
|
||||
$oAttDef = $oLeftExpr->GetAttDef($oSearch->GetJoinedClasses());
|
||||
$aCriteriaRight = $oRightExpr->GetCriterion($oSearch, $aArgs, $bRetrofitParams, $oAttDef);
|
||||
|
||||
$aCriteria = array_merge($aCriteriaLeft, $aCriteriaRight);
|
||||
$aCriteria['operator'] = $this->GetOperator();
|
||||
}
|
||||
@@ -1056,9 +1064,28 @@ class FieldExpression extends UnaryExpression
|
||||
}
|
||||
}
|
||||
|
||||
private function GetJoinedFilters($oSearch, $iOperatorCodeTarget)
|
||||
{
|
||||
$aFilters = array();
|
||||
$aPointingToByKey = $oSearch->GetCriteria_PointingTo();
|
||||
foreach ($aPointingToByKey as $sExtKey => $aPointingTo)
|
||||
{
|
||||
foreach($aPointingTo as $iOperatorCode => $aFilter)
|
||||
{
|
||||
if ($iOperatorCode == $iOperatorCodeTarget)
|
||||
{
|
||||
foreach($aFilter as $oExtFilter)
|
||||
{
|
||||
$aFilters[$sExtKey] = $oExtFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $oSearch
|
||||
* @param DBObjectSearch $oSearch
|
||||
* @param null $aArgs
|
||||
* @param bool $bRetrofitParams
|
||||
* @param AttributeDefinition $oAttDef
|
||||
@@ -1067,6 +1094,38 @@ class FieldExpression extends UnaryExpression
|
||||
*/
|
||||
public function GetCriterion($oSearch, &$aArgs = null, $bRetrofitParams = false, $oAttDef = null)
|
||||
{
|
||||
$aCriteria = array();
|
||||
$aCriteria['is_hierarchical'] = false;
|
||||
// Replace BELOW joins by the corresponding external key for the search
|
||||
// Try to detect hierarchical links
|
||||
if ($this->m_sName == 'id')
|
||||
{
|
||||
if (method_exists($oSearch, 'GetCriteria_PointingTo'))
|
||||
{
|
||||
$aFilters = $this->GetJoinedFilters($oSearch, TREE_OPERATOR_EQUALS);
|
||||
if (!empty($aFilters))
|
||||
{
|
||||
foreach($aFilters as $sExtKey => $oFilter)
|
||||
{
|
||||
$aSubFilters = $this->GetJoinedFilters($oFilter, TREE_OPERATOR_BELOW);
|
||||
foreach($aSubFilters as $oSubFilter)
|
||||
{
|
||||
/** @var \DBObjectSearch $oSubFilter */
|
||||
$sClassAlias = $oSubFilter->GetClassAlias();
|
||||
if ($sClassAlias == $this->m_sParent)
|
||||
{
|
||||
// Hierarchical link detected
|
||||
// replace current field with the corresponding external key
|
||||
$this->m_sName = $sExtKey;
|
||||
$this->m_sParent = $oSearch->GetClassAlias();
|
||||
$aCriteria['is_hierarchical'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (method_exists($oSearch, 'GetJoinedClasses'))
|
||||
{
|
||||
$oAttDef = $this->GetAttDef($oSearch->GetJoinedClasses());
|
||||
@@ -1096,11 +1155,12 @@ class FieldExpression extends UnaryExpression
|
||||
{
|
||||
$sSearchType = AttributeDefinition::SEARCH_WIDGET_TYPE;
|
||||
}
|
||||
return array(
|
||||
'widget' => $sSearchType,
|
||||
'ref' => $this->GetParent().'.'.$this->GetName(),
|
||||
'class_alias' => $this->GetParent(),
|
||||
);
|
||||
|
||||
$aCriteria['widget'] = $sSearchType;
|
||||
$aCriteria['ref'] = $this->GetParent().'.'.$this->GetName();
|
||||
$aCriteria['class_alias'] = $this->GetParent();
|
||||
|
||||
return $aCriteria;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -35,7 +35,8 @@ class ItopTestCase extends TestCase
|
||||
{
|
||||
@include_once '../approot.inc.php';
|
||||
@include_once '../../approot.inc.php';
|
||||
@include_once '../../../approot.inc.php';
|
||||
@include_once '../../../approot.inc.php';
|
||||
@include_once '../../../../approot.inc.php';
|
||||
|
||||
$this->debug("\n----------\n---------- ".$this->getName()."\n----------\n");
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ use Combodo\iTop\Application\Search\CriterionConversion\CriterionToSearchForm;
|
||||
use Combodo\iTop\Application\Search\CriterionParser;
|
||||
use Combodo\iTop\Application\Search\SearchForm;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBObjectSearch;
|
||||
use DBSearch;
|
||||
|
||||
class CriterionConversionTest extends ItopDataTestCase
|
||||
{
|
||||
@@ -49,13 +51,17 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
/**
|
||||
* @dataProvider ToOqlProvider
|
||||
*
|
||||
* @param $sClass
|
||||
* @param $sJSONCriterion
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testToOql($sJSONCriterion, $sExpectedOQL)
|
||||
public function testToOql($sClass, $sJSONCriterion, $sExpectedOQL)
|
||||
{
|
||||
$oSearch = new DBObjectSearch($sClass);
|
||||
$sOql = CriterionToOQL::Convert(
|
||||
json_decode($sJSONCriterion, true)
|
||||
$oSearch, json_decode($sJSONCriterion, true)
|
||||
);
|
||||
|
||||
$this->debug($sOql);
|
||||
@@ -66,6 +72,7 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
{
|
||||
return array(
|
||||
'>' => array(
|
||||
'UserRequest',
|
||||
'{
|
||||
"ref": "UserRequest.start_date",
|
||||
"values": [
|
||||
@@ -80,6 +87,7 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
"(`UserRequest`.`start_date` > '2017-01-01')"
|
||||
),
|
||||
'contains' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
@@ -94,6 +102,7 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
"(`Contact`.`name` LIKE '%toto%')"
|
||||
),
|
||||
'starts_with' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
@@ -108,6 +117,7 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
"(`Contact`.`name` LIKE 'toto%')"
|
||||
),
|
||||
'ends_with' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
@@ -122,6 +132,7 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
"(`Contact`.`name` LIKE '%toto')"
|
||||
),
|
||||
'empty' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
@@ -136,6 +147,7 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
"(`Contact`.`name` = '')"
|
||||
),
|
||||
'not_empty' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
@@ -163,7 +175,8 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
function testToSearchForm($aCriterion, $sExpectedOperator)
|
||||
{
|
||||
$oSearchForm = new SearchForm();
|
||||
$oSearch = \DBSearch::FromOQL("SELECT Contact");
|
||||
/** @var \DBObjectSearch $oSearch */
|
||||
$oSearch = DBSearch::FromOQL("SELECT Contact");
|
||||
$aFields = $oSearchForm->GetFields(new \DBObjectSet($oSearch));
|
||||
$aRes = CriterionToSearchForm::Convert($aCriterion, $aFields, $oSearch->GetJoinedClasses());
|
||||
$this->debug($aRes);
|
||||
@@ -530,8 +543,8 @@ class CriterionConversionTest extends ItopDataTestCase
|
||||
),
|
||||
'Hierarchical below' => array(
|
||||
'OQL' => "SELECT Person AS P JOIN Organization AS Node ON P.org_id = Node.id JOIN Organization AS Root ON Node.parent_id BELOW Root.id WHERE Root.id=1",
|
||||
'ExpectedOQL' => "SELECT `P` FROM Person AS `P` JOIN Organization AS `Node` ON `P`.org_id = `Node`.id JOIN Organization AS `Root` ON `Node`.parent_id BELOW `Root`.id WHERE (`Root`.`id` = 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
'ExpectedOQL' => "SELECT `P` FROM Person AS `P` JOIN Organization AS `Node` ON `P`.org_id = `Node`.id JOIN Organization AS `Root` ON `Node`.parent_id BELOW `Root`.id WHERE (`Root`.`id` = '1')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key')),
|
||||
),
|
||||
'IP range' => array(
|
||||
'OQL' => "SELECT DatacenterDevice AS dev WHERE INET_ATON(dev.managementip) > INET_ATON('10.22.32.224') AND INET_ATON(dev.managementip) < INET_ATON('10.22.32.255')",
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Combodo\iTop\Test\UnitTest\Application\Search;
|
||||
|
||||
use Combodo\iTop\Application\Search\SearchForm;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBObjectSearch;
|
||||
use Exception;
|
||||
|
||||
class SearchFormTest extends ItopDataTestCase
|
||||
@@ -43,27 +44,25 @@ class SearchFormTest extends ItopDataTestCase
|
||||
* @dataProvider GetFieldsProvider
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function testGetFields($sOQL, $iNum, $sList)
|
||||
public function testGetFields($sOQL)
|
||||
{
|
||||
$oSearchForm = new SearchForm();
|
||||
$oSearch = \DBSearch::FromOQL($sOQL);
|
||||
$aFields = $oSearchForm->GetFields(new \DBObjectSet($oSearch));
|
||||
$this->debug($sOQL);
|
||||
$this->debug(json_encode($aFields, JSON_PRETTY_PRINT));
|
||||
$this->assertCount($iNum, $aFields[$sList]);
|
||||
|
||||
$this->assertTrue(count($aFields['zlist']) > 0);
|
||||
$this->assertTrue(count($aFields['others']) > 0);
|
||||
}
|
||||
|
||||
public function GetFieldsProvider()
|
||||
{
|
||||
return array(
|
||||
array("SELECT Contact", 8, 'zlist'),
|
||||
array("SELECT Contact AS C WHERE C.status = 'active'", 3, 'others'),
|
||||
array("SELECT Person", 12, 'zlist'),
|
||||
array("SELECT Contact"),
|
||||
array("SELECT Contact AS C WHERE C.status = 'active'"),
|
||||
array("SELECT Person"),
|
||||
array(
|
||||
"SELECT Person AS p JOIN UserRequest AS u ON u.agent_id = p.id WHERE u.status != 'closed'",
|
||||
12,
|
||||
'zlist'
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -83,6 +82,7 @@ class SearchFormTest extends ItopDataTestCase
|
||||
{
|
||||
$oSearch = \DBSearch::FromOQL($sOQL);
|
||||
$aFields = $oSearchForm->GetFields(new \DBObjectSet($oSearch));
|
||||
/** @var DBObjectSearch $oSearch */
|
||||
$aCriterion = $oSearchForm->GetCriterion($oSearch, $aFields);
|
||||
} catch (\OQLException $e)
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ class apcEmulationTest extends ItopTestCase
|
||||
{
|
||||
parent::setUp();
|
||||
require_once(APPROOT.'core/apc-emulation.php');
|
||||
require_once 'mockApcEmulation.php';
|
||||
require_once 'mockApcEmulation.incphp';
|
||||
apc_clear_cache();
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class dictTest extends ItopTestCase
|
||||
parent::setUp();
|
||||
require_once (APPROOT.'core/coreexception.class.inc.php');
|
||||
require_once (APPROOT.'core/dict.class.inc.php');
|
||||
require_once 'mockDict.php';
|
||||
require_once 'mockDict.incphp';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user