Przeglądaj źródła

#148 Allow overloading attribute/enum labels in the dictionary

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1477 a333f486-631f-4898-b8df-5754b55c2be0
romainq 14 lat temu
rodzic
commit
7e2c8a8b83

+ 1 - 1
application/displayblock.class.inc.php

@@ -672,7 +672,7 @@ class DisplayBlock
 					$oFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
 					$oSet = new DBObjectSet($oFilter);
 					$aCounts[$sStateValue] = $oSet->Count();
-					$aStateLabels[$sStateValue] = Dict::S("Class:".$oAttDef->GetHostClass()."/Attribute:$sStateAttrCode/Value:$sStateValue");
+					$aStateLabels[$sStateValue] = $oAttDef->GetValueLabel($sStateValue);
 					if ($aCounts[$sStateValue] == 0)
 					{
 						$aCounts[$sStateValue] = '-';

+ 120 - 9
core/attributedef.class.inc.php

@@ -179,7 +179,26 @@ abstract class AttributeDefinition
 	public function IsWritable() {return false;} 
 	public function IsNullAllowed() {return true;} 
 	public function GetCode() {return $this->m_sCode;} 
-	public function GetLabel() {return Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode, $this->m_sCode);}
+
+	public function GetLabel()
+	{
+		$sLabel = Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode, '');
+		if (strlen($sLabel) == 0)
+		{
+			$sLabel = $this->m_sCode;
+			$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
+			if ($sParentClass)
+			{
+				if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
+				{
+					$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
+					$sLabel = $oAttDef->GetLabel();
+				}
+			}
+		}
+		return $sLabel;
+	}
+
 	public function GetLabel_Obsolete()
 	{
 		// Written for compatibility with a data model written prior to version 0.9.1
@@ -192,8 +211,42 @@ abstract class AttributeDefinition
 			return $this->GetLabel();
 		}
 	}
-	public function GetDescription() {return Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode.'+', '');} 
-	public function GetHelpOnEdition() {return Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode.'?', '');} 
+
+	public function GetDescription()
+	{
+		$sDescription = Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode.'+', '');
+		if (strlen($sDescription) == 0)
+		{
+			$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
+			if ($sParentClass)
+			{
+				if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
+				{
+					$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
+					$sDescription = $oAttDef->GetDescription();
+				}
+			}
+		}
+		return $sDescription;
+	} 
+
+	public function GetHelpOnEdition()
+	{
+		$sHelp = Dict::S('Class:'.$this->m_sHostClass.'/Attribute:'.$this->m_sCode.'?', '');
+		if (strlen($sHelp) == 0)
+		{
+			$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
+			if ($sParentClass)
+			{
+				if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
+				{
+					$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
+					$sHelp = $oAttDef->GetHelpOnEdition();
+				}
+			}
+		}
+		return $sHelp;
+	} 
 
 	public function GetHelpOnSmartSearch()
 	{
@@ -1895,7 +1948,7 @@ class AttributeEnum extends AttributeString
 		return parent::GetBasicFilterSQLExpr($sOpCode, $value);
 	} 
 
-	public function GetAsHTML($sValue, $oHostObject = null)
+	public function GetValueLabel($sValue)
 	{
 		if (is_null($sValue))
 		{
@@ -1904,17 +1957,61 @@ class AttributeEnum extends AttributeString
 		}
 		else
 		{
-			$sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue, $sValue);
+			$sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue, '');
+			if (strlen($sLabel) == 0)
+			{
+				$sLabel = $sValue;
+				$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
+				if ($sParentClass)
+				{
+					if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
+					{
+						$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
+						$sLabel = $oAttDef->GetValueLabel($sValue);
+					}
+				}
+			}
+		}
+		return $sLabel;
+	}
+
+	public function GetValueDescription($sValue)
+	{
+		if (is_null($sValue))
+		{
+			// Unless a specific label is defined for the null value of this enum, use a generic "undefined" label		
+			$sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', Dict::S('Enum:Undefined'));
+		}
+		else
+		{
+			$sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', '');
+			if (strlen($sDescription) == 0)
+			{
+				$sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
+				if ($sParentClass)
+				{
+					if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode))
+					{
+						$oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
+						$sDescription = $oAttDef->GetValueDescription($sValue);
+					}
+				}
+			}
 		}
-		$sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', $sValue);
+		return $sDescription;
+	}
+
+	public function GetAsHTML($sValue, $oHostObject = null)
+	{
+		$sLabel = $this->GetValueLabel($sValue);
+		$sDescription = $this->GetValueDescription($sValue);
 		// later, we could imagine a detailed description in the title
 		return "<span title=\"$sDescription\">".parent::GetAsHtml($sLabel)."</span>";
 	}
 
 	public function GetEditValue($sValue)
 	{
-		$sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue, $sValue);
-		return $sLabel;
+		return $this->GetValueLabel($sValue);
 	}
 
 	public function GetAllowedValues($aArgs = array(), $sContains = '')
@@ -1924,7 +2021,7 @@ class AttributeEnum extends AttributeString
 		$aLocalizedValues = array();
 		foreach ($aRawValues as $sKey => $sValue)
 		{
-			$aLocalizedValues[$sKey] = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sKey, $sKey);
+			$aLocalizedValues[$sKey] = $this->GetValueLabel($sKey);
 		}
   		return $aLocalizedValues;
   	}
@@ -2466,6 +2563,8 @@ class AttributeExternalKey extends AttributeDBFieldVoid
  */
 class AttributeHierarchicalKey extends AttributeExternalKey
 {
+	protected $m_sTargetClass;
+
 	static protected function ListExpectedParams()
 	{
 		$aParams = parent::ListExpectedParams();
@@ -2482,6 +2581,18 @@ class AttributeHierarchicalKey extends AttributeExternalKey
 		return true;
 	}
 
+	/*
+	*  The target class is the class for which the attribute has been defined first
+	*/	
+	public function SetHostClass($sHostClass)
+	{
+		if (!isset($this->m_sTargetClass))
+		{
+			$this->m_sTargetClass = $sHostClass;
+		}
+		parent::SetHostClass($sHostClass);
+	}
+
 	public function IsHierarchicalKey() {return true;}
 	public function GetTargetClass($iType = EXTKEY_RELATIVE) {return $this->GetHostClass();}
 	public function GetKeyAttDef($iType = EXTKEY_RELATIVE){return $this;}

+ 18 - 24
core/metamodel.class.php

@@ -974,21 +974,13 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
 	{
 		$sStateAttrCode = self::GetStateAttributeCode($sClass);
 		$oAttDef = self::GetAttributeDef($sClass, $sStateAttrCode);
-		// Be consistent with what is done for enums, since states are defined as enums...
-		return Dict::S("Class:".$oAttDef->GetHostClass()."/Attribute:$sStateAttrCode/Value:$sStateValue");
-
-		// I've decided the current implementation, because I need
-		// to get the description as well -GetAllowedValues does not render the description,
-		// so far...
-		// Could have been implemented the following way (not tested
-		// $oStateAttrDef = self::GetAttributeDef($sClass, $sStateAttrCode);
-		// $aAllowedValues = $oStateAttrDef->GetAllowedValues();
-		// return $aAllowedValues[$sStateValue];
+		return $oAttDef->GetValueLabel($sStateValue);
 	}
 	public static function GetStateDescription($sClass, $sStateValue)
 	{
 		$sStateAttrCode = self::GetStateAttributeCode($sClass);
-		return Dict::S("Class:$sClass/Attribute:$sStateAttrCode/Value:$sStateValue+", '');
+		$oAttDef = self::GetAttributeDef($sClass, $sStateAttrCode);
+		return $oAttDef->GetValueDescription($sStateValue);
 	}
 
 	public static function EnumTransitions($sClass, $sStateCode)
@@ -1426,19 +1418,10 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
 				self::$m_aAttribOrigins[$sTargetClass] = array();
 			}
 			self::$m_aAttribDefs[$sTargetClass] = self::object_array_mergeclone(self::$m_aAttribDefs[$sTargetClass], self::$m_aAttribDefs[$sSourceClass]);
-			// Note: while investigating on some issues related to attribute inheritance,
-			//       I found out that the notion of "host class" is unclear
-			//       For stability reasons, and also because a workaround has been found
-			//       I leave it unchanged, but later it could be a good thing to force
-			//       attribute host class to the new class (See code below)
-			//       In that case, we will have to review the attribute labels
-			//       (currently relying on host class => the original declaration
-			//       of the attribute)
-			//       See TRAC #148
-			//       foreach(self::$m_aAttribDefs[$sTargetClass] as $sAttCode => $oAttDef)
-			//       {
-			//       	$oAttDef->SetHostClass($sTargetClass);
-			//       }
+			foreach(self::$m_aAttribDefs[$sTargetClass] as $sAttCode => $oAttDef)
+			{
+				$oAttDef->SetHostClass($sTargetClass);
+			}
 			self::$m_aAttribOrigins[$sTargetClass] = array_merge(self::$m_aAttribOrigins[$sTargetClass], self::$m_aAttribOrigins[$sSourceClass]);
 		}
 		// Build root class information
@@ -1678,6 +1661,17 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]))
 		self::_check_subclass($sClass);
 		return (self::GetRootClass($sClass) == $sClass);
 	}
+	public static function GetParentClass($sClass)
+	{
+		if (count(self::$m_aParentClasses[$sClass]) == 0)
+		{
+			return null;
+		}
+		else
+		{
+			return end(self::$m_aParentClasses[$sClass]);
+		}
+	}
 	/**
 	 * Tells if a class contains a hierarchical key, and if so what is its AttCode
 	 * @return mixed String = sAttCode or false if the class is not part of a hierarchy