فهرست منبع

- Use the new HierarchicalKeys for Organization and Locations and use the hierarchy of organization for the profiles/user rights.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1382 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 14 سال پیش
والد
کامیت
c62b94c12a

+ 44 - 6
addons/userrights/userrightsprofile.class.inc.php

@@ -780,8 +780,6 @@ exit;
 			// All of them are visible
 			return true;
 		}
-		$oExpression = new FieldExpression($sAttCode, $sClass);
-
 		// Position the user
 		//
 		@$aUserOrgs = $this->m_aUserOrgs[$oUser->GetKey()];
@@ -791,12 +789,52 @@ exit;
 			return true;
 		}
 
+		$oExpression = new FieldExpression($sAttCode, $sClass);
+		$oFilter  = new DBObjectSearch($sClass);
 		$aIds = array_keys($aUserOrgs);
 		$oListExpr = ListExpression::FromScalars($aIds);
-		$oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
-
-		$oFilter  = new DBObjectSearch($sClass);
-		$oFilter->AddConditionExpression($oCondition);
+		
+		// Check if the condition points to a hierarchical key
+		if ($sAttCode == 'id')
+		{
+			// Filtering on the objects themselves
+			$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sClass);
+			
+			if ($sHierarchicalKeyCode !== false)
+			{
+				$oRootFilter = new DBObjectSearch($sClass);
+				$oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
+				$oRootFilter->AddConditionExpression($oCondition);
+				$oFilter->AddCondition_PointingTo($oRootFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); // Use the 'below' operator by default
+				$bConditionAdded = true;
+			}
+		}
+		else
+		{
+			$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
+			$bConditionAdded = false;
+			if ($oAttDef->IsExternalKey())
+			{
+				$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass());
+				
+				if ($sHierarchicalKeyCode !== false)
+				{
+					$oRootFilter = new DBObjectSearch($oAttDef->GetTargetClass());
+					$oExpression = new FieldExpression('id', $oAttDef->GetTargetClass());
+					$oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
+					$oRootFilter->AddConditionExpression($oCondition);
+					$oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass());
+					$oHKFilter->AddCondition_PointingTo($oRootFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW); // Use the 'below' operator by default
+					$oFilter->AddCondition_PointingTo($oHKFilter, $sAttCode);
+					$bConditionAdded = true;
+				}
+			}
+		}
+		if (!$bConditionAdded)
+		{
+			$oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr);
+			$oFilter->AddConditionExpression($oCondition);
+		}
 		return $oFilter;
 	}
 

+ 8 - 7
core/attributedef.class.inc.php

@@ -2431,9 +2431,10 @@ class AttributeHierarchicalKey extends AttributeExternalKey
 	static protected function ListExpectedParams()
 	{
 		$aParams = parent::ListExpectedParams();
-		//unset($aParams[array_search('targetclass', $aParams)]);
-		
-		//print_r($aParams);
+		$idx = array_search('targetclass', $aParams);
+		unset($aParams[$idx]);
+		$idx = array_search('jointype', $aParams);
+		unset($aParams[$idx]);
 		return $aParams; // TODO: mettre les bons parametres ici !!
 	}
 
@@ -2444,9 +2445,9 @@ class AttributeHierarchicalKey extends AttributeExternalKey
 	}
 
 	public function IsHierarchicalKey() {return true;}
+	public function GetTargetClass($iType = EXTKEY_RELATIVE) {return $this->GetHostClass();}
 	public function GetKeyAttDef($iType = EXTKEY_RELATIVE){return $this;}
-	public function GetKeyAttCode() {return $this->GetCode();} 
-	
+	public function GetKeyAttCode() {return $this->GetCode();}
 
 	public function GetBasicFilterOperators()
 	{
@@ -2637,8 +2638,8 @@ class AttributeExternalField extends AttributeDefinition
 	public function GetExtAttDef()
 	{
 		$oKeyAttDef = $this->GetKeyAttDef();
-		$oExtAttDef = MetaModel::GetAttributeDef($oKeyAttDef->Get("targetclass"), $this->Get("target_attcode"));
-		if (!is_object($oExtAttDef)) throw new CoreException("Invalid external field ".$this->GetCode()." in class ".$this->GetHostClass().". The class ".$oKeyAttDef->Get("targetclass")." has no attribute ".$this->Get("target_attcode"));
+		$oExtAttDef = MetaModel::GetAttributeDef($oKeyAttDef->GetTargetClass(), $this->Get("target_attcode"));
+		if (!is_object($oExtAttDef)) throw new CoreException("Invalid external field ".$this->GetCode()." in class ".$this->GetHostClass().". The class ".$oKeyAttDef->GetTargetClass()." has no attribute ".$this->Get("target_attcode"));
 		return $oExtAttDef;
 	}
 

+ 5 - 7
core/metamodel.class.php

@@ -1487,7 +1487,10 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
 		if ($sAttCode == 'finalclass') throw new Exception('Using a reserved keyword in metamodel declaration: '.$sAttCode);
 		if ($sAttCode == 'friendlyname') throw new Exception('Using a reserved keyword in metamodel declaration: '.$sAttCode);
 	
-		$sTargetClass = self::GetCallersPHPClass("Init");		
+		$sTargetClass = self::GetCallersPHPClass("Init");
+		// Set the "host class" as soon as possible, since HierarchicalKeys use it for their 'target class' as well
+		// and this needs to be know early (for Init_IsKnowClass 19 lines below)		
+		$oAtt->SetHostClass($sTargetClass);
 
 		// Some attributes could refer to a class
 		// declared in a module which is currently not installed/active
@@ -1527,12 +1530,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
 
 		self::$m_aAttribDefs[$sTargetClass][$oAtt->GetCode()] = $oAtt;
 		self::$m_aAttribOrigins[$sTargetClass][$oAtt->GetCode()] = $sTargetClass;
-		// Note: it looks redundant to put targetclass there, but a mix occurs when inheritance is used
-		
-		// Specific case of external fields:
-		// I wanted to simplify the syntax of the declaration of objects in the biz model
-		// Therefore, the reference to the host class is set there 
-		$oAtt->SetHostClass($sTargetClass);
+		// Note: it looks redundant to put targetclass there, but a mix occurs when inheritance is used		
 	}
 
 	public static function Init_SetZListItems($sListCode, $aItems)

+ 1 - 0
dictionaries/dictionary.itop.ui.php

@@ -920,5 +920,6 @@ When associated with a trigger, each action is given an "order" number, specifyi
 	'UI:Pagination:PageSize' => '%1$s objects per page',
 	'UI:Pagination:PagesLabel' => 'Pages:',
 	'UI:Pagination:All' => 'All',
+	'UI:HierarchyOf_Class' => 'Hierarchy of %1$s',
 ));
 ?>

+ 1 - 0
dictionaries/fr.dictionary.itop.ui.php

@@ -770,5 +770,6 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
 	'UI:Pagination:PageSize' => '%1$s éléments par page',
 	'UI:Pagination:PagesLabel' => 'Pages:',
 	'UI:Pagination:All' => 'Tous',
+	'UI:HierarchyOf_Class' => 'Hiérarchie de type %1$s',
 ));
 ?>

+ 2 - 2
modules/itop-config-mgmt-1.0.0/model.itop-config-mgmt.php

@@ -50,7 +50,7 @@ class Organization extends cmdbAbstractObject
 		MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
 		MetaModel::Init_AddAttribute(new AttributeString("code", array("allowed_values"=>null, "sql"=>"code", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
 		MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('active,inactive'), "sql"=>"status", "default_value"=>"active", "is_null_allowed"=>true, "depends_on"=>array())));
-		MetaModel::Init_AddAttribute(new AttributeExternalKey("parent_id", array("targetclass"=>"Organization", "jointype"=>null, "allowed_values"=>null, "sql"=>"parent_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
+		MetaModel::Init_AddAttribute(new AttributeHierarchicalKey("parent_id", array("allowed_values"=>null, "sql"=>"parent_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
 		MetaModel::Init_AddAttribute(new AttributeExternalField("parent_name", array("allowed_values"=>null, "extkey_attcode"=>"parent_id", "target_attcode"=>"name", "is_null_allowed"=>true, "depends_on"=>array())));
 
 		MetaModel::Init_SetZListItems('details', array('name', 'code', 'status', 'parent_id'));
@@ -87,7 +87,7 @@ class Location extends cmdbAbstractObject
 		MetaModel::Init_AddAttribute(new AttributeString("postal_code", array("allowed_values"=>null, "sql"=>"postal_code", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
 		MetaModel::Init_AddAttribute(new AttributeString("city", array("allowed_values"=>null, "sql"=>"city", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
 		MetaModel::Init_AddAttribute(new AttributeString("country", array("allowed_values"=>null, "sql"=>"country", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
-		MetaModel::Init_AddAttribute(new AttributeExternalKey("parent_id", array("targetclass"=>"Location", "jointype"=>null, "allowed_values"=>new ValueSetObjects('SELECT Location AS L WHERE L.org_id = :this->org_id'), "sql"=>"parent_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array("org_id"))));
+		MetaModel::Init_AddAttribute(new AttributeHierarchicalKey("parent_id", array("allowed_values"=>new ValueSetObjects('SELECT Location AS L WHERE L.org_id = :this->org_id'), "sql"=>"parent_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array("org_id"))));
 		MetaModel::Init_AddAttribute(new AttributeExternalField("parent_name", array("allowed_values"=>null, "extkey_attcode"=>"parent_id", "target_attcode"=>"name", "is_null_allowed"=>true, "depends_on"=>array())));
 
 		MetaModel::Init_AddAttribute(new AttributeLinkedSet("contact_list", array("linked_class"=>"Contact", "ext_key_to_me"=>"location_id", "allowed_values"=>null, "count_min"=>0, "count_max"=>0, "depends_on"=>array())));

+ 2 - 1
pages/run_query.php

@@ -42,7 +42,8 @@ function ShowExamples($oP, $sExpression)
 			"Person having an 'A' in their name" => "SELECT Person AS B WHERE B.name LIKE '%A%'",
 			"Servers having a name like dbserver1.demo.com or dbserver023.foo.fr" => "SELECT Server WHERE name REGEXP '^dbserver[0-9]+\\\\..+\\\\.[a-z]{2,3}$'",
 			"Changes planned on new year's day" => "SELECT Change AS ch WHERE ch.start_date >= '2009-12-31' AND ch.end_date <= '2010-01-01'",
-			"IPs in a range" => "SELECT InfrastructureCI AS dev WHERE INET_ATON(dev.management_ip) > INET_ATON('10.22.32.224') AND INET_ATON(dev.management_ip) < INET_ATON('10.22.32.255')"
+			"IPs in a range" => "SELECT InfrastructureCI AS dev WHERE INET_ATON(dev.management_ip) > INET_ATON('10.22.32.224') AND INET_ATON(dev.management_ip) < INET_ATON('10.22.32.255')",
+			"Persons below a given root organization" => "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",
 		),
 		'Usefull examples' => array(
 			"NW interfaces of equipment in production for customer 'Demo'" => "SELECT NetworkInterface AS if JOIN InfrastructureCI AS dev ON if.device_id = dev.id WHERE if.status = 'production' AND dev.status = 'production' AND dev.owner_name = 'Demo' AND if.physical_type = 'ethernet'",