diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php
index 49d10c506..f2178c641 100644
--- a/application/cmdbabstract.class.inc.php
+++ b/application/cmdbabstract.class.inc.php
@@ -1,5 +1,5 @@
$trash)
{
- $aDeps[$sAttCode] = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode);
+ $aDeps[$sAttCode] = MetaModel::GetPrerequisiteAttributes($sClass, $sAttCode);
}
$aList = $this->OrderDependentFields($aDeps);
@@ -3489,7 +3489,7 @@ EOF
$sFormPrefix = '2_';
foreach($aList as $sAttCode => $oAttDef)
{
- $aPrerequisites = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one
+ $aPrerequisites = MetaModel::GetPrerequisiteAttributes($sClass, $sAttCode); // List of attributes that are needed for the current one
if (count($aPrerequisites) > 0)
{
// When 'enabling' a field, all its prerequisites must be enabled too
diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php
index 7f53dea14..529c11c11 100644
--- a/core/attributedef.class.inc.php
+++ b/core/attributedef.class.inc.php
@@ -1,5 +1,5 @@
Get("allowed_values");}
- public function GetPrerequisiteAttributes() {return $this->Get("depends_on");}
+ public function GetPrerequisiteAttributes($sClass = null) {return $this->Get("depends_on");}
public function GetDefaultValue($aArgs = array())
{
// Note: so far, this feature is a prototype,
@@ -1274,7 +1274,7 @@ class AttributeDBFieldVoid extends AttributeDefinition
public function GetEditClass() {return "String";}
public function GetValuesDef() {return $this->Get("allowed_values");}
- public function GetPrerequisiteAttributes() {return $this->Get("depends_on");}
+ public function GetPrerequisiteAttributes($sClass = null) {return $this->Get("depends_on");}
public function IsDirectField() {return true;}
public function IsScalar() {return true;}
@@ -2992,6 +2992,120 @@ class AttributeEnum extends AttributeString
}
}
+/**
+ * A meta enum is an aggregation of enum from subclasses into an enum of a base class
+ * It has been designed is to cope with the fact that statuses must be defined in leaf classes, while it makes sense to
+ * have a superstatus available on the root classe(s)
+ *
+ * @package iTopORM
+ */
+class AttributeMetaEnum extends AttributeEnum
+{
+ static public function ListExpectedParams()
+ {
+ return array('allowed_values', 'sql', 'default_value', 'mapping');
+ }
+
+ public function IsWritable()
+ {
+ return false;
+ }
+
+ public function RequiresIndex()
+ {
+ return true;
+ }
+
+ public function GetPrerequisiteAttributes($sClass = null)
+ {
+ if (is_null($sClass))
+ {
+ $sClass = $this->GetHostClass();
+ }
+ $aMappingData = $this->GetMapRule($sClass);
+ if ($aMappingData == null)
+ {
+ $aRet = array();
+ }
+ else
+ {
+ $aRet = array($aMappingData['attcode']);
+ }
+ return $aRet;
+ }
+
+ /**
+ * Overload the standard so as to leave the data unsorted
+ *
+ * @param array $aArgs
+ * @param string $sContains
+ * @return array|null
+ */
+ public function GetAllowedValues($aArgs = array(), $sContains = '')
+ {
+ $oValSetDef = $this->GetValuesDef();
+ if (!$oValSetDef) return null;
+ $aRawValues = $oValSetDef->GetValueList();
+
+ if (is_null($aRawValues)) return null;
+ $aLocalizedValues = array();
+ foreach ($aRawValues as $sKey => $sValue)
+ {
+ $aLocalizedValues[$sKey] = Str::pure2html($this->GetValueLabel($sKey));
+ }
+ return $aLocalizedValues;
+ }
+
+ /**
+ * Returns the meta value for the given object.
+ * See also MetaModel::RebuildMetaEnums() that must be maintained when MapValue changes
+ *
+ * @param $oObject
+ * @return mixed
+ * @throws Exception
+ */
+ public function MapValue($oObject)
+ {
+ $aMappingData = $this->GetMapRule(get_class($oObject));
+ if ($aMappingData == null)
+ {
+ $sRet = $this->GetDefaultValue();
+ }
+ else
+ {
+ $sAttCode = $aMappingData['attcode'];
+ $value = $oObject->Get($sAttCode);
+ if (array_key_exists($value, $aMappingData['values']))
+ {
+ $sRet = $aMappingData['values'][$value];
+ }
+ elseif ($this->GetDefaultValue() != '')
+ {
+ $sRet = $this->GetDefaultValue();
+ }
+ else
+ {
+ throw new Exception('AttributeMetaEnum::MapValue(): mapping not found for value "'.$value.'" in '.get_class($oObject).', on attribute '.MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()).'::'.$this->GetCode());
+ }
+ }
+ return $sRet;
+ }
+
+ public function GetMapRule($sClass)
+ {
+ $aMappings = $this->Get('mapping');
+ if (array_key_exists($sClass, $aMappings))
+ {
+ $aMappingData = $aMappings[$sClass];
+ }
+ else
+ {
+ $sParent = MetaModel::GetParentClass($sClass);
+ $aMappingData = $this->GetMapRule($sParent);
+ }
+ return $aMappingData;
+ }
+}
/**
* Map a date+time column to an attribute
*
@@ -3794,7 +3908,7 @@ class AttributeExternalField extends AttributeDefinition
}
}
- public function GetPrerequisiteAttributes()
+ public function GetPrerequisiteAttributes($sClass = null)
{
return array($this->Get("extkey_attcode"));
}
@@ -4833,7 +4947,6 @@ class AttributeSubItem extends AttributeDefinition
public function GetEditClass() {return "";}
public function GetValuesDef() {return null;}
- //public function GetPrerequisiteAttributes() {return $this->Get("depends_on");}
public function IsDirectField() {return true;}
public function IsScalar() {return true;}
@@ -5322,7 +5435,7 @@ class AttributeComputedFieldVoid extends AttributeDefinition
public function GetEditClass() {return "";}
public function GetValuesDef() {return null;}
- public function GetPrerequisiteAttributes() {return $this->GetOptional("depends_on", array());}
+ public function GetPrerequisiteAttributes($sClass = null) {return $this->GetOptional("depends_on", array());}
public function IsDirectField() {return true;}
public function IsScalar() {return true;}
@@ -5546,7 +5659,7 @@ class AttributeRedundancySettings extends AttributeDBField
}
public function GetValuesDef() {return null;}
- public function GetPrerequisiteAttributes() {return array();}
+ public function GetPrerequisiteAttributes($sClass = null) {return array();}
public function GetEditClass() {return "RedundancySetting";}
protected function GetSQLCol($bFullSpec = false)
diff --git a/core/dbobject.class.php b/core/dbobject.class.php
index 50df3469c..1125ac131 100644
--- a/core/dbobject.class.php
+++ b/core/dbobject.class.php
@@ -1,5 +1,5 @@
m_aCurrValues[$sAttCode] = $realvalue;
$this->m_aTouchedAtt[$sAttCode] = true;
unset($this->m_aModifiedAtt[$sAttCode]);
-
+
+ foreach (MetaModel::ListMetaAttributes(get_class($this), $sAttCode) as $sMetaAttCode => $oMetaAttDef)
+ {
+ $this->Set($sMetaAttCode, $oMetaAttDef->MapValue($this));
+ }
+
// The object has changed, reset caches
$this->m_bCheckStatus = null;
diff --git a/core/metamodel.class.php b/core/metamodel.class.php
index 8aa9131d4..5567bd4a9 100644
--- a/core/metamodel.class.php
+++ b/core/metamodel.class.php
@@ -1,5 +1,5 @@
GetPrerequisiteAttributes();
}
/**
- * Find all attributes that depend on the specified one (reverse of GetPrequisiteAttributes)
+ * Find all attributes that depend on the specified one (reverse of GetPrerequisiteAttributes)
* @param string $sClass Name of the class
* @param string $sAttCode Code of the attributes
* @return Array List of attribute codes that depend on the given attribute, empty array if none.
@@ -510,7 +510,7 @@ abstract class MetaModel
self::_check_subclass($sClass);
foreach (self::ListAttributeDefs($sClass) as $sDependentAttCode=>$void)
{
- $aPrerequisites = self::GetPrequisiteAttributes($sClass, $sDependentAttCode);
+ $aPrerequisites = self::GetPrerequisiteAttributes($sClass, $sDependentAttCode);
if (in_array($sAttCode, $aPrerequisites))
{
$aResults[] = $sDependentAttCode;
@@ -633,7 +633,8 @@ abstract class MetaModel
private static $m_aAttribDefs = array(); // array of ("classname" => array of attributes)
private static $m_aAttribOrigins = array(); // array of ("classname" => array of ("attcode"=>"sourceclass"))
private static $m_aExtKeyFriends = array(); // array of ("classname" => array of ("indirect ext key attcode"=> array of ("relative ext field")))
- private static $m_aIgnoredAttributes = array(); //array of ("classname" => array of ("attcode")
+ private static $m_aIgnoredAttributes = array(); //array of ("classname" => array of ("attcode"))
+ private static $m_aEnumToMeta = array(); // array of ("classname" => array of ("attcode" => array of ("metaattcode" => oMetaAttDef))
final static public function ListAttributeDefs($sClass)
{
@@ -848,6 +849,18 @@ abstract class MetaModel
return self::$m_aTrackForwardCache[$sClass];
}
+ final static public function ListMetaAttributes($sClass, $sAttCode)
+ {
+ if (isset(self::$m_aEnumToMeta[$sClass][$sAttCode]))
+ {
+ $aRet = self::$m_aEnumToMeta[$sClass][$sAttCode];
+ }
+ else
+ {
+ $aRet = array();
+ }
+ return $aRet;
+ }
/**
* Get the attribute label
@@ -1847,6 +1860,15 @@ abstract class MetaModel
}
}
}
+ if ($oAttDef instanceof AttributeMetaEnum)
+ {
+ $aMappingData = $oAttDef->GetMapRule($sClass);
+ if ($aMappingData != null)
+ {
+ $sEnumAttCode = $aMappingData['attcode'];
+ self::$m_aEnumToMeta[$sClass][$sEnumAttCode][$sAttCode] = $oAttDef;
+ }
+ }
}
// Add a 'id' filter
@@ -2685,7 +2707,77 @@ abstract class MetaModel
CMDBSource::Query($sSQL);
}
}
-
+
+ /**
+ * Update the meta enums
+ * See Also AttributeMetaEnum::MapValue that must be aligned with the above implementation
+ *
+ * @param $bVerbose boolean Displays some information about what is done/what needs to be done
+ */
+ public static function RebuildMetaEnums($bVerbose = false)
+ {
+ foreach (self::GetClasses() as $sClass)
+ {
+ if (!self::HasTable($sClass)) continue;
+
+ foreach(self::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
+ {
+ // Check (once) all the attributes that are hierarchical keys
+ if((self::GetAttributeOrigin($sClass, $sAttCode) == $sClass) && $oAttDef instanceof AttributeEnum)
+ {
+ if (isset(self::$m_aEnumToMeta[$sClass][$sAttCode]))
+ {
+ foreach (self::$m_aEnumToMeta[$sClass][$sAttCode] as $sMetaAttCode => $oMetaAttDef)
+ {
+ $aMetaValues = array(); // array of (metavalue => array of values)
+ foreach ($oAttDef->GetAllowedValues() as $sCode => $sLabel)
+ {
+ $aMappingData = $oMetaAttDef->GetMapRule($sClass);
+ if ($aMappingData == null)
+ {
+ $sMetaValue = $oMetaAttDef->GetDefaultValue();
+ }
+ else
+ {
+ if (array_key_exists($sCode, $aMappingData['values']))
+ {
+ $sMetaValue = $aMappingData['values'][$sCode];
+ }
+ elseif ($oMetaAttDef->GetDefaultValue() != '')
+ {
+ $sMetaValue = $oMetaAttDef->GetDefaultValue();
+ }
+ else
+ {
+ throw new Exception('MetaModel::RebuildMetaEnums(): mapping not found for value "'.$sCode.'"" in '.$sClass.', on attribute '.self::GetAttributeOrigin($sClass, $oMetaAttDef->GetCode()).'::'.$oMetaAttDef->GetCode());
+ }
+ }
+ $aMetaValues[$sMetaValue][] = $sCode;
+ }
+ foreach ($aMetaValues as $sMetaValue => $aEnumValues)
+ {
+ $sMetaTable = self::DBGetTable($sClass, $sMetaAttCode);
+ $sEnumTable = self::DBGetTable($sClass);
+ $aColumns = array_keys($oMetaAttDef->GetSQLColumns());
+ $sMetaColumn = reset($aColumns);
+ $aColumns = array_keys($oAttDef->GetSQLColumns());
+ $sEnumColumn = reset($aColumns);
+ $sValueList = implode(', ', CMDBSource::Quote($aEnumValues));
+ $sSql = "UPDATE `$sMetaTable` JOIN `$sEnumTable` ON `$sEnumTable`.id = `$sMetaTable`.id SET `$sMetaTable`.`$sMetaColumn` = '$sMetaValue' WHERE `$sEnumTable`.`$sEnumColumn` IN ($sValueList) AND `$sMetaTable`.`$sMetaColumn` != '$sMetaValue'";
+ if ($bVerbose)
+ {
+ echo "Executing query: $sSql\n";
+ }
+ CMDBSource::Query($sSql);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
public static function CheckDataSources($bDiagnostics, $bVerbose)
{
$sOQL = 'SELECT SynchroDataSource';
@@ -4190,6 +4282,7 @@ abstract class MetaModel
self::$m_aStimuli = $result['m_aStimuli'];
self::$m_aTransitions = $result['m_aTransitions'];
self::$m_aHighlightScales = $result['m_aHighlightScales'];
+ self::$m_aEnumToMeta = $result['m_aEnumToMeta'];
}
$oKPI->ComputeAndReport('Metamodel APC (fetch + read)');
}
@@ -4227,6 +4320,7 @@ abstract class MetaModel
$aCache['m_aStimuli'] = self::$m_aStimuli; // array of ("classname" => array of ("stimuluscode"=>array('label'=>...)))
$aCache['m_aTransitions'] = self::$m_aTransitions; // array of ("classname" => array of ("statcode_from"=>array of ("stimuluscode" => array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD)))
$aCache['m_aHighlightScales'] = self::$m_aHighlightScales; // array of ("classname" => array of higlightcodes)))
+ $aCache['m_aEnumToMeta'] = self::$m_aEnumToMeta;
apc_store($sOqlAPCCacheId, $aCache);
$oKPI->ComputeAndReport('Metamodel APC (store)');
}
diff --git a/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml b/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml
index 54ed7d3ac..8d225e7fa 100755
--- a/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml
+++ b/datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml
@@ -1103,6 +1103,9 @@
-
30
+ -
+ 35
+
-
40
@@ -1179,6 +1182,9 @@
-
60
+ -
+ 65
+
-
70
@@ -1893,6 +1899,9 @@
-
30
+ -
+ 35
+
-
40
@@ -1969,6 +1978,9 @@
-
60
+ -
+ 65
+
-
70
@@ -2884,6 +2896,9 @@
-
30
+ -
+ 35
+
-
40
@@ -2963,6 +2978,9 @@
-
60
+ -
+ 65
+
-
70
@@ -3570,6 +3588,9 @@
-
30
+ -
+ 35
+
-
40
@@ -3652,6 +3673,9 @@
-
60
+ -
+ 65
+
-
70
@@ -4323,6 +4347,9 @@
-
30
+ -
+ 35
+
-
40
@@ -4402,6 +4429,9 @@
-
60
+ -
+ 65
+
-
70
diff --git a/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml b/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml
index 4f6830f9d..302870fe0 100755
--- a/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml
+++ b/datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml
@@ -664,6 +664,9 @@
-
40
+ -
+ 45
+
-
50
@@ -707,6 +710,9 @@
-
50
+ -
+ 55
+
-
60
diff --git a/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml b/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml
index 518c8167d..6e8448c0a 100755
--- a/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml
+++ b/datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml
@@ -1553,6 +1553,9 @@
-
90
+ -
+ 95
+
-
100
@@ -1614,6 +1617,9 @@
-
50
+ -
+ 55
+
-
60
diff --git a/datamodels/2.x/itop-problem-mgmt/datamodel.itop-problem-mgmt.xml b/datamodels/2.x/itop-problem-mgmt/datamodel.itop-problem-mgmt.xml
index daa76b917..293187964 100755
--- a/datamodels/2.x/itop-problem-mgmt/datamodel.itop-problem-mgmt.xml
+++ b/datamodels/2.x/itop-problem-mgmt/datamodel.itop-problem-mgmt.xml
@@ -607,6 +607,9 @@
-
50
+ -
+ 55
+
-
60
@@ -653,6 +656,9 @@
-
40
+ -
+ 45
+
-
50
diff --git a/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml b/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml
index e542f87c8..6fb81e76d 100755
--- a/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml
+++ b/datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml
@@ -1615,6 +1615,9 @@
-
90
+ -
+ 95
+
-
100
@@ -1679,6 +1682,9 @@
-
50
+ -
+ 55
+
-
60
diff --git a/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml b/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml
index 9916b3c6d..76aa59c32 100755
--- a/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml
+++ b/datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml
@@ -1615,6 +1615,9 @@
-
90
+ -
+ 95
+
-
100
@@ -1679,6 +1682,9 @@
-
50
+ -
+ 55
+
-
60
diff --git a/datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml b/datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml
index 4456ca5fa..277591027 100755
--- a/datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml
+++ b/datamodels/2.x/itop-tickets/datamodel.itop-tickets.xml
@@ -1,5 +1,5 @@
-
+
service_id AND sc.org_id = :this->org_id AND slt.request_type = :request_type AND slt.priority = :this->priority]]>
@@ -45,6 +45,28 @@
+
+
+ active
+ inactive
+
+ operational_status
+ active
+
+
+ status
+
+
+
+
+
+
+
+
+
+
+
+
ref
@@ -238,6 +260,9 @@
-
70
+ -
+ 75
+
-
80
@@ -275,6 +300,9 @@
-
30
+ -
+ 35
+
-
40
@@ -309,6 +337,9 @@
-
60
+ -
+ 65
+
-
70
diff --git a/datamodels/2.x/itop-tickets/en.dict.itop-tickets.php b/datamodels/2.x/itop-tickets/en.dict.itop-tickets.php
index 6888d212c..169e79153 100755
--- a/datamodels/2.x/itop-tickets/en.dict.itop-tickets.php
+++ b/datamodels/2.x/itop-tickets/en.dict.itop-tickets.php
@@ -82,6 +82,12 @@ Dict::Add('EN US', 'English', 'English', array(
'Class:Ticket/Attribute:workorders_list+' => 'All the work orders for this ticket',
'Class:Ticket/Attribute:finalclass' => 'Type',
'Class:Ticket/Attribute:finalclass+' => '',
+ 'Class:Ticket/Attribute:operational_status' => 'Operational status',
+ 'Class:Ticket/Attribute:operational_status+' => 'Computed after the detailed status',
+ 'Class:Ticket/Attribute:operational_status/Value:active' => 'Active',
+ 'Class:Ticket/Attribute:operational_status/Value:active+' => 'Work in progress',
+ 'Class:Ticket/Attribute:operational_status/Value:inactive' => 'Inactive',
+ 'Class:Ticket/Attribute:operational_status/Value:inactive+' => 'Done',
'Ticket:ImpactAnalysis' => 'Impact Analysis',
));
diff --git a/datamodels/2.x/itop-tickets/fr.dict.itop-tickets.php b/datamodels/2.x/itop-tickets/fr.dict.itop-tickets.php
index 893d8ab32..23c5b68f3 100755
--- a/datamodels/2.x/itop-tickets/fr.dict.itop-tickets.php
+++ b/datamodels/2.x/itop-tickets/fr.dict.itop-tickets.php
@@ -69,6 +69,12 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Class:Ticket/Attribute:workorders_list+' => '',
'Class:Ticket/Attribute:finalclass' => 'Type',
'Class:Ticket/Attribute:finalclass+' => '',
+ 'Class:Ticket/Attribute:operational_status' => 'Statut opérationnel',
+ 'Class:Ticket/Attribute:operational_status+' => 'Calculé à partir du statut détaillé',
+ 'Class:Ticket/Attribute:operational_status/Value:active' => 'Actif',
+ 'Class:Ticket/Attribute:operational_status/Value:active+' => 'Traitement en cours',
+ 'Class:Ticket/Attribute:operational_status/Value:inactive' => 'Inactif',
+ 'Class:Ticket/Attribute:operational_status/Value:inactive+' => 'Ticket définitivement fermé',
'Ticket:ImpactAnalysis' => 'Analyse d\'Impact',
));
diff --git a/pages/UI.php b/pages/UI.php
index 1821b9aa3..e0e42b6ef 100644
--- a/pages/UI.php
+++ b/pages/UI.php
@@ -1,5 +1,5 @@
0)
{
// When 'enabling' a field, all its prerequisites must be enabled too
diff --git a/setup/compiler.class.inc.php b/setup/compiler.class.inc.php
index 869b46672..b75700d54 100644
--- a/setup/compiler.class.inc.php
+++ b/setup/compiler.class.inc.php
@@ -1,5 +1,5 @@
GetPropString($oField, 'display_style', 'list');
$aParameters['sql'] = $this->GetMandatoryPropString($oField, 'sql', '');
$aParameters['default_value'] = $this->GetPropString($oField, 'default_value', '');
- $aParameters['is_null_allowed'] = $this->GetPropBoolean($oField, 'is_null_allowed', false);
- $aParameters['depends_on'] = $sDependencies;
$oMappings = $oField->GetUniqueElement('mappings');
$oMappingNodes = $oMappings->getElementsByTagName('mapping');
diff --git a/setup/itopdesignformat.class.inc.php b/setup/itopdesignformat.class.inc.php
index b1b824e3c..4e0fb002e 100644
--- a/setup/itopdesignformat.class.inc.php
+++ b/setup/itopdesignformat.class.inc.php
@@ -1,5 +1,5 @@
LogWarning('The module design defined in '.self::GetItopNodePath($oNode).' will be lost.');
$this->DeleteNode($oNode);
}
+
+ // Remove MetaEnum attributes
+ //
+ $oNodeList = $oXPath->query("/itop_design/classes//class/fields/field[@xsi:type='AttributeMetaEnum']");
+ foreach ($oNodeList as $oNode)
+ {
+ $this->LogWarning('The attribute '.self::GetItopNodePath($oNode).' is irrelevant and must be removed.');
+ $this->DeleteNode($oNode);
+ }
}
/**