Browse Source

Fixed issues with pagination + core limitations in the use of Object Sets (wrong filter when adding objects to a set)

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1300 a333f486-631f-4898-b8df-5754b55c2be0
romainq 14 years ago
parent
commit
ec1a744652

+ 2 - 1
application/cmdbabstract.class.inc.php

@@ -752,7 +752,8 @@ $sHtml =
 EOF
 .$sHtml;
 			//$oP->add_ready_script("table.tablesorter( { headers: { 0: {sorter: false}}, widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $('#pager')});\n");
-			$sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them
+			$aArgs = $oSet->GetArgs();
+			$sExtraParams = addslashes(str_replace('"', "'", json_encode(array_merge($aExtraParams, $aArgs)))); // JSON encode, change the style of the quotes and escape them
 			$sSelectMode = '';
 			$sHeaders = '';
 			if ($bSelectMode)

+ 8 - 10
core/cmdbobject.class.inc.php

@@ -498,24 +498,22 @@ class CMDBObjectSet extends DBObjectSet
 	static public function FromScratch($sClass)
 	{
 		$oFilter = new CMDBSearchFilter($sClass);
-		$oRetSet = new CMDBObjectSet($oFilter); // THE ONLY DIFF IS HERE
-		// NOTE: THIS DOES NOT WORK IF m_bLoaded is private...
-		// BUT IT THAT CASE YOU DO NOT GET ANY ERROR !!!!!
+		$oFilter->AddConditionExpression(new FalseExpression());
+		$oRetSet = new self($oFilter);
+		// NOTE: THIS DOES NOT WORK IF m_bLoaded is private in the base class (and you will not get any error message)
 		$oRetSet->m_bLoaded = true; // no DB load
 		return $oRetSet;
 	} 
 
+	// create an object set ex nihilo
+	// input = array of objects
 	static public function FromArray($sClass, $aObjects)
 	{
-		$oFilter = new CMDBSearchFilter($sClass);
-		$oRetSet = new CMDBObjectSet($oFilter); // THE ONLY DIFF IS HERE
-		// NOTE: THIS DOES NOT WORK IF m_bLoaded is private...
-		// BUT IT THAT CASE YOU DO NOT GET ANY ERROR !!!!!
-		$oRetSet->m_bLoaded = true; // no DB load
-		$oRetSet->AddObjectArray($aObjects);
+		$oRetSet = self::FromScratch($sClass);
+		$oRetSet->AddObjectArray($aObjects, $sClass);
 		return $oRetSet;
 	} 
-	
+
 	static public function FromArrayAssoc($aClasses, $aObjects)
 	{
 		// In a perfect world, we should create a complete tree of DBObjectSearch,

+ 60 - 0
core/dbobjectsearch.class.php

@@ -221,6 +221,11 @@ class DBObjectSearch
 		// ? is that usefull/enough, do I need to rebuild the list after the subqueries ?
 	}
 
+	public function MergeConditionExpression($oExpression)
+	{
+		$this->m_oSearchCondition = $this->m_oSearchCondition->LogOr($oExpression); 
+	}
+
 	public function AddConditionExpression($oExpression)
 	{
 		$this->m_oSearchCondition = $this->m_oSearchCondition->LogAnd($oExpression); 
@@ -320,6 +325,61 @@ class DBObjectSearch
 		$this->AddConditionExpression($oNewCondition);
 	}
 
+	/**
+	 * Specify a condition on external keys or link sets
+	 * @param sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
+	 *                 Example: infra_list->ci_id->location_id->country	 
+	 * @param value The value to match
+	 * @return void
+	 */
+	public function AddConditionAdvanced($sAttSpec, $value)
+	{
+		$sClass = $this->GetClass();
+
+		$iPos = strpos($sAttSpec, '->');
+		if ($iPos !== false)
+		{
+			$sAttCode = substr($sAttSpec, 0, $iPos);
+			$sSubSpec = substr($sAttSpec, $iPos + 2);
+
+			if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
+			{
+				throw new Exception("Invalid attribute code '$sClass/$sAttCode' in condition specification '$sAttSpec'");
+			}
+
+			$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
+			if ($oAttDef->IsLinkSet())
+			{
+				$sTargetClass = $oAttDef->GetLinkedClass();
+				$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
+
+				$oNewFilter = new DBObjectSearch($sTargetClass);
+				$oNewFilter->AddConditionAdvanced($sSubSpec, $value);
+
+				$this->AddCondition_ReferencedBy($oNewFilter, $sExtKeyToMe);
+			}
+			elseif ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
+			{
+				$sTargetClass = $oAttDef->GetTargetClass(EXTKEY_ABSOLUTE);
+
+				$oNewFilter = new DBObjectSearch($sTargetClass);
+				$oNewFilter->AddConditionAdvanced($sSubSpec, $value);
+
+				$this->AddCondition_PointingTo($oNewFilter, $sAttCode);
+			}
+			else
+			{
+				throw new Exception("Attribute specification '$sAttSpec', '$sAttCode' should be either a link set or an external key");
+			}
+		}
+		else
+		{
+			// $sAttSpec is an attribute code
+			//
+			$this->AddCondition($sAttSpec, $value);
+		}
+	}
+
 	public function AddCondition_FullText($sFullText)
 	{
 		$this->m_aFullText[] = $sFullText;

+ 25 - 6
core/dbobjectset.class.php

@@ -32,6 +32,7 @@
 class DBObjectSet
 {
 	private $m_oFilter;
+	private $m_aAddedIds; // Ids of objects added
 	private $m_aOrderBy;
 	public $m_bLoaded;
 	private $m_aData;
@@ -41,6 +42,7 @@ class DBObjectSet
 	public function __construct(DBObjectSearch $oFilter, $aOrderBy = array(), $aArgs = array(), $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0)
 	{
 		$this->m_oFilter = $oFilter;
+		$this->m_aAddedIds = array();
 		$this->m_aOrderBy = $aOrderBy;
 		$this->m_aArgs = $aArgs;
 		$this->m_aAttToLoad = null;
@@ -128,7 +130,8 @@ class DBObjectSet
 
 	static public function FromScratch($sClass)
 	{
-		$oFilter = new CMDBSearchFilter($sClass);
+		$oFilter = new DBObjectSearch($sClass);
+		$oFilter->AddConditionExpression(new FalseExpression());
 		$oRetSet = new self($oFilter);
 		$oRetSet->m_bLoaded = true; // no DB load
 		return $oRetSet;
@@ -138,9 +141,7 @@ class DBObjectSet
 	// input = array of objects
 	static public function FromArray($sClass, $aObjects)
 	{
-		$oFilter = new CMDBSearchFilter($sClass);
-		$oRetSet = new self($oFilter);
-		$oRetSet->m_bLoaded = true; // no DB load
+		$oRetSet = self::FromScratch($sClass);
 		$oRetSet->AddObjectArray($aObjects, $sClass);
 		return $oRetSet;
 	} 
@@ -268,8 +269,19 @@ class DBObjectSet
 
 	public function GetFilter()
 	{
-		// #@# This is false as soon as the set has been manipulated (AddObject...)
-		return $this->m_oFilter;
+		if (count($this->m_aAddedIds) == 0)
+		{
+			return $this->m_oFilter;
+		}
+		else
+		{
+			$oFilter = $this->m_oFilter;
+			$oIdListExpr = ListExpression::FromScalars($this->m_aAddedIds);
+			$oIdExpr = new FieldExpression('id', $oFilter->GetClassAlias());
+			$oIdInList = new BinaryExpression($oIdExpr, 'IN', $oIdListExpr);
+			$oFilter->MergeConditionExpression($oIdInList);
+			return $oFilter;
+		}
 	}
 
 	public function GetClass()
@@ -287,6 +299,11 @@ class DBObjectSet
 		return MetaModel::GetRootClass($this->GetClass());
 	}
 
+	public function GetArgs()
+	{
+		return $this->m_aArgs;
+	}
+
 	public function SetLimit($iLimitCount, $iLimitStart = 0)
 	{
 		$this->m_iLimitCount = $iLimitCount;
@@ -427,6 +444,7 @@ class DBObjectSet
 		if (!is_null($oObject))
 		{
 			$this->m_aId2Row[$sClassAlias][$oObject->GetKey()] = $iNextPos;
+			$this->m_aAddedIds[] = $oObject->GetKey();
 		}
 	}
 
@@ -442,6 +460,7 @@ class DBObjectSet
 			if (!is_null($oObject))
 			{
 				$this->m_aId2Row[$sClassAlias][$oObject->GetKey()] = $iNextPos;
+				$this->m_aAddedIds[] = $oObject->GetKey();
 			}
 		}
 	}

+ 1 - 1
pages/ajax.render.php

@@ -51,7 +51,7 @@ try
 	switch($operation)
 	{
 		case 'pagination':
-		$sExtraParams = stripslashes(utils::ReadParam('extra_params', ''));
+		$sExtraParams = stripslashes(utils::ReadParam('extra_param', ''));
 		$aExtraParams = array();
 		if (!empty($sExtraParams))
 		{