Explorar o código

OQL normalization and dashlets have been made independent from the class MetaModel (reviewed the API)

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@2772 a333f486-631f-4898-b8df-5754b55c2be0
romainq %!s(int64=12) %!d(string=hai) anos
pai
achega
22b1599776

+ 21 - 14
application/dashlet.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2012-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -536,16 +536,19 @@ abstract class DashletGroupBy extends Dashlet
 		$oSearch = DBObjectSearch::FromOQL($sOql);
 		$sClass = $oSearch->GetClass();
 		$aGroupBy = array();
-		foreach($this->oModelReflection->ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
+		foreach($this->oModelReflection->ListAttributes($sClass) as $sAttCode => $sAttType)
 		{
-			if (!$oAttDef->IsScalar()) continue; // skip link sets
-			if ($oAttDef instanceof AttributeFriendlyName) continue;
-			if ($oAttDef instanceof AttributeExternalField) continue;
-
-			$sLabel = $oAttDef->GetLabel();
+			if ($sAttType == 'AttributeLinkedSet') continue;
+			if (is_subclass_of($sAttType, 'AttributeLinkedSet')) continue;
+			if ($sAttType == 'AttributeFriendlyName') continue;
+			if (is_subclass_of($sAttType, 'AttributeFriendlyName')) continue;
+			if ($sAttType == 'AttributeExternalField') continue;
+			if (is_subclass_of($sAttType, 'AttributeExternalField')) continue;
+
+			$sLabel = $this->oModelReflection->GetLabel($sClass, $sAttCode);
 			$aGroupBy[$sAttCode] = $sLabel;
 
-			if ($oAttDef instanceof AttributeDateTime)
+			if (is_subclass_of($sAttType, 'AttributeDateTime') || $sAttType == 'AttributeDateTime')
 			{
 				$aGroupBy[$sAttCode.':hour'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-Hour', $sLabel);
 				$aGroupBy[$sAttCode.':month'] = Dict::Format('UI:DashletGroupBy:Prop-GroupBy:Select-Month', $sLabel);
@@ -931,10 +934,13 @@ class DashletHeaderDynamic extends Dashlet
 			$oSearch = DBObjectSearch::FromOQL($this->aProperties['query']);
 			$sClass = $oSearch->GetClass();
 			$aGroupBy = array();
-			foreach($this->oModelReflection->ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
+			foreach($this->oModelReflection->ListAttributes($sClass, 'AttributeEnum,AttributeFinalClass') as $sAttCode => $sAttType)
 			{
-				if (!$oAttDef instanceof AttributeEnum && (!$oAttDef instanceof AttributeFinalClass || !$this->oModelReflection->HasChildrenClasses($sClass))) continue;
-				$sLabel = $oAttDef->GetLabel();
+				if (is_subclass_of($sAttType, 'AttributeFinalClass') || ($sAttType == 'AttributeFinalClass'))
+				{
+					if (!$this->oModelReflection->HasChildrenClasses($sClass)) continue;
+				}
+				$sLabel = $this->oModelReflection->GetLabel($sClass, $sAttCode);
 				$aGroupBy[$sAttCode] = $sLabel;
 			}
 			$oField = new DesignerComboField('group_by', Dict::S('UI:DashletHeaderDynamic:Prop-GroupBy'), $this->aProperties['group_by']);
@@ -1050,11 +1056,12 @@ class DashletBadge extends Dashlet
 	
 		foreach($this->oModelReflection->GetClasses('bizmodel') as $sClass)
 		{	
-			foreach($this->oModelReflection->ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
+			foreach($this->oModelReflection->ListAttributes($sClass, 'AttributeLinkedSetIndirect') as $sAttCode => $sAttType)
 			{
-				if ($oAttDef instanceof AttributeLinkedSetIndirect)
+				$sLinkedClass = $this->oModelReflection->GetAttributeProperty($sClass, $sAttCode, 'linked_class');
+				if ($sLinkedClass != null)
 				{
-					$aLinkClasses[$oAttDef->GetLinkedClass()] = true;
+					$aLinkClasses[$sLinkedClass] = true;
 				}
 			}
 		}

+ 48 - 15
core/modelreflection.class.inc.php

@@ -30,13 +30,12 @@ interface ModelReflection
 	public function IsValidAttCode($sClass, $sAttCode);
 	public function GetName($sClass);
 	public function GetLabel($sClass, $sAttCodeEx);
-	public function ListAttributeDefs($sClass);
+	public function ListAttributes($sClass, $sScope = null);
+	public function GetAttributeProperty($sClass, $sAttCode, $sPropName);
 	public function GetAllowedValues_att($sClass, $sAttCode);
 	public function HasChildrenClasses($sClass);
 	public function GetClasses($sCategories = '');
 	public function IsValidClass($sClass);
-	public function GetExternalKeys($sClass);
-	public function GetAttributeDef($sClass, $sAttCode);
 	public function IsSameFamilyBranch($sClassA, $sClassB);
 	public function GetFiltersList($sClass);
 	public function IsValidFilterCode($sClass, $sFilterCode);
@@ -68,11 +67,55 @@ class ModelReflectionRuntime implements ModelReflection
 		return MetaModel::GetLabel($sClass, $sAttCodeEx);
 	}
  
-	public function ListAttributeDefs($sClass)
+	public function ListAttributes($sClass, $sScope = null)
 	{
-		return MetaModel::ListAttributeDefs($sClass);
+		$aScope = null;
+		if ($sScope != null)
+		{
+			$aScope = array();
+			foreach (explode(',', $sScope) as $sScopeClass)
+			{
+				$aScope[] = trim($sScopeClass);
+			}
+		}
+		$aAttributes = array();
+		foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
+		{
+			$sAttributeClass = get_class($oAttDef);
+			if ($aScope != null)
+			{
+				foreach ($aScope as $sScopeClass)
+				{
+					if (($sAttributeClass == $sScopeClass) || is_subclass_of($sAttributeClass, $sScopeClass))
+					{
+						$aAttributes[$sAttCode] = $sAttributeClass;
+						break;
+					}
+				}
+			}
+			else
+			{
+				$aAttributes[$sAttCode] = $sAttributeClass;
+			}
+		}
+		return $aAttributes;
 	}
  
+	public function GetAttributeProperty($sClass, $sAttCode, $sPropName, $default = null)
+	{
+		$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
+		$aParams = $oAttDef->GetParams();
+		if (array_key_exists($sPropName, $aParams))
+		{
+			$ret = $aParams[$sPropName];
+		}
+		else
+		{
+			$ret = $default;
+		}
+		return $ret;
+	}
+
 	public function GetAllowedValues_att($sClass, $sAttCode)
 	{
 		return MetaModel::GetAllowedValues_att($sClass, $sAttCode);
@@ -93,16 +136,6 @@ class ModelReflectionRuntime implements ModelReflection
 		return MetaModel::IsValidClass($sClass);
 	}
 
-	public function GetExternalKeys($sClass)
-	{
-		return MetaModel::GetExternalKeys($sClass);
-	}
-
-	public function GetAttributeDef($sClass, $sAttCode)
-	{
-		return MetaModel::GetAttributeDef($sClass, $sAttCode);
-	}
-
 	public function IsSameFamilyBranch($sClassA, $sClassB)
 	{
 		return MetaModel::IsSameFamilyBranch($sClassA, $sClassB);

+ 14 - 12
core/oql/oqlquery.class.inc.php

@@ -1,5 +1,5 @@
 <?php
-// Copyright (C) 2010-2012 Combodo SARL
+// Copyright (C) 2010-2013 Combodo SARL
 //
 //   This file is part of iTop.
 //
@@ -335,7 +335,7 @@ class OqlObjectQuery extends OqlQuery
 
 		if (!$oModelReflection->IsValidClass($sClass))
 		{
-			throw new UnknownClassOqlException($sSourceQuery, $this->GetClassDetails(), $oModelReflection->GetClasses('bizmodelx'));
+			throw new UnknownClassOqlException($sSourceQuery, $this->GetClassDetails(), $oModelReflection->GetClasses());
 		}
 
 		$aAliases = array($sClassAlias => $sClass);
@@ -387,18 +387,18 @@ class OqlObjectQuery extends OqlQuery
 				{
 					throw new OqlNormalizeException('Unknown class in join condition (right expression)', $sSourceQuery, $oRightField->GetParentDetails(), array_keys($aAliases));
 				}
-				$aExtKeys = array_keys($oModelReflection->GetExternalKeys($aAliases[$sFromClass]));
-				if (!in_array($sExtKeyAttCode, $aExtKeys))
+				$aExtKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], 'AttributeExternalKey');
+				if (!array_key_exists($sExtKeyAttCode, $aExtKeys))
 				{
-					throw new OqlNormalizeException('Unknown external key in join condition (left expression)', $sSourceQuery, $oLeftField->GetNameDetails(), $aExtKeys);
+					throw new OqlNormalizeException('Unknown external key in join condition (left expression)', $sSourceQuery, $oLeftField->GetNameDetails(), array_keys($aExtKeys));
 				}
 
 				if ($sFromClass == $sJoinClassAlias)
 				{
-					$oAttExtKey = $oModelReflection->GetAttributeDef($aAliases[$sFromClass], $sExtKeyAttCode);
-					if(!$oModelReflection->IsSameFamilyBranch($aAliases[$sToClass], $oAttExtKey->GetTargetClass()))
+					$sTargetClass = $oModelReflection->GetAttributeProperty($aAliases[$sFromClass], $sExtKeyAttCode, 'targetclass');
+					if(!$oModelReflection->IsSameFamilyBranch($aAliases[$sToClass], $sTargetClass))
 					{
-						throw new OqlNormalizeException("The joined class ($aAliases[$sFromClass]) is not compatible with the external key, which is pointing to {$oAttExtKey->GetTargetClass()}", $sSourceQuery, $oLeftField->GetNameDetails());
+						throw new OqlNormalizeException("The joined class ($aAliases[$sFromClass]) is not compatible with the external key, which is pointing to $sTargetClass", $sSourceQuery, $oLeftField->GetNameDetails());
 					}
 				}
 				else
@@ -434,12 +434,14 @@ class OqlObjectQuery extends OqlQuery
 						$iOperatorCode = TREE_OPERATOR_NOT_ABOVE_STRICT;
 						break;
 					}
-					$oAttExtKey = $oModelReflection->GetAttributeDef($aAliases[$sFromClass], $sExtKeyAttCode);
-					if(!$oModelReflection->IsSameFamilyBranch($aAliases[$sToClass], $oAttExtKey->GetTargetClass()))
+					$sTargetClass = $oModelReflection->GetAttributeProperty($aAliases[$sFromClass], $sExtKeyAttCode, 'targetclass');
+					if(!$oModelReflection->IsSameFamilyBranch($aAliases[$sToClass], $sTargetClass))
 					{
-						throw new OqlNormalizeException("The joined class ($aAliases[$sToClass]) is not compatible with the external key, which is pointing to {$oAttExtKey->GetTargetClass()}", $sSourceQuery, $oLeftField->GetNameDetails());
+						throw new OqlNormalizeException("The joined class ($aAliases[$sToClass]) is not compatible with the external key, which is pointing to $sTargetClass", $sSourceQuery, $oLeftField->GetNameDetails());
 					}
-					if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !($oAttExtKey instanceof AttributeHierarchicalKey))
+					$aAttList = $oModelReflection->ListAttributes($aAliases[$sFromClass]);
+					$sAttType = $aAttList[$sExtKeyAttCode];
+					if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !is_subclass_of($sAttType, 'AttributeHierarchicalKey') && ($sAttType != 'AttributeHierarchicalKey'))
 					{
 						throw new OqlNormalizeException("The specified tree operator $sOperator is not applicable to the key", $sSourceQuery, $oLeftField->GetNameDetails());
 					}