Browse Source

N°436 Core API: Correctly (mathematically!) handle the "allow all data" flag, with UNIONS and INTERSECTIONS. Requires testing

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@4404 a333f486-631f-4898-b8df-5754b55c2be0
romainq 8 năm trước cách đây
mục cha
commit
c05b6818e5
3 tập tin đã thay đổi với 72 bổ sung44 xóa
  1. 45 4
      core/dbobjectsearch.class.php
  2. 9 38
      core/dbsearch.class.php
  3. 18 2
      core/dbunionsearch.class.php

+ 45 - 4
core/dbobjectsearch.class.php

@@ -35,6 +35,11 @@ class DBObjectSearch extends DBSearch
 	private $m_aPointingTo;
 	private $m_aReferencedBy;
 
+	// By default, some information may be hidden to the current user
+	// But it may happen that we need to disable that feature
+	protected $m_bAllowAllData = false;
+	protected $m_bDataFiltered = false;
+
 	public function __construct($sClass, $sClassAlias = null)
 	{
 		parent::__construct();
@@ -52,6 +57,11 @@ class DBObjectSearch extends DBSearch
 		$this->m_aReferencedBy = array();
 	}
 
+	public function AllowAllData($bAllowAllData = true) {$this->m_bAllowAllData = $bAllowAllData;}
+	public function IsAllDataAllowed() {return $this->m_bAllowAllData;}
+	protected function IsDataFiltered() {return $this->m_bDataFiltered; }
+	protected function SetDataFiltered() {$this->m_bDataFiltered = true;}
+
 	// Create a search definition that leads to 0 result, still a valid search object
 	static public function FromEmptySet($sClass)
 	{
@@ -654,7 +664,10 @@ class DBObjectSearch extends DBSearch
 
 			$oLeftFilter = $this->DeepClone();
 			$oRightFilter = $oRightFilter->DeepClone();
-	
+
+			$bAllowAllData = ($oLeftFilter->IsAllDataAllowed() && $oRightFilter->IsAllDataAllowed());
+			$oLeftFilter->AllowAllData($bAllowAllData);
+
 			if ($oLeftFilter->GetClass() != $oRightFilter->GetClass())
 			{
 				if (MetaModel::IsParentClass($oLeftFilter->GetClass(), $oRightFilter->GetClass()))
@@ -810,7 +823,7 @@ class DBObjectSearch extends DBSearch
 		return $this->m_oSearchCondition->ApplyParameters(array_merge($this->m_aParams, $aArgs));
 	}
 	
-	public function ToOQL($bDevelopParams = false, $aContextParams = null)
+	public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false)
 	{
 		// Currently unused, but could be useful later
 		$bRetrofitParams = false;
@@ -850,6 +863,10 @@ class DBObjectSearch extends DBSearch
 		{
 			$sRes .= " AND MATCHES '$sFullText'";
 		}
+		if ($bWithAllowAllFlag && $this->m_bAllowAllData)
+		{
+			$sRes .= " ALLOW ALL DATA";
+		}
 		return $sRes;
 	}
 
@@ -1131,9 +1148,33 @@ class DBObjectSearch extends DBSearch
 
 	public function MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null)
 	{
-		$oBuild = new QueryBuilderContext($this, $aModifierProperties, $aGroupByExpr, $aSelectedClasses);
+		// Hide objects that are not visible to the current user
+		//
+		$oSearch = $this;
+		if (!$this->IsAllDataAllowed() && !$this->IsDataFiltered())
+		{
+			$oVisibleObjects = UserRights::GetSelectFilter($this->GetClass(), $this->GetModifierProperties('UserRightsGetSelectFilter'));
+			if ($oVisibleObjects === false)
+			{
+				// Make sure this is a valid search object, saying NO for all
+				$oVisibleObjects = DBObjectSearch::FromEmptySet($this->GetClass());
+			}
+			if (is_object($oVisibleObjects))
+			{
+				$oVisibleObjects->AllowAllData();
+				$oSearch = $this->Intersect($oVisibleObjects);
+				$oSearch->SetDataFiltered();
+			}
+			else
+			{
+				// should be true at this point, meaning that no additional filtering
+				// is required
+			}
+		}
+
+		$oBuild = new QueryBuilderContext($oSearch, $aModifierProperties, $aGroupByExpr, $aSelectedClasses);
 
-		$oSQLQuery = $this->MakeSQLObjectQuery($oBuild, $aAttToLoad, array());
+		$oSQLQuery = $oSearch->MakeSQLObjectQuery($oBuild, $aAttToLoad, array());
 		$oSQLQuery->SetCondition($oBuild->m_oQBExpressions->GetCondition());
 		if ($aGroupByExpr)
 		{

+ 9 - 38
core/dbsearch.class.php

@@ -42,14 +42,9 @@ abstract class DBSearch
 	const JOIN_POINTING_TO = 0;
 	const JOIN_REFERENCED_BY = 1;
 
-	protected $m_bDataFiltered = false;
 	protected $m_bNoContextParameters = false;
 	protected $m_aModifierProperties = array();
 
-	// By default, some information may be hidden to the current user
-	// But it may happen that we need to disable that feature
-	protected $m_bAllowAllData = false;
-
 	public function __construct()
 	{
 	}
@@ -62,12 +57,11 @@ abstract class DBSearch
 		return unserialize(serialize($this)); // Beware this serializes/unserializes the search and its parameters as well
 	}
 
-	public function AllowAllData() {$this->m_bAllowAllData = true;}
-	public function IsAllDataAllowed() {return $this->m_bAllowAllData;}
+	abstract public function AllowAllData();
+	abstract public function IsAllDataAllowed();
+
 	public function NoContextParameters() {$this->m_bNoContextParameters = true;}
 	public function HasContextParameters() {return $this->m_bNoContextParameters;}
-	public function IsDataFiltered() {return $this->m_bDataFiltered; }
-	public function SetDataFiltered() {$this->m_bDataFiltered = true;}
 
 	public function SetModifierProperty($sPluginClass, $sProperty, $value)
 	{
@@ -219,7 +213,7 @@ abstract class DBSearch
         return $oSearchWithAlias;
     }
 
-    abstract public function ToOQL($bDevelopParams = false, $aContextParams = null);
+    abstract public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false);
 
 	static protected $m_aOQLQueries = array();
 
@@ -492,39 +486,16 @@ abstract class DBSearch
 
 	protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null)
 	{
-		// Hide objects that are not visible to the current user
-		//
-		$oSearch = $this;
-		if (!$this->IsAllDataAllowed() && !$this->IsDataFiltered())
-		{
-			$oVisibleObjects = UserRights::GetSelectFilter($this->GetClass(), $this->GetModifierProperties('UserRightsGetSelectFilter'));
-			if ($oVisibleObjects === false)
-			{
-				// Make sure this is a valid search object, saying NO for all
-				$oVisibleObjects = DBObjectSearch::FromEmptySet($this->GetClass());
-			}
-			if (is_object($oVisibleObjects))
-			{
-				$oSearch = $this->Intersect($oVisibleObjects);
-				$oSearch->SetDataFiltered();
-			}
-			else
-			{
-				// should be true at this point, meaning that no additional filtering
-				// is required
-			}
-		}
-
 		// Compute query modifiers properties (can be set in the search itself, by the context, etc.)
 		//
-		$aModifierProperties = MetaModel::MakeModifierProperties($oSearch);
+		$aModifierProperties = MetaModel::MakeModifierProperties($this);
 
 		// Create a unique cache id
 		//
 		if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
 		{
 			// Need to identify the query
-			$sOqlQuery = $oSearch->ToOql();
+			$sOqlQuery = $this->ToOql(false, null, true);
 
 			if (count($aModifierProperties))
 			{
@@ -553,7 +524,7 @@ abstract class DBSearch
 		}
 		else
 		{
-			$sOqlQuery = "SELECTING... ".$oSearch->GetClass();
+			$sOqlQuery = "SELECTING... ".$this->GetClass();
 			$sOqlId = "query id ? n/a";
 		}
 
@@ -599,7 +570,7 @@ abstract class DBSearch
 		if (!isset($oSQLQuery))
 		{
 			$oKPI = new ExecutionKPI();
-			$oSQLQuery = $oSearch->MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr);
+			$oSQLQuery = $this->MakeSQLQuery($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr);
 			$oSQLQuery->SetSourceOQL($sOqlQuery);
 			$oKPI->ComputeStats('MakeSQLQuery', $sOqlQuery);
 
@@ -624,7 +595,7 @@ abstract class DBSearch
 			$aExtendedFields = array();
 			foreach($aExtendedDataSpec['fields'] as $sColumn)
 			{
-				$sColRef = $oSearch->GetClassAlias().'_extdata_'.$sColumn;
+				$sColRef = $this->GetClassAlias().'_extdata_'.$sColumn;
 				$aExtendedFields[$sColRef] = new FieldExpressionResolved($sColumn, $sTableAlias);
 			}
 			$oSQLQueryExt = new SQLObjectQuery($aExtendedDataSpec['table'], $sTableAlias, $aExtendedFields);

+ 18 - 2
core/dbunionsearch.class.php

@@ -55,6 +55,22 @@ class DBUnionSearch extends DBSearch
 		$this->ComputeSelectedClasses();
 	}
 
+	public function AllowAllData()
+	{
+		foreach ($this->aSearches as $oSearch)
+		{
+			$oSearch->AllowAllData();
+		}
+	}
+	public function IsAllDataAllowed()
+	{
+		foreach ($this->aSearches as $oSearch)
+		{
+			if ($oSearch->IsAllDataAllowed() === false) return false;
+		}
+		return true;
+	}
+
 	/**
 	 * Find the lowest common ancestor for each of the selected class
 	 */
@@ -357,12 +373,12 @@ class DBUnionSearch extends DBSearch
 	/**
 	 * Overloads for query building
 	 */ 
-	public function ToOQL($bDevelopParams = false, $aContextParams = null)
+	public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false)
 	{
 		$aSubQueries = array();
 		foreach ($this->aSearches as $oSearch)
 		{
-			$aSubQueries[] = $oSearch->ToOQL($bDevelopParams, $aContextParams);
+			$aSubQueries[] = $oSearch->ToOQL($bDevelopParams, $aContextParams, $bWithAllowAllFlag);
 		}
 		$sRet = implode(' UNION ', $aSubQueries);
 		return $sRet;