浏览代码

Enhancing the search (Trac #147): now allows to pass some "magic patterns" when doing a standard search without any operator. Specially useful for searching on ranges of dates/datetimes

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@638 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 15 年之前
父节点
当前提交
37d3b4bf0c

+ 4 - 4
application/cmdbabstract.class.inc.php

@@ -112,7 +112,7 @@ abstract class cmdbAbstractObject extends CMDBObject
 
 
 		// action menu
 		// action menu
 		$oSingletonFilter = new DBObjectSearch(get_class($this));
 		$oSingletonFilter = new DBObjectSearch(get_class($this));
-		$oSingletonFilter->AddCondition('id', array($this->GetKey()));
+		$oSingletonFilter->AddCondition('id', $this->GetKey(), '=');
 		$oBlock = new MenuBlock($oSingletonFilter, 'popup', false);
 		$oBlock = new MenuBlock($oSingletonFilter, 'popup', false);
 		$oBlock->Display($oPage, -1);
 		$oBlock->Display($oPage, -1);
 		$oPage->add("<div class=\"page_header\"><h1><img src=\"".$this->GetIcon()."\" style=\"margin-right:10px;margin-top: -16px;vertical-align:middle;\">\n");
 		$oPage->add("<div class=\"page_header\"><h1><img src=\"".$this->GetIcon()."\" style=\"margin-right:10px;margin-top: -16px;vertical-align:middle;\">\n");
@@ -124,8 +124,8 @@ abstract class cmdbAbstractObject extends CMDBObject
 	{
 	{
 		// history block (with as a tab)
 		// history block (with as a tab)
 		$oHistoryFilter = new DBObjectSearch('CMDBChangeOp');
 		$oHistoryFilter = new DBObjectSearch('CMDBChangeOp');
-		$oHistoryFilter->AddCondition('objkey', $this->GetKey());
-		$oHistoryFilter->AddCondition('objclass', get_class($this));
+		$oHistoryFilter->AddCondition('objkey', $this->GetKey(), '=');
+		$oHistoryFilter->AddCondition('objclass', get_class($this), '=');
 		$oBlock = new HistoryBlock($oHistoryFilter, 'table', false);
 		$oBlock = new HistoryBlock($oHistoryFilter, 'table', false);
 		$oBlock->Display($oPage, -1);
 		$oBlock->Display($oPage, -1);
 	}
 	}
@@ -163,7 +163,7 @@ abstract class cmdbAbstractObject extends CMDBObject
 					$oPage->p("<img src=\"".MetaModel::GetClassIcon($sTargetClass)."\" style=\"vertical-align:middle;\">&nbsp;".$oAttDef->GetDescription());
 					$oPage->p("<img src=\"".MetaModel::GetClassIcon($sTargetClass)."\" style=\"vertical-align:middle;\">&nbsp;".$oAttDef->GetDescription());
 
 
 					$oFilter = new DBObjectSearch($sTargetClass);
 					$oFilter = new DBObjectSearch($sTargetClass);
-					$oFilter->AddCondition($oAttDef->GetExtKeyToMe(), $this->GetKey());
+					$oFilter->AddCondition($oAttDef->GetExtKeyToMe(), $this->GetKey(),'=');
 
 
 					$oBlock = new DisplayBlock($oFilter, 'list', false);
 					$oBlock = new DisplayBlock($oFilter, 'list', false);
 					$oBlock->Display($oPage, 0);
 					$oBlock->Display($oPage, 0);

+ 1 - 1
application/user.preferences.class.inc.php

@@ -125,7 +125,7 @@ class appUserPreferences extends DBObject
 	{
 	{
 		if (self::$oUserPrefs != null) return;
 		if (self::$oUserPrefs != null) return;
 		$oSearch = new DBObjectSearch('appUserPreferences');
 		$oSearch = new DBObjectSearch('appUserPreferences');
-		$oSearch->AddCondition('userid', UserRights::GetUser());
+		$oSearch->AddCondition('userid', UserRights::GetUser(), '=');
 		$oSet = new DBObjectSet($oSearch);
 		$oSet = new DBObjectSet($oSearch);
 		$oObj = $oSet->Fetch();
 		$oObj = $oSet->Fetch();
 		if ($oObj == null)
 		if ($oObj == null)

+ 97 - 0
core/attributedef.class.inc.php

@@ -260,6 +260,35 @@ abstract class AttributeDefinition
 		if (!$oValSetDef) return null;
 		if (!$oValSetDef) return null;
 		return $oValSetDef->GetValues($aArgs, $sBeginsWith);
 		return $oValSetDef->GetValues($aArgs, $sBeginsWith);
 	}
 	}
+	
+	/**
+	 * Parses a string to find some smart search patterns and build the corresponding search/OQL condition
+	 * Each derived class is reponsible for defining and processing their own smart patterns, the base class
+	 * does nothing special, and just calls the default (loose) operator
+	 * @param string $sSearchText The search string to analyze for smart patterns
+	 * @param FieldExpression The FieldExpression representing the atttribute code in this OQL query
+	 * @param Hash $aParams Values of the query parameters
+	 * @return Expression The search condition to be added (AND) to the current search
+	 */
+	public function GetSmartConditionExpression($sSearchText, FieldExpression $oField, &$aParams)
+	{
+		$sParamName = $oField->GetParent().'_'.$oField->GetName();
+		$oRightExpr = new VariableExpression($sParamName);
+		$sOperator = $this->GetBasicFilterLooseOperator();
+		switch ($sOperator)
+		{
+			case 'Contains':
+			$aParams[$sParamName] = "%$sSearchText%";
+			$sSQLOperator = 'LIKE';
+			break;
+			
+			default:
+			$sSQLOperator = $sOperator;
+			$aParams[$sParamName] = $sSearchText;
+		}
+		$oNewCondition = new BinaryExpression($oField, $sSQLOperator, $oRightExpr);
+		return $oNewCondition;
+	}
 }
 }
 
 
 /**
 /**
@@ -1189,6 +1218,74 @@ class AttributeDateTime extends AttributeDBField
 		$sEscaped = str_replace($sFrom, $sTo, (string)$sValue);
 		$sEscaped = str_replace($sFrom, $sTo, (string)$sValue);
 		return '"'.$sEscaped.'"';
 		return '"'.$sEscaped.'"';
 	}
 	}
+	
+	/**
+	 * Parses a string to find some smart search patterns and build the corresponding search/OQL condition
+	 * Each derived class is reponsible for defining and processing their own smart patterns, the base class
+	 * does nothing special, and just calls the default (loose) operator
+	 * @param string $sSearchText The search string to analyze for smart patterns
+	 * @param FieldExpression The FieldExpression representing the atttribute code in this OQL query
+	 * @param Hash $aParams Values of the query parameters
+	 * @return Expression The search condition to be added (AND) to the current search
+	 */
+	public function GetSmartConditionExpression($sSearchText, FieldExpression $oField, &$aParams)
+	{
+		// Possible smart patterns
+		$aPatterns = array(
+			'between' => array('pattern' => '/^\[(.*),(.*)\]$/', 'operator' => 'n/a'),
+			'greater than or equal' => array('pattern' => '/^>=(.*)$/', 'operator' => '>='),
+			'greater than' => array('pattern' => '/^>(.*)$/', 'operator' => '>'),
+			'less than or equal' => array('pattern' => '/^<=(.*)$/', 'operator' => '<='),
+			'less than' =>  array('pattern' => '/^<(.*)$/', 'operator' => '<'),
+		);
+		
+		$sPatternFound = '';
+		$aMatches = array();
+		foreach($aPatterns as $sPatName => $sPattern)
+		{
+			if (preg_match($sPattern['pattern'], $sSearchText, $aMatches))
+			{
+				$sPatternFound = $sPatName;
+				break;
+			}			
+		}
+		
+		switch($sPatternFound)
+		{
+			case 'between':
+			
+			$sParamName1 = $oField->GetParent().'_'.$oField->GetName().'_1';
+			$oRightExpr = new VariableExpression($sParamName1);
+			$aParams[$sParamName1] = $aMatches[1];
+			$oCondition1 = new BinaryExpression($oField, '>=', $oRightExpr);
+
+			$sParamName2 = $oField->GetParent().'_'.$oField->GetName().'_2';
+			$oRightExpr = new VariableExpression($sParamName2);
+			$sOperator = $this->GetBasicFilterLooseOperator();
+			$aParams[$sParamName2] = $aMatches[2];
+			$oCondition2 = new BinaryExpression($oField, '<=', $oRightExpr);
+			
+			$oNewCondition = new BinaryExpression($oCondition1, 'AND', $oCondition2);
+			break;
+			
+			case 'greater than':
+			case 'greater than or equal':
+			case 'less than':
+			case 'less than or equal':
+			$sSQLOperator = $aPatterns[$sPatternFound]['operator'];
+			$sParamName = $oField->GetParent().'_'.$oField->GetName();
+			$oRightExpr = new VariableExpression($sParamName);
+			$aParams[$sParamName] = $aMatches[1];
+			$oNewCondition = new BinaryExpression($oField, $sSQLOperator, $oRightExpr);
+			
+			break;
+						
+			default:
+			$oNewCondition = parent::GetSmartConditionExpression($sSearchText, $oField, &$aParams);
+		}
+
+		return $oNewCondition;
+	}
 }
 }
 
 
 /**
 /**

+ 3 - 3
core/cmdbchangeop.class.inc.php

@@ -212,7 +212,7 @@ class CMDBChangeOpSetAttributeScalar extends CMDBChangeOpSetAttribute
 		$oTargetObjectClass = $this->Get('objclass');
 		$oTargetObjectClass = $this->Get('objclass');
 		$oTargetObjectKey = $this->Get('objkey');
 		$oTargetObjectKey = $this->Get('objkey');
 		$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
 		$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
-		$oTargetSearch->AddCondition('id', $oTargetObjectKey);
+		$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
 
 
 		$oMonoObjectSet = new DBObjectSet($oTargetSearch);
 		$oMonoObjectSet = new DBObjectSet($oTargetSearch);
 		if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
 		if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
@@ -301,7 +301,7 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
 		$oTargetObjectClass = $this->Get('objclass');
 		$oTargetObjectClass = $this->Get('objclass');
 		$oTargetObjectKey = $this->Get('objkey');
 		$oTargetObjectKey = $this->Get('objkey');
 		$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
 		$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
-		$oTargetSearch->AddCondition('id', $oTargetObjectKey);
+		$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
 
 
 		$oMonoObjectSet = new DBObjectSet($oTargetSearch);
 		$oMonoObjectSet = new DBObjectSet($oTargetSearch);
 		if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
 		if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
@@ -360,7 +360,7 @@ class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
 		$oTargetObjectClass = $this->Get('objclass');
 		$oTargetObjectClass = $this->Get('objclass');
 		$oTargetObjectKey = $this->Get('objkey');
 		$oTargetObjectKey = $this->Get('objkey');
 		$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
 		$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
-		$oTargetSearch->AddCondition('id', $oTargetObjectKey);
+		$oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
 
 
 		$oMonoObjectSet = new DBObjectSet($oTargetSearch);
 		$oMonoObjectSet = new DBObjectSet($oTargetSearch);
 		if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
 		if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)

+ 1 - 1
core/dbobject.class.php

@@ -1101,7 +1101,7 @@ abstract class DBObject
 				if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) continue;
 				if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) continue;
 
 
 				$oSearch = new DBObjectSearch($sRemoteClass);
 				$oSearch = new DBObjectSearch($sRemoteClass);
-				$oSearch->AddCondition($sExtKeyAttCode, $this->GetKey());
+				$oSearch->AddCondition($sExtKeyAttCode, $this->GetKey(), '=');
 				$oSet = new CMDBObjectSet($oSearch);
 				$oSet = new CMDBObjectSet($oSearch);
 				if ($oSet->Count() > 0)
 				if ($oSet->Count() > 0)
 				{
 				{

+ 12 - 2
core/dbobjectsearch.class.php

@@ -224,15 +224,25 @@ class DBObjectSearch
 		MyHelpers::CheckKeyInArray('filter code', $sFilterCode, MetaModel::GetClassFilterDefs($this->GetClass()));
 		MyHelpers::CheckKeyInArray('filter code', $sFilterCode, MetaModel::GetClassFilterDefs($this->GetClass()));
 		$oFilterDef = MetaModel::GetClassFilterDef($this->GetClass(), $sFilterCode);
 		$oFilterDef = MetaModel::GetClassFilterDef($this->GetClass(), $sFilterCode);
 
 
+		$oField = new FieldExpression($sFilterCode, $this->GetClassAlias());
 		if (empty($sOpCode))
 		if (empty($sOpCode))
 		{
 		{
-			$sOpCode = $oFilterDef->GetLooseOperator();
+			if ($sFilterCode == 'id')
+			{
+				$sOpCode = '=';
+			}
+			else
+			{
+				$oAttDef = MetaModel::GetAttributeDef($this->GetClass(), $sFilterCode);
+				$oNewCondition = $oAttDef->GetSmartConditionExpression($value, $oField, $this->m_aParams);
+				$this->AddConditionExpression($oNewCondition);
+				return;
+			}
 		}
 		}
 		MyHelpers::CheckKeyInArray('operator', $sOpCode, $oFilterDef->GetOperators());
 		MyHelpers::CheckKeyInArray('operator', $sOpCode, $oFilterDef->GetOperators());
 
 
 		// Preserve backward compatibility - quick n'dirty way to change that API semantic
 		// Preserve backward compatibility - quick n'dirty way to change that API semantic
 		//
 		//
-		$oField = new FieldExpression($sFilterCode, $this->GetClassAlias());
 		switch($sOpCode)
 		switch($sOpCode)
 		{
 		{
 		case 'SameDay':
 		case 'SameDay':

+ 1 - 1
pages/ajax.csvimport.php

@@ -330,7 +330,7 @@ EOF
 	case 'get_csv_template':
 	case 'get_csv_template':
 	$sClassName = utils::ReadParam('class_name');
 	$sClassName = utils::ReadParam('class_name');
 	$oSearch = new DBObjectSearch($sClassName);
 	$oSearch = new DBObjectSearch($sClassName);
-	$oSearch->AddCondition('id', 0); // Make sure we create an empty set
+	$oSearch->AddCondition('id', 0, '='); // Make sure we create an empty set
 	$oSet = new CMDBObjectSet($oSearch);
 	$oSet = new CMDBObjectSet($oSearch);
 	$sResult = cmdbAbstractObject::GetSetAsCSV($oSet);
 	$sResult = cmdbAbstractObject::GetSetAsCSV($oSet);
 	//$aCSV = explode("\n", $sCSV);
 	//$aCSV = explode("\n", $sCSV);

+ 1 - 1
pages/ajax.render.php

@@ -280,7 +280,7 @@ switch($operation)
 	$iCount = 0;
 	$iCount = 0;
 	$oFilter = $oContext->NewFilter($sClass);
 	$oFilter = $oContext->NewFilter($sClass);
 	$oFilter->AddCondition($sAttCode, $sName, 'Begins with');
 	$oFilter->AddCondition($sAttCode, $sName, 'Begins with');
-	//$oFilter->AddCondition('org_id', $sOrg);
+	//$oFilter->AddCondition('org_id', $sOrg, '=');
 	$oSet = new CMDBObjectSet($oFilter, array($sAttCode => true));
 	$oSet = new CMDBObjectSet($oFilter, array($sAttCode => true));
 	while( ($iCount < $iMaxCount) && ($oObj = $oSet->fetch()) )
 	while( ($iCount < $iMaxCount) && ($oObj = $oSet->fetch()) )
 	{
 	{

+ 3 - 3
pages/audit.php

@@ -92,7 +92,7 @@ switch($operation)
 	$oDefinitionFilter = DBObjectSearch::FromOQL($oAuditCategory->Get('definition_set'));
 	$oDefinitionFilter = DBObjectSearch::FromOQL($oAuditCategory->Get('definition_set'));
 	if (!empty($currentOrganization))
 	if (!empty($currentOrganization))
 	{
 	{
-		$oDefinitionFilter->AddCondition('org_id', $currentOrganization);
+		$oDefinitionFilter->AddCondition('org_id', $currentOrganization, '=');
 	}
 	}
 	$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
 	$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
 	$oErrorObjectSet = GetRuleResultSet($iRuleIndex, $oDefinitionFilter);
 	$oErrorObjectSet = GetRuleResultSet($iRuleIndex, $oDefinitionFilter);
@@ -124,14 +124,14 @@ switch($operation)
 		{
 		{
 			if (MetaModel::IsValidFilterCode($oDefinitionFilter->GetClass(), 'org_id'))
 			if (MetaModel::IsValidFilterCode($oDefinitionFilter->GetClass(), 'org_id'))
 			{
 			{
-				$oDefinitionFilter->AddCondition('org_id', $currentOrganization);
+				$oDefinitionFilter->AddCondition('org_id', $currentOrganization, '=');
 			}
 			}
 		}
 		}
 		$aResults = array();
 		$aResults = array();
 		$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
 		$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
 		$iCount = $oDefinitionSet->Count();
 		$iCount = $oDefinitionSet->Count();
 		$oRulesFilter = new CMDBSearchFilter('AuditRule');
 		$oRulesFilter = new CMDBSearchFilter('AuditRule');
-		$oRulesFilter->AddCondition('category_id', $oAuditCategory->GetKey());
+		$oRulesFilter->AddCondition('category_id', $oAuditCategory->GetKey(), '=');
 		$oRulesSet = new DBObjectSet($oRulesFilter);
 		$oRulesSet = new DBObjectSet($oRulesFilter);
 		while($oAuditRule = $oRulesSet->fetch() )
 		while($oAuditRule = $oRulesSet->fetch() )
 		{
 		{

+ 1 - 1
setup/xmldataloader.class.inc.php

@@ -252,7 +252,7 @@ class XMLDataLoader
 					{
 					{
 						if ($oTargetObj->Get($sAttCode) != '')
 						if ($oTargetObj->Get($sAttCode) != '')
 						{
 						{
-							$oSearch->AddCondition($sAttCode, $oTargetObj->Get($sAttCode));
+							$oSearch->AddCondition($sAttCode, $oTargetObj->Get($sAttCode), '=');
 							$iConditionsCount++;
 							$iConditionsCount++;
 						}
 						}
 					}
 					}