diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 4661bf3f12..5cc512fd31 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -43,37 +43,37 @@ define('ENUM_PARENT_CLASSES_EXCLUDELEAF', 1); define('ENUM_PARENT_CLASSES_ALL', 2); /** - * Specifies that this attribute is visible/editable.... normal (default config) + * Specifies that this attribute is visible/editable.... normal (default config) * * @package iTopORM */ define('OPT_ATT_NORMAL', 0); /** - * Specifies that this attribute is hidden in that state + * Specifies that this attribute is hidden in that state * * @package iTopORM */ define('OPT_ATT_HIDDEN', 1); /** - * Specifies that this attribute is not editable in that state + * Specifies that this attribute is not editable in that state * * @package iTopORM */ define('OPT_ATT_READONLY', 2); /** - * Specifieds that the attribute must be set (different than default value?) when arriving into that state + * Specifieds that the attribute must be set (different than default value?) when arriving into that state * * @package iTopORM */ define('OPT_ATT_MANDATORY', 4); /** - * Specifies that the attribute must change when arriving into that state + * Specifies that the attribute must change when arriving into that state * * @package iTopORM */ define('OPT_ATT_MUSTCHANGE', 8); /** - * Specifies that the attribute must be proposed when arriving into that state + * Specifies that the attribute must be proposed when arriving into that state * * @package iTopORM */ @@ -87,7 +87,7 @@ define('OPT_ATT_MUSTPROMPT', 16); define('OPT_ATT_SLAVE', 32); /** - * DB Engine -should be moved into CMDBSource + * DB Engine -should be moved into CMDBSource * * @package iTopORM */ @@ -95,9 +95,8 @@ define('MYSQL_ENGINE', 'innodb'); //define('MYSQL_ENGINE', 'myisam'); - /** - * (API) The objects definitions as well as their mapping to the database + * (API) The objects definitions as well as their mapping to the database * * @package iTopORM */ @@ -169,7 +168,7 @@ abstract class MetaModel private static $m_bSkipCheckExtKeys = false; private static $m_bUseAPCCache = false; - + private static $m_bLogIssue = false; private static $m_bLogNotification = false; private static $m_bLogWebService = false; @@ -188,10 +187,12 @@ abstract class MetaModel { return self::$m_bLogIssue; } + public static function IsLogEnabledNotification() { return self::$m_bLogNotification; } + public static function IsLogEnabledWebService() { return self::$m_bLogWebService; @@ -210,9 +211,15 @@ abstract class MetaModel static public function GetParentPersistentClass($sRefClass) { $sClass = get_parent_class($sRefClass); - if (!$sClass) return ''; + if (!$sClass) + { + return ''; + } - if ($sClass == 'DBObject') return ''; // Warning: __CLASS__ is lower case in my version of PHP + if ($sClass == 'DBObject') + { + return ''; + } // Warning: __CLASS__ is lower case in my version of PHP // Note: the UI/business model may implement pure PHP classes (intermediate layers) if (array_key_exists($sClass, self::$m_aClassParams)) @@ -228,6 +235,7 @@ abstract class MetaModel $sStringCode = 'Class:'.$sClass; return Dict::S($sStringCode, str_replace('_', ' ', $sClass)); } + final static public function GetName_Obsolete($sClass) { // Written for compatibility with a data model written prior to version 0.9.1 @@ -241,6 +249,7 @@ abstract class MetaModel return self::GetName($sClass); } } + final static public function GetClassFromLabel($sClassLabel, $bCaseSensitive = true) { foreach(self::GetClasses() as $sClass) @@ -257,7 +266,7 @@ abstract class MetaModel if (strcasecmp(self::GetName($sClass), $sClassLabel) == 0) { return $sClass; - } + } } } return null; @@ -265,20 +274,23 @@ abstract class MetaModel final static public function GetCategory($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return self::$m_aClassParams[$sClass]["category"]; } + final static public function HasCategory($sClass, $sCategory) { - self::_check_subclass($sClass); - return (strpos(self::$m_aClassParams[$sClass]["category"], $sCategory) !== false); + self::_check_subclass($sClass); + return (strpos(self::$m_aClassParams[$sClass]["category"], $sCategory) !== false); } + final static public function GetClassDescription($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); $sStringCode = 'Class:'.$sClass.'+'; return Dict::S($sStringCode, ''); } + final static public function GetClassDescription_Obsolete($sClass) { // Written for compatibility with a data model written prior to version 0.9.1 @@ -292,6 +304,7 @@ abstract class MetaModel return self::GetClassDescription($sClass); } } + final static public function GetClassIcon($sClass, $bImgTag = true, $sMoreStyles = '') { self::_check_subclass($sClass); @@ -316,21 +329,25 @@ abstract class MetaModel } return $sIcon; } + final static public function IsAutoIncrementKey($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return (self::$m_aClassParams[$sClass]["key_type"] == "autoincrement"); } + final static public function IsArchivable($sClass) { self::_check_subclass($sClass); return self::$m_aClassParams[$sClass]["archive"]; } + final static public function IsObsoletable($sClass) { self::_check_subclass($sClass); return (!is_null(self::$m_aClassParams[$sClass]['obsolescence_expression'])); } + final static public function GetObsolescenceExpression($sClass) { if (self::IsObsoletable($sClass)) @@ -345,6 +362,7 @@ abstract class MetaModel } return $oRet; } + final static public function GetNameSpec($sClass) { self::_check_subclass($sClass); @@ -355,10 +373,10 @@ abstract class MetaModel if (strlen($sFormat) == 0) { // Default to "%1$s %2$s..." - for($i = 1 ; $i <= count($nameRawSpec) ; $i++) + for($i = 1; $i <= count($nameRawSpec); $i++) { if (empty($sFormat)) - { + { $sFormat .= '%'.$i.'$s'; } else @@ -383,12 +401,12 @@ abstract class MetaModel /** * Get the friendly name expression for a given class - */ + */ final static public function GetNameExpression($sClass) { $aNameSpec = self::GetNameSpec($sClass); $sFormat = $aNameSpec[0]; - $aAttributes = $aNameSpec[1]; + $aAttributes = $aNameSpec[1]; $aPieces = preg_split('/%([0-9])\\$s/', $sFormat, -1, PREG_SPLIT_DELIM_CAPTURE); $aExpressions = array(); @@ -412,7 +430,7 @@ abstract class MetaModel // if (strlen($sPiece) > 0) { - $aExpressions[] = new ScalarExpression($sPiece); + $aExpressions[] = new ScalarExpression($sPiece); } } } @@ -422,13 +440,13 @@ abstract class MetaModel } /** - * Returns the friendly name IIF it is equivalent to a single attribute - */ + * Returns the friendly name IIF it is equivalent to a single attribute + */ final static public function GetFriendlyNameAttributeCode($sClass) { $aNameSpec = self::GetNameSpec($sClass); $sFormat = trim($aNameSpec[0]); - $aAttributes = $aNameSpec[1]; + $aAttributes = $aNameSpec[1]; if (($sFormat != '') && ($sFormat != '%1$s')) { return null; @@ -442,9 +460,10 @@ abstract class MetaModel final static public function GetStateAttributeCode($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return self::$m_aClassParams[$sClass]["state_attcode"]; } + final static public function GetDefaultState($sClass) { $sDefaultState = ''; @@ -456,21 +475,23 @@ abstract class MetaModel } return $sDefaultState; } + final static public function GetReconcKeys($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return self::$m_aClassParams[$sClass]["reconc_keys"]; } + final static public function GetDisplayTemplate($sClass) { - self::_check_subclass($sClass); - return array_key_exists("display_template", self::$m_aClassParams[$sClass]) ? self::$m_aClassParams[$sClass]["display_template"]: ''; + self::_check_subclass($sClass); + return array_key_exists("display_template", self::$m_aClassParams[$sClass]) ? self::$m_aClassParams[$sClass]["display_template"] : ''; } final static public function GetOrderByDefault($sClass, $bOnlyDeclared = false) { - self::_check_subclass($sClass); - $aOrderBy = array_key_exists("order_by_default", self::$m_aClassParams[$sClass]) ? self::$m_aClassParams[$sClass]["order_by_default"]: array(); + self::_check_subclass($sClass); + $aOrderBy = array_key_exists("order_by_default", self::$m_aClassParams[$sClass]) ? self::$m_aClassParams[$sClass]["order_by_default"] : array(); if ($bOnlyDeclared) { // Used to reverse engineer the declaration of the data model @@ -491,6 +512,7 @@ abstract class MetaModel self::_check_subclass($sClass); return self::$m_aAttribOrigins[$sClass][$sAttCode]; } + final static public function GetPrerequisiteAttributes($sClass, $sAttCode) { self::_check_subclass($sClass); @@ -498,10 +520,11 @@ abstract class MetaModel // Temporary implementation: later, we might be able to compute // the dependencies, based on the attributes definition // (allowed values and default values) - + // Even non-writable attributes (like ExternalFields) can now have Prerequisites return $oAtt->GetPrerequisiteAttributes(); } + /** * Find all attributes that depend on the specified one (reverse of GetPrerequisiteAttributes) * @param string $sClass Name of the class @@ -512,7 +535,7 @@ abstract class MetaModel { $aResults = array(); self::_check_subclass($sClass); - foreach (self::ListAttributeDefs($sClass) as $sDependentAttCode=>$void) + foreach(self::ListAttributeDefs($sClass) as $sDependentAttCode => $void) { $aPrerequisites = self::GetPrerequisiteAttributes($sClass, $sDependentAttCode); if (in_array($sAttCode, $aPrerequisites)) @@ -522,6 +545,7 @@ abstract class MetaModel } return $aResults; } + // #@# restore to private ? final static public function DBGetTable($sClass, $sAttCode = null) { @@ -555,9 +579,12 @@ abstract class MetaModel // the list of existing tables // Rather, it uses the list of expected tables, corresponding to the data model $aTables = array(); - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { - if (!self::HasTable($sClass)) continue; + if (!self::HasTable($sClass)) + { + continue; + } $sTable = self::DBGetTable($sClass); // Could be completed later with all the classes that are using a given table @@ -568,7 +595,7 @@ abstract class MetaModel $aTables[$sTable][] = $sClass; } return $aTables; - } + } final static public function DBGetIndexes($sClass) { @@ -586,14 +613,16 @@ abstract class MetaModel final static public function DBGetKey($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return self::$m_aClassParams[$sClass]["db_key_field"]; } + final static public function DBGetClassField($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return self::$m_aClassParams[$sClass]["db_finalclass_field"]; } + final static public function IsStandaloneClass($sClass) { self::_check_subclass($sClass); @@ -607,27 +636,45 @@ abstract class MetaModel } return false; } + final static public function IsParentClass($sParentClass, $sChildClass) { self::_check_subclass($sChildClass); self::_check_subclass($sParentClass); - if (in_array($sParentClass, self::$m_aParentClasses[$sChildClass])) return true; - if ($sChildClass == $sParentClass) return true; + if (in_array($sParentClass, self::$m_aParentClasses[$sChildClass])) + { + return true; + } + if ($sChildClass == $sParentClass) + { + return true; + } return false; } + final static public function IsSameFamilyBranch($sClassA, $sClassB) { - self::_check_subclass($sClassA); - self::_check_subclass($sClassB); - if (in_array($sClassA, self::$m_aParentClasses[$sClassB])) return true; - if (in_array($sClassB, self::$m_aParentClasses[$sClassA])) return true; - if ($sClassA == $sClassB) return true; + self::_check_subclass($sClassA); + self::_check_subclass($sClassB); + if (in_array($sClassA, self::$m_aParentClasses[$sClassB])) + { + return true; + } + if (in_array($sClassB, self::$m_aParentClasses[$sClassA])) + { + return true; + } + if ($sClassA == $sClassB) + { + return true; + } return false; } + final static public function IsSameFamily($sClassA, $sClassB) { - self::_check_subclass($sClassA); - self::_check_subclass($sClassB); + self::_check_subclass($sClassA); + self::_check_subclass($sClassB); return (self::GetRootClass($sClassA) == self::GetRootClass($sClassB)); } @@ -646,19 +693,19 @@ abstract class MetaModel */ final static public function ListAttributeDefs($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return self::$m_aAttribDefs[$sClass]; } final public static function GetAttributesList($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return array_keys(self::$m_aAttribDefs[$sClass]); } final public static function GetFiltersList($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return array_keys(self::$m_aFilterDefs[$sClass]); } @@ -672,19 +719,29 @@ abstract class MetaModel { $aExtKeys[] = $sAttCode; } - } + } return $aExtKeys; } - + final static public function IsValidKeyAttCode($sClass, $sAttCode) { - if (!array_key_exists($sClass, self::$m_aAttribDefs)) return false; - if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) return false; + if (!array_key_exists($sClass, self::$m_aAttribDefs)) + { + return false; + } + if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) + { + return false; + } return (self::$m_aAttribDefs[$sClass][$sAttCode]->IsExternalKey()); } + final static public function IsValidAttCode($sClass, $sAttCode, $bExtended = false) { - if (!array_key_exists($sClass, self::$m_aAttribDefs)) return false; + if (!array_key_exists($sClass, self::$m_aAttribDefs)) + { + return false; + } if ($bExtended) { @@ -712,9 +769,10 @@ abstract class MetaModel { $bRes = array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]); } - + return $bRes; } + final static public function IsAttributeOrigin($sClass, $sAttCode) { return (self::$m_aAttribOrigins[$sClass][$sAttCode] == $sClass); @@ -722,9 +780,13 @@ abstract class MetaModel final static public function IsValidFilterCode($sClass, $sFilterCode) { - if (!array_key_exists($sClass, self::$m_aFilterDefs)) return false; + if (!array_key_exists($sClass, self::$m_aFilterDefs)) + { + return false; + } return (array_key_exists($sFilterCode, self::$m_aFilterDefs[$sClass])); } + public static function IsValidClass($sClass) { return (array_key_exists($sClass, self::$m_aAttribDefs)); @@ -732,7 +794,10 @@ abstract class MetaModel public static function IsValidObject($oObject) { - if (!is_object($oObject)) return false; + if (!is_object($oObject)) + { + return false; + } return (self::IsValidClass(get_class($oObject))); } @@ -741,14 +806,14 @@ abstract class MetaModel return (in_array($sAttCode, self::GetReconcKeys($sClass))); } - /** - * Returns the AttributeDefinition of the $sAttCode attribute of the $sClass class - * - * @param string $sClass Class name - * @param string $sAttCode Attribute code - * @return AttributeDefinition - * @throws Exception - */ + /** + * Returns the AttributeDefinition of the $sAttCode attribute of the $sClass class + * + * @param string $sClass Class name + * @param string $sAttCode Attribute code + * @return AttributeDefinition + * @throws Exception + */ final static public function GetAttributeDef($sClass, $sAttCode) { self::_check_subclass($sClass); @@ -773,7 +838,7 @@ abstract class MetaModel final static public function GetExternalKeys($sClass) { $aExtKeys = array(); - foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) + foreach(self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) { if ($oAtt->IsExternalKey()) { @@ -786,7 +851,7 @@ abstract class MetaModel final static public function GetLinkedSets($sClass) { $aLinkedSets = array(); - foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) + foreach(self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) { if (is_subclass_of($oAtt, 'AttributeLinkedSet')) { @@ -802,7 +867,7 @@ abstract class MetaModel if (!isset($aExtFields[$sClass][$sKeyAttCode])) { $aExtFields[$sClass][$sKeyAttCode] = array(); - foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) + foreach(self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) { if ($oAtt->IsExternalField() && ($oAtt->GetKeyAttCode() == $sKeyAttCode)) { @@ -827,24 +892,34 @@ abstract class MetaModel } protected static $m_aTrackForwardCache = array(); + /** * List external keys for which there is a LinkSet (direct or indirect) on the other end * For those external keys, a change will have a special meaning on the other end - * in term of change tracking - */ + * in term of change tracking + */ final static public function GetTrackForwardExternalKeys($sClass) { if (!isset(self::$m_aTrackForwardCache[$sClass])) { $aRes = array(); - foreach (MetaModel::GetExternalKeys($sClass) as $sAttCode => $oAttDef) + foreach(MetaModel::GetExternalKeys($sClass) as $sAttCode => $oAttDef) { $sRemoteClass = $oAttDef->GetTargetClass(); - foreach (MetaModel::ListAttributeDefs($sRemoteClass) as $sRemoteAttCode => $oRemoteAttDef) + foreach(MetaModel::ListAttributeDefs($sRemoteClass) as $sRemoteAttCode => $oRemoteAttDef) { - if (!$oRemoteAttDef->IsLinkSet()) continue; - if (!is_subclass_of($sClass, $oRemoteAttDef->GetLinkedClass()) && $oRemoteAttDef->GetLinkedClass() != $sClass) continue; - if ($oRemoteAttDef->GetExtKeyToMe() != $sAttCode) continue; + if (!$oRemoteAttDef->IsLinkSet()) + { + continue; + } + if (!is_subclass_of($sClass, $oRemoteAttDef->GetLinkedClass()) && $oRemoteAttDef->GetLinkedClass() != $sClass) + { + continue; + } + if ($oRemoteAttDef->GetExtKeyToMe() != $sAttCode) + { + continue; + } $aRes[$sAttCode] = $oRemoteAttDef; } } @@ -868,11 +943,11 @@ abstract class MetaModel /** * Get the attribute label - * @param string sClass Persistent class - * @param string sAttCodeEx Extended attribute code: attcode[->attcode] + * @param string sClass Persistent class + * @param string sAttCodeEx Extended attribute code: attcode[->attcode] * @param bool $bShowMandatory If true, add a star character (at the end or before the ->) to show that the field is mandatory * @return string A user friendly format of the string: AttributeName or AttributeName->ExtAttributeName - */ + */ public static function GetLabel($sClass, $sAttCodeEx, $bShowMandatory = false) { $sLabel = ''; @@ -904,7 +979,10 @@ abstract class MetaModel public static function GetDescription($sClass, $sAttCode) { $oAttDef = self::GetAttributeDef($sClass, $sAttCode); - if ($oAttDef) return $oAttDef->GetDescription(); + if ($oAttDef) + { + return $oAttDef->GetDescription(); + } return ""; } @@ -917,7 +995,7 @@ abstract class MetaModel public static function GetClassFilterDefs($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); return self::$m_aFilterDefs[$sClass]; } @@ -934,14 +1012,20 @@ abstract class MetaModel public static function GetFilterLabel($sClass, $sFilterCode) { $oFilter = self::GetClassFilterDef($sClass, $sFilterCode); - if ($oFilter) return $oFilter->GetLabel(); + if ($oFilter) + { + return $oFilter->GetLabel(); + } return ""; } public static function GetFilterDescription($sClass, $sFilterCode) { $oFilter = self::GetClassFilterDef($sClass, $sFilterCode); - if ($oFilter) return $oFilter->GetDescription(); + if ($oFilter) + { + return $oFilter->GetDescription(); + } return ""; } @@ -949,7 +1033,10 @@ abstract class MetaModel public static function GetFilterOperators($sClass, $sFilterCode) { $oFilter = self::GetClassFilterDef($sClass, $sFilterCode); - if ($oFilter) return $oFilter->GetOperators(); + if ($oFilter) + { + return $oFilter->GetOperators(); + } return array(); } @@ -957,14 +1044,20 @@ abstract class MetaModel public static function GetFilterLooseOperator($sClass, $sFilterCode) { $oFilter = self::GetClassFilterDef($sClass, $sFilterCode); - if ($oFilter) return $oFilter->GetLooseOperator(); + if ($oFilter) + { + return $oFilter->GetLooseOperator(); + } return array(); } public static function GetFilterOpDescription($sClass, $sFilterCode, $sOpCode) { $oFilter = self::GetClassFilterDef($sClass, $sFilterCode); - if ($oFilter) return $oFilter->GetOpDescription($sOpCode); + if ($oFilter) + { + return $oFilter->GetOpDescription($sOpCode); + } return ""; } @@ -1000,7 +1093,10 @@ abstract class MetaModel } } $sParentClass = self::GetParentPersistentClass($sClass); - if (empty($sParentClass)) return array(); // nothing for the mother of all classes + if (empty($sParentClass)) + { + return array(); + } // nothing for the mother of all classes // Dig recursively return self::GetZListItems($sParentClass, $sListCode); } @@ -1034,7 +1130,7 @@ abstract class MetaModel // for the specified class $aClassRelations = array(); foreach($aResult as $sRelCode) - { + { $aQueriesDown = self::EnumRelationQueries($sClass, $sRelCode); if (count($aQueriesDown) > 0) { @@ -1053,7 +1149,7 @@ abstract class MetaModel } } - return $aClassRelations; + return $aClassRelations; } // Temporary patch: until the impact analysis GUI gets rewritten, @@ -1080,17 +1176,17 @@ abstract class MetaModel { $aClassRelations[$sRelCode]['down'] = self::GetRelationLabel($sRelCode, true); } - + $aQueriesUp = self::EnumRelationQueries($sClass, $sRelCode, false /* Up */); if (count($aQueriesUp) > 0) { $aClassRelations[$sRelCode]['up'] = self::GetRelationLabel($sRelCode, false); } } - + return $aClassRelations; } - + final static public function GetRelationDescription($sRelCode) { return Dict::S("Relation:$sRelCode/Description"); @@ -1100,11 +1196,11 @@ abstract class MetaModel { if ($bDown) { - // The legacy convention is confusing with regard to the way we have conceptualized the relations: - // In the former representation, the main stream was named after "up" - // Now, the relation from A to B says that something is transmitted from A to B, thus going DOWNstream as described in a petri net. - $sKey = "Relation:$sRelCode/DownStream"; - $sLegacy = Dict::S("Relation:$sRelCode/VerbUp", $sKey); + // The legacy convention is confusing with regard to the way we have conceptualized the relations: + // In the former representation, the main stream was named after "up" + // Now, the relation from A to B says that something is transmitted from A to B, thus going DOWNstream as described in a petri net. + $sKey = "Relation:$sRelCode/DownStream"; + $sLegacy = Dict::S("Relation:$sRelCode/VerbUp", $sKey); } else { @@ -1119,7 +1215,7 @@ abstract class MetaModel { $bHasLegacy = false; $aQueries = array(); - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { $aQueries[$sClass]['down'] = array(); if (!array_key_exists('up', $aQueries[$sClass])) @@ -1128,7 +1224,7 @@ abstract class MetaModel } $aNeighboursDown = call_user_func_array(array($sClass, 'GetRelationQueriesEx'), array($sRelCode)); - + // Translate attributes into queries (new style of spec only) foreach($aNeighboursDown as $sNeighbourId => $aNeighbourData) { @@ -1154,7 +1250,7 @@ abstract class MetaModel $sExtKeyToRemote = $oAttDef->GetExtKeyToRemote(); $oRemoteAttDef = self::GetAttributeDef($sLinkedClass, $sExtKeyToRemote); $sRemoteClass = $oRemoteAttDef->GetTargetClass(); - + $aNeighbourData['sToClass'] = $sRemoteClass; $aNeighbourData['sQueryDown'] = "SELECT $sRemoteClass AS o JOIN $sLinkedClass AS lnk ON lnk.$sExtKeyToRemote = o.id WHERE lnk.$sExtKeyToMe = :this->id"; $aNeighbourData['sQueryUp'] = "SELECT ".$aNeighbourData['sFromClass']." AS o JOIN $sLinkedClass AS lnk ON lnk.$sExtKeyToMe = o.id WHERE lnk.$sExtKeyToRemote = :this->id"; @@ -1197,7 +1293,7 @@ abstract class MetaModel { $sFromClass = $aNeighbourData['sFromClass']; $sToClass = $aNeighbourData['sToClass']; - foreach (self::EnumChildClasses($sToClass, ENUM_CHILD_CLASSES_ALL) as $sSubClass) + foreach(self::EnumChildClasses($sToClass, ENUM_CHILD_CLASSES_ALL) as $sSubClass) { $aQueries[$sSubClass]['up'][$sArrowId] = $aNeighbourData; } @@ -1221,15 +1317,18 @@ abstract class MetaModel foreach($aLegacy as $sId => $aLegacyEntry) { $bHasLegacy = true; - + $oFilter = DBObjectSearch::FromOQL($aLegacyEntry['sQuery']); $sRemoteClass = $oFilter->GetClass(); // Determine wether the query is inherited from a parent or not $bInherited = false; - foreach (self::EnumParentClasses($sClass) as $sParent) + foreach(self::EnumParentClasses($sClass) as $sParent) { - if (!isset($aQueries[$sParent]['down'][$sRemoteClass])) continue; + if (!isset($aQueries[$sParent]['down'][$sRemoteClass])) + { + continue; + } if ($aLegacyEntry['sQuery'] == $aQueries[$sParent]['down'][$sRemoteClass]['sQueryDown']) { $bInherited = true; @@ -1263,9 +1362,12 @@ abstract class MetaModel // Determine wether the query is inherited from a parent or not $bInherited = false; - foreach (self::EnumParentClasses($sClass) as $sParent) + foreach(self::EnumParentClasses($sClass) as $sParent) { - if (!isset($aQueries[$sParent]['up'][$sRemoteClass])) continue; + if (!isset($aQueries[$sParent]['up'][$sRemoteClass])) + { + continue; + } if ($aLegacyEntry['sQuery'] == $aQueries[$sParent]['up'][$sRemoteClass]['sQueryUp']) { $bInherited = true; @@ -1298,21 +1400,24 @@ abstract class MetaModel // Perform the up/down reconciliation for the legacy definitions if ($bHasLegacy) { - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { // Foreach "up" legacy query, update its "down" counterpart if (isset($aQueries[$sClass]['up'])) { - foreach ($aQueries[$sClass]['up'] as $sNeighbourId => $aNeighbourData) + foreach($aQueries[$sClass]['up'] as $sNeighbourId => $aNeighbourData) { if (!array_key_exists('_legacy_', $aNeighbourData)) { continue; } - if (!$aNeighbourData['_legacy_']) continue; // Skip modern definitions + if (!$aNeighbourData['_legacy_']) + { + continue; + } // Skip modern definitions $sLocalClass = $aNeighbourData['sToClass']; - foreach (self::EnumChildClasses($aNeighbourData['sFromClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass) + foreach(self::EnumChildClasses($aNeighbourData['sFromClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass) { if (isset($aQueries[$sRemoteClass]['down'][$sLocalClass])) { @@ -1328,12 +1433,15 @@ abstract class MetaModel } } // Foreach "down" legacy query, update its "up" counterpart (if any) - foreach ($aQueries[$sClass]['down'] as $sNeighbourId => $aNeighbourData) + foreach($aQueries[$sClass]['down'] as $sNeighbourId => $aNeighbourData) { - if (!$aNeighbourData['_legacy_']) continue; // Skip modern definitions + if (!$aNeighbourData['_legacy_']) + { + continue; + } // Skip modern definitions $sLocalClass = $aNeighbourData['sFromClass']; - foreach (self::EnumChildClasses($aNeighbourData['sToClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass) + foreach(self::EnumChildClasses($aNeighbourData['sToClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass) { if (isset($aQueries[$sRemoteClass]['up'][$sLocalClass])) { @@ -1366,19 +1474,19 @@ abstract class MetaModel /** * Compute the "RelatedObjects" for a whole set of DBObjects - * + * * @param string $sRelCode The code of the relation to use for the computation * @param array $asourceObjects The objects to start with * @param int $iMaxDepth * @param boolean $bEnableReduncancy * @param array $aUnreachable Array of objects to be considered as 'unreachable' - * + * * @return RelationGraph The graph of all the related objects */ static public function GetRelatedObjectsDown($sRelCode, $aSourceObjects, $iMaxDepth = 99, $bEnableRedundancy = true, $aUnreachable = array(), $aContexts = array()) { $oGraph = new RelationGraph(); - foreach ($aSourceObjects as $oObject) + foreach($aSourceObjects as $oObject) { $oGraph->AddSourceObject($oObject); } @@ -1392,18 +1500,18 @@ abstract class MetaModel /** * Compute the "RelatedObjects" in the reverse way - * + * * @param string $sRelCode The code of the relation to use for the computation * @param array $asourceObjects The objects to start with * @param int $iMaxDepth * @param boolean $bEnableReduncancy - * + * * @return RelationGraph The graph of all the related objects */ static public function GetRelatedObjectsUp($sRelCode, $aSourceObjects, $iMaxDepth = 99, $bEnableRedundancy = true, $aContexts = array()) { $oGraph = new RelationGraph(); - foreach ($aSourceObjects as $oObject) + foreach($aSourceObjects as $oObject) { $oGraph->AddSinkObject($oObject); } @@ -1482,6 +1590,7 @@ abstract class MetaModel $oAttDef = self::GetAttributeDef($sClass, $sStateAttrCode); return $oAttDef->GetValueLabel($sStateValue); } + public static function GetStateDescription($sClass, $sStateValue) { $sStateAttrCode = self::GetStateAttributeCode($sClass); @@ -1500,6 +1609,7 @@ abstract class MetaModel } return array(); } + public static function GetAttributeFlags($sClass, $sState, $sAttCode) { $iFlags = 0; // By default (if no life cycle) no flag at all @@ -1512,7 +1622,7 @@ abstract class MetaModel throw new CoreException("Invalid state '$sState' for class '$sClass', expecting a value in {".implode(', ', array_keys($aStates))."}"); } $aCurrentState = $aStates[$sState]; - if ( (array_key_exists('attribute_list', $aCurrentState)) && (array_key_exists($sAttCode, $aCurrentState['attribute_list'])) ) + if ((array_key_exists('attribute_list', $aCurrentState)) && (array_key_exists($sAttCode, $aCurrentState['attribute_list']))) { $iFlags = $aCurrentState['attribute_list'][$sAttCode]; } @@ -1520,90 +1630,99 @@ abstract class MetaModel return $iFlags; } - /** - * Returns the $sAttCode flags when $sStimulus is applied on an object of $sClass in the $sState state. - * Note: This does NOT combine flags from the target state. - * - * @param $sClass string - * @param $sState string - * @param $sStimulus string - * @param $sAttCode string - * @return int - * @throws CoreException - */ + /** + * Returns the $sAttCode flags when $sStimulus is applied on an object of $sClass in the $sState state. + * Note: This does NOT combine flags from the target state. + * + * @param $sClass string + * @param $sState string + * @param $sStimulus string + * @param $sAttCode string + * @return int + * @throws CoreException + */ public static function GetTransitionFlags($sClass, $sState, $sStimulus, $sAttCode) - { - $iFlags = 0; // By default (if no lifecycle) no flag at all - $sStateAttCode = self::GetStateAttributeCode($sClass); - if (!empty($sStateAttCode)) - { - $aTransitions = MetaModel::EnumTransitions($sClass, $sState); - if(!array_key_exists($sStimulus, $aTransitions)) - { - throw new CoreException("Invalid transition '$sStimulus' for class '$sClass', expecting a value in {".implode(', ', array_keys($aTransitions))."}"); - } + { + $iFlags = 0; // By default (if no lifecycle) no flag at all + $sStateAttCode = self::GetStateAttributeCode($sClass); + if (!empty($sStateAttCode)) + { + $aTransitions = MetaModel::EnumTransitions($sClass, $sState); + if (!array_key_exists($sStimulus, $aTransitions)) + { + throw new CoreException("Invalid transition '$sStimulus' for class '$sClass', expecting a value in {".implode(', ', array_keys($aTransitions))."}"); + } - $aCurrentTransition = $aTransitions[$sStimulus]; - if( (array_key_exists('attribute_list', $aCurrentTransition)) && (array_key_exists($sAttCode, $aCurrentTransition['attribute_list'])) ) - { - $iFlags = $aCurrentTransition['attribute_list'][$sAttCode]; - } - } + $aCurrentTransition = $aTransitions[$sStimulus]; + if ((array_key_exists('attribute_list', $aCurrentTransition)) && (array_key_exists($sAttCode, $aCurrentTransition['attribute_list']))) + { + $iFlags = $aCurrentTransition['attribute_list'][$sAttCode]; + } + } - return $iFlags; - } + return $iFlags; + } - /** - * Returns an array of attribute codes (with their flags) when $sStimulus is applied on an object of $sClass in the $sOriginState state. - * Note: Attributes (and flags) from the target state and the transition are combined. - * - * @param $sClass string Object class - * @param $sStimulus string Stimulus code applied - * @param $sOriginState string State the stimulus comes from - * @return array - */ - public static function GetTransitionAttributes($sClass, $sStimulus, $sOriginState) - { - $aAttributes = array(); + /** + * Returns an array of attribute codes (with their flags) when $sStimulus is applied on an object of $sClass in the $sOriginState state. + * Note: Attributes (and flags) from the target state and the transition are combined. + * + * @param $sClass string Object class + * @param $sStimulus string Stimulus code applied + * @param $sOriginState string State the stimulus comes from + * @return array + */ + public static function GetTransitionAttributes($sClass, $sStimulus, $sOriginState) + { + $aAttributes = array(); - // Retrieving target state - $aTransitions = MetaModel::EnumTransitions($sClass, $sOriginState); - $aTransition = $aTransitions[$sStimulus]; - $sTargetState = $aTransition['target_state']; + // Retrieving target state + $aTransitions = MetaModel::EnumTransitions($sClass, $sOriginState); + $aTransition = $aTransitions[$sStimulus]; + $sTargetState = $aTransition['target_state']; - // Retrieving attributes from state - $aStates = MetaModel::EnumStates($sClass); - $aTargetState = $aStates[$sTargetState]; - $aTargetStateAttributes = $aTargetState['attribute_list']; - // - Merging with results (only MUST_XXX and MANDATORY) - foreach($aTargetStateAttributes as $sTargetStateAttCode => $iTargetStateAttFlags) - { - $iTmpAttFlags = OPT_ATT_NORMAL; - if($iTargetStateAttFlags & OPT_ATT_MUSTPROMPT){ $iTmpAttFlags = $iTmpAttFlags | OPT_ATT_MUSTPROMPT; } - if($iTargetStateAttFlags & OPT_ATT_MUSTCHANGE){ $iTmpAttFlags = $iTmpAttFlags | OPT_ATT_MUSTCHANGE; } - if($iTargetStateAttFlags & OPT_ATT_MANDATORY){ $iTmpAttFlags = $iTmpAttFlags | OPT_ATT_MANDATORY; } + // Retrieving attributes from state + $aStates = MetaModel::EnumStates($sClass); + $aTargetState = $aStates[$sTargetState]; + $aTargetStateAttributes = $aTargetState['attribute_list']; + // - Merging with results (only MUST_XXX and MANDATORY) + foreach($aTargetStateAttributes as $sTargetStateAttCode => $iTargetStateAttFlags) + { + $iTmpAttFlags = OPT_ATT_NORMAL; + if ($iTargetStateAttFlags & OPT_ATT_MUSTPROMPT) + { + $iTmpAttFlags = $iTmpAttFlags | OPT_ATT_MUSTPROMPT; + } + if ($iTargetStateAttFlags & OPT_ATT_MUSTCHANGE) + { + $iTmpAttFlags = $iTmpAttFlags | OPT_ATT_MUSTCHANGE; + } + if ($iTargetStateAttFlags & OPT_ATT_MANDATORY) + { + $iTmpAttFlags = $iTmpAttFlags | OPT_ATT_MANDATORY; + } - $aAttributes[$sTargetStateAttCode] = $iTmpAttFlags; - } + $aAttributes[$sTargetStateAttCode] = $iTmpAttFlags; + } - // Retrieving attributes from transition - $aTransitionAttributes = $aTransition['attribute_list']; - // - Merging with results - foreach($aTransitionAttributes as $sAttCode => $iAttributeFlags) - { - if(array_key_exists($sAttCode, $aAttributes)) - { - $aAttributes[$sAttCode] = $aAttributes[$sAttCode] | $iAttributeFlags; - } - else - { - $aAttributes[$sAttCode] = $iAttributeFlags; - } - } + // Retrieving attributes from transition + $aTransitionAttributes = $aTransition['attribute_list']; + // - Merging with results + foreach($aTransitionAttributes as $sAttCode => $iAttributeFlags) + { + if (array_key_exists($sAttCode, $aAttributes)) + { + $aAttributes[$sAttCode] = $aAttributes[$sAttCode] | $iAttributeFlags; + } + else + { + $aAttributes[$sAttCode] = $iAttributeFlags; + } + } + + return $aAttributes; + } - return $aAttributes; - } - /** * Combines the flags from the all states that compose the initial_state_path */ @@ -1678,15 +1797,15 @@ abstract class MetaModel $aMandatParams = array( "description" => "detailed (though one line) description of the list", "type" => "attributes | filters", - ); - foreach($aMandatParams as $sParamName=>$sParamDesc) + ); + foreach($aMandatParams as $sParamName => $sParamDesc) { if (!array_key_exists($sParamName, $aListInfo)) { throw new CoreException("Declaration of list $sListCode - missing parameter $sParamName"); } } - + self::$m_aListInfos[$sListCode] = $aListInfo; } @@ -1714,6 +1833,7 @@ abstract class MetaModel self::$m_aFilterDefs[$sTargetClass][$sCode] = $oFlt; self::$m_aFilterOrigins[$sTargetClass][$sCode] = $sOriginClass; } + // Must be called once and only once... public static function InitClasses($sTablePrefix) { @@ -1805,7 +1925,7 @@ abstract class MetaModel } self::$m_aClassParams[$sPHPClass]['obsolescence_expression'] = $sObsolescence; - foreach (MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit) + foreach(MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit) { $oClassInit->OnAfterClassInitialization($sPHPClass); } @@ -1822,8 +1942,11 @@ abstract class MetaModel // foreach(self::EnumRootClasses() as $sRootClass) { - if (self::IsStandaloneClass($sRootClass)) continue; - + if (self::IsStandaloneClass($sRootClass)) + { + continue; + } + $sDbFinalClassField = self::DBGetClassField($sRootClass); if (strlen($sDbFinalClassField) == 0) { @@ -1831,15 +1954,15 @@ abstract class MetaModel self::$m_aClassParams[$sRootClass]["db_finalclass_field"] = 'finalclass'; } $oClassAtt = new AttributeFinalClass('finalclass', array( - "sql"=>$sDbFinalClassField, - "default_value"=>$sRootClass, - "is_null_allowed"=>false, - "depends_on"=>array() + "sql" => $sDbFinalClassField, + "default_value" => $sRootClass, + "is_null_allowed" => false, + "depends_on" => array() )); self::AddMagicAttribute($oClassAtt, $sRootClass); $bObsoletable = array_key_exists($sRootClass, $aObsoletableRootClasses); - if ($bObsoletable && is_null(self::$m_aClassParams[$sRootClass]['obsolescence_expression'])) + if ($bObsoletable && is_null(self::$m_aClassParams[$sRootClass]['obsolescence_expression'])) { self::$m_aClassParams[$sRootClass]['obsolescence_expression'] = '0'; } @@ -1859,7 +1982,7 @@ abstract class MetaModel $oCloned->SetFixedValue($sChildClass); self::AddMagicAttribute($oCloned, $sChildClass, $sRootClass); - if ($bObsoletable && is_null(self::$m_aClassParams[$sChildClass]['obsolescence_expression'])) + if ($bObsoletable && is_null(self::$m_aClassParams[$sChildClass]['obsolescence_expression'])) { self::$m_aClassParams[$sChildClass]['obsolescence_expression'] = '0'; } @@ -1867,7 +1990,7 @@ abstract class MetaModel } // Add magic attributes to the classes - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { $sRootClass = self::$m_aRootClasses[$sClass]; @@ -1921,13 +2044,13 @@ abstract class MetaModel // Prepare external fields and filters // Add final class to external keys // Add magic attributes to external keys (finalclass, friendlyname, archive_flag, obsolescence_flag) - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { - foreach (self::$m_aAttribDefs[$sClass] as $sAttCode => $oAttDef) + foreach(self::$m_aAttribDefs[$sClass] as $sAttCode => $oAttDef) { // Compute the filter codes // - foreach ($oAttDef->GetFilterDefinitions() as $sFilterCode => $oFilterDef) + foreach($oAttDef->GetFilterDefinitions() as $sFilterCode => $oFilterDef) { self::$m_aFilterDefs[$sClass][$sFilterCode] = $oFilterDef; @@ -1942,7 +2065,7 @@ abstract class MetaModel self::$m_aFilterOrigins[$sClass][$sFilterCode] = self::$m_aAttribOrigins[$sClass][$sAttCode]; } } - + // Compute the fields that will be used to display a pointer to another object // if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) @@ -1960,26 +2083,26 @@ abstract class MetaModel $sKeyAttCode = $oAttDef->GetKeyAttCode(); $sRemoteAttCode = $oAttDef->GetExtAttCode()."_friendlyname"; $sFriendlyNameAttCode = $sAttCode.'_friendlyname'; - $oFriendlyName = new AttributeExternalField($sFriendlyNameAttCode, array("allowed_values"=>null, "extkey_attcode"=>$sKeyAttCode, "target_attcode"=>$sRemoteAttCode, "depends_on"=>array())); + $oFriendlyName = new AttributeExternalField($sFriendlyNameAttCode, array("allowed_values" => null, "extkey_attcode" => $sKeyAttCode, "target_attcode" => $sRemoteAttCode, "depends_on" => array())); self::AddMagicAttribute($oFriendlyName, $sClass, self::$m_aAttribOrigins[$sClass][$sKeyAttCode]); } else { // Create the friendly name attribute $sFriendlyNameAttCode = $sAttCode.'_friendlyname'; - $oFriendlyName = new AttributeExternalField($sFriendlyNameAttCode, array('allowed_values'=>null, 'extkey_attcode'=>$sAttCode, "target_attcode"=>'friendlyname', 'depends_on'=>array())); + $oFriendlyName = new AttributeExternalField($sFriendlyNameAttCode, array('allowed_values' => null, 'extkey_attcode' => $sAttCode, "target_attcode" => 'friendlyname', 'depends_on' => array())); self::AddMagicAttribute($oFriendlyName, $sClass, self::$m_aAttribOrigins[$sClass][$sAttCode]); if (self::HasChildrenClasses($sRemoteClass)) { // First, create an external field attribute, that gets the final class - $sClassRecallAttCode = $sAttCode.'_finalclass_recall'; + $sClassRecallAttCode = $sAttCode.'_finalclass_recall'; $oClassRecall = new AttributeExternalField($sClassRecallAttCode, array( - "allowed_values"=>null, - "extkey_attcode"=>$sAttCode, - "target_attcode"=>"finalclass", - "is_null_allowed"=>true, - "depends_on"=>array() + "allowed_values" => null, + "extkey_attcode" => $sAttCode, + "target_attcode" => "finalclass", + "is_null_allowed" => true, + "depends_on" => array() )); self::AddMagicAttribute($oClassRecall, $sClass, self::$m_aAttribOrigins[$sClass][$sAttCode]); @@ -2025,7 +2148,7 @@ abstract class MetaModel $sKeyAttCode = $sAttCode; $sRemoteAttCode = 'archive_flag'; } - $oMagic = new AttributeExternalField($sCode, array("allowed_values"=>null, "extkey_attcode"=>$sKeyAttCode, "target_attcode"=>$sRemoteAttCode, "depends_on"=>array())); + $oMagic = new AttributeExternalField($sCode, array("allowed_values" => null, "extkey_attcode" => $sKeyAttCode, "target_attcode" => $sRemoteAttCode, "depends_on" => array())); self::AddMagicAttribute($oMagic, $sClass, self::$m_aAttribOrigins[$sClass][$sKeyAttCode]); } @@ -2044,7 +2167,7 @@ abstract class MetaModel $sKeyAttCode = $sAttCode; $sRemoteAttCode = 'obsolescence_flag'; } - $oMagic = new AttributeExternalField($sCode, array("allowed_values"=>null, "extkey_attcode"=>$sKeyAttCode, "target_attcode"=>$sRemoteAttCode, "depends_on"=>array())); + $oMagic = new AttributeExternalField($sCode, array("allowed_values" => null, "extkey_attcode" => $sKeyAttCode, "target_attcode" => $sRemoteAttCode, "depends_on" => array())); self::AddMagicAttribute($oMagic, $sClass, self::$m_aAttribOrigins[$sClass][$sKeyAttCode]); } } @@ -2092,6 +2215,7 @@ abstract class MetaModel { // In fact it is an ABSTRACT function, but this is not compatible with the fact that it is STATIC (error in E_STRICT interpretation) } + // To be overloaded by biz model declarations public static function GetRelationQueries($sRelCode) { @@ -2111,31 +2235,31 @@ abstract class MetaModel "db_table" => "database table", "db_key_field" => "database field which is the key", "db_finalclass_field" => "database field wich is the reference to the actual class of the object, considering that this will be a compound class", - ); + ); $sClass = self::GetCallersPHPClass("Init", self::$m_bTraceSourceFiles); - foreach($aMandatParams as $sParamName=>$sParamDesc) + foreach($aMandatParams as $sParamName => $sParamDesc) { if (!array_key_exists($sParamName, $aParams)) { throw new CoreException("Declaration of class $sClass - missing parameter $sParamName"); } } - + $aCategories = explode(',', $aParams['category']); - foreach ($aCategories as $sCategory) + foreach($aCategories as $sCategory) { self::$m_Category2Class[$sCategory][] = $sClass; } self::$m_Category2Class[''][] = $sClass; // all categories, include this one - + self::$m_aRootClasses[$sClass] = $sClass; // first, let consider that I am the root... updated on inheritance self::$m_aParentClasses[$sClass] = array(); self::$m_aChildClasses[$sClass] = array(); - self::$m_aClassParams[$sClass]= $aParams; + self::$m_aClassParams[$sClass] = $aParams; self::$m_aAttribDefs[$sClass] = array(); self::$m_aAttribOrigins[$sClass] = array(); @@ -2146,11 +2270,11 @@ abstract class MetaModel protected static function object_array_mergeclone($aSource1, $aSource2) { $aRes = array(); - foreach ($aSource1 as $key=>$object) + foreach($aSource1 as $key => $object) { $aRes[$key] = clone $object; } - foreach ($aSource2 as $key=>$object) + foreach($aSource2 as $key => $object) { $aRes[$key] = clone $object; } @@ -2164,7 +2288,10 @@ abstract class MetaModel { // Default: inherit from parent class $sSourceClass = self::GetParentPersistentClass($sTargetClass); - if (empty($sSourceClass)) return; // no attributes for the mother of all classes + if (empty($sSourceClass)) + { + return; + } // no attributes for the mother of all classes } if (isset(self::$m_aAttribDefs[$sSourceClass])) { @@ -2205,8 +2332,14 @@ abstract class MetaModel { // Differs from self::IsValidClass() // because it is being called before all the classes have been initialized - if (!class_exists($sClass)) return false; - if (!is_subclass_of($sClass, 'DBObject')) return false; + if (!class_exists($sClass)) + { + return false; + } + if (!is_subclass_of($sClass, 'DBObject')) + { + return false; + } return true; } @@ -2230,7 +2363,7 @@ abstract class MetaModel { throw new Exception("Declaration of $sTargetClass: attempting to redeclare the inherited attribute '$sAttCode', originaly declared in ".self::$m_aAttribOrigins[$sTargetClass][$sAttCode]); } - + // 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); @@ -2248,7 +2381,7 @@ abstract class MetaModel return; } } - elseif($oAtt->IsExternalKey()) + elseif ($oAtt->IsExternalKey()) { $sRemoteClass = $oAtt->GetTargetClass(); if (!self::Init_IsKnownClass($sRemoteClass)) @@ -2257,7 +2390,7 @@ abstract class MetaModel return; } } - elseif($oAtt->IsExternalField()) + elseif ($oAtt->IsExternalField()) { $sExtKeyAttCode = $oAtt->GetKeyAttCode(); if (isset(self::$m_aIgnoredAttributes[$sTargetClass][$sExtKeyAttCode])) @@ -2291,7 +2424,7 @@ abstract class MetaModel self::Init_CheckZListItems($aItems, $sTargetClass); self::$m_aListData[$sTargetClass][$sListCode] = $aItems; } - + protected static function Init_CheckZListItems(&$aItems, $sTargetClass) { foreach($aItems as $iFoo => $attCode) @@ -2306,9 +2439,12 @@ abstract class MetaModel unset($aItems[$iFoo]); } } - else if (isset(self::$m_aIgnoredAttributes[$sTargetClass][$attCode])) + else { - unset($aItems[$iFoo]); + if (isset(self::$m_aIgnoredAttributes[$sTargetClass][$attCode])) + { + unset($aItems[$iFoo]); + } } } } @@ -2329,11 +2465,14 @@ abstract class MetaModel } return $aResult; } - + public static function Init_DefineState($sStateCode, $aStateDef) { $sTargetClass = self::GetCallersPHPClass("Init"); - if (is_null($aStateDef['attribute_list'])) $aStateDef['attribute_list'] = array(); + if (is_null($aStateDef['attribute_list'])) + { + $aStateDef['attribute_list'] = array(); + } $sParentState = $aStateDef['attribute_inherit']; if (!empty($sParentState)) @@ -2344,13 +2483,13 @@ abstract class MetaModel // Reset the constraint when it was mandatory to set the value at the previous state // - foreach ($aToInherit['attribute_list'] as $sState => $iFlags) + foreach($aToInherit['attribute_list'] as $sState => $iFlags) { $iFlags = $iFlags & ~OPT_ATT_MUSTPROMPT; $iFlags = $iFlags & ~OPT_ATT_MUSTCHANGE; $aToInherit['attribute_list'][$sState] = $iFlags; } - + // The inherited configuration could be overriden $aStateDef['attribute_list'] = array_merge($aToInherit['attribute_list'], $aStateDef['attribute_list']); } @@ -2374,7 +2513,7 @@ abstract class MetaModel $sTargetClass = self::GetCallersPHPClass("Init"); self::$m_aHighlightScales[$sTargetClass] = $aHighlightScale; } - + public static function GetHighlightScale($sTargetClass) { $aScale = array(); @@ -2391,13 +2530,13 @@ abstract class MetaModel } return array_merge($aParentScale, $aScale); // Merge both arrays, the values from the last one have precedence } - + public static function GetHighlightCode($sTargetClass, $sStateCode) { $sCode = ''; - if ( array_key_exists($sTargetClass, self::$m_aStates) - && array_key_exists($sStateCode, self::$m_aStates[$sTargetClass]) - && array_key_exists('highlight', self::$m_aStates[$sTargetClass][$sStateCode]) ) + if (array_key_exists($sTargetClass, self::$m_aStates) + && array_key_exists($sStateCode, self::$m_aStates[$sTargetClass]) + && array_key_exists('highlight', self::$m_aStates[$sTargetClass][$sStateCode])) { $sCode = self::$m_aStates[$sTargetClass][$sStateCode]['highlight']['code']; } @@ -2412,7 +2551,7 @@ abstract class MetaModel } return $sCode; } - + public static function Init_OverloadStateAttribute($sStateCode, $sAttCode, $iFlags) { // Warning: this is not sufficient: the flags have to be copied to the states that are inheriting from this state @@ -2433,7 +2572,10 @@ abstract class MetaModel public static function Init_DefineTransition($sStateCode, $sStimulusCode, $aTransitionDef) { $sTargetClass = self::GetCallersPHPClass("Init"); - if (is_null($aTransitionDef['actions'])) $aTransitionDef['actions'] = array(); + if (is_null($aTransitionDef['actions'])) + { + $aTransitionDef['actions'] = array(); + } self::$m_aTransitions[$sTargetClass][$sStateCode][$sStimulusCode] = $aTransitionDef; } @@ -2444,7 +2586,10 @@ abstract class MetaModel { // Default: inherit from parent class $sSourceClass = self::GetParentPersistentClass($sTargetClass); - if (empty($sSourceClass)) return; // no attributes for the mother of all classes + if (empty($sSourceClass)) + { + return; + } // no attributes for the mother of all classes } self::$m_aClassParams[$sTargetClass]["state_attcode"] = self::$m_aClassParams[$sSourceClass]["state_attcode"]; @@ -2463,11 +2608,13 @@ abstract class MetaModel self::_check_subclass($sClass); return self::$m_aRootClasses[$sClass]; } + public static function IsRootClass($sClass) { self::_check_subclass($sClass); return (self::GetRootClass($sClass) == $sClass); } + public static function GetParentClass($sClass) { if (count(self::$m_aParentClasses[$sClass]) == 0) @@ -2479,6 +2626,7 @@ abstract class MetaModel return end(self::$m_aParentClasses[$sClass]); } } + public static function GetLowestCommonAncestor($aClasses) { $sAncestor = null; @@ -2505,9 +2653,10 @@ abstract class MetaModel } return $sAncestor; } + /** - * Note: assumes that class A and B have a common ancestor - */ + * Note: assumes that class A and B have a common ancestor + */ protected static function LowestCommonAncestor($sClassA, $sClassB) { if ($sClassA == $sClassB) @@ -2537,7 +2686,7 @@ abstract class MetaModel public static function IsHierarchicalClass($sClass) { $sHierarchicalKeyCode = false; - foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) + foreach(self::ListAttributeDefs($sClass) as $sAttCode => $oAtt) { if ($oAtt->IsHierarchicalKey()) { @@ -2547,13 +2696,15 @@ abstract class MetaModel } return $sHierarchicalKeyCode; } + public static function EnumRootClasses() { return array_unique(self::$m_aRootClasses); } + public static function EnumParentClasses($sClass, $iOption = ENUM_PARENT_CLASSES_EXCLUDELEAF, $bRootFirst = true) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); if ($bRootFirst) { $aRes = self::$m_aParentClasses[$sClass]; @@ -2577,6 +2728,7 @@ abstract class MetaModel } return $aRes; } + public static function EnumChildClasses($sClass, $iOption = ENUM_CHILD_CLASSES_EXCLUDETOP) { self::_check_subclass($sClass); @@ -2589,10 +2741,11 @@ abstract class MetaModel } return $aRes; } + public static function EnumArchivableClasses() { $aRes = array(); - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { if (self::IsArchivable($sClass)) { @@ -2601,14 +2754,18 @@ abstract class MetaModel } return $aRes; } + public static function EnumObsoletableClasses($bRootClassesOnly = true) { $aRes = array(); - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { if (self::IsObsoletable($sClass)) { - if ($bRootClassesOnly && !static::IsRootClass($sClass)) continue; + if ($bRootClassesOnly && !static::IsRootClass($sClass)) + { + continue; + } $aRes[] = $sClass; } } @@ -2628,7 +2785,7 @@ abstract class MetaModel // Note: use EnumChildClasses to take the compound objects into account public static function GetSubclasses($sClass) { - self::_check_subclass($sClass); + self::_check_subclass($sClass); $aSubClasses = array(); foreach(self::$m_aClassParams as $sSubClass => $foo) { @@ -2639,6 +2796,7 @@ abstract class MetaModel } return $aSubClasses; } + public static function GetClasses($sCategories = '', $bStrict = false) { $aCategories = explode(',', $sCategories); @@ -2660,13 +2818,16 @@ abstract class MetaModel throw new CoreException("unkown class category '$sCategory', expecting a value in {".implode(', ', array_keys(self::$m_Category2Class))."}"); } } - + return array_unique($aClasses); } public static function HasTable($sClass) { - if (strlen(self::DBGetTable($sClass)) == 0) return false; + if (strlen(self::DBGetTable($sClass)) == 0) + { + return false; + } return true; } @@ -2708,7 +2869,7 @@ abstract class MetaModel { if (is_scalar($value)) { - $aScalarArgs[$sArgName] = (string) $value; + $aScalarArgs[$sArgName] = (string)$value; } elseif (is_null($value)) { @@ -2753,7 +2914,7 @@ abstract class MetaModel // Compute query modifiers properties (can be set in the search itself, by the context, etc.) // $aModifierProperties = array(); - foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier) + foreach(MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier) { // Lowest precedence: the application context $aPluginProps = ApplicationContext::GetPluginProperties($sPluginClass); @@ -2775,7 +2936,7 @@ abstract class MetaModel * Special processing for the hierarchical keys stored as nested sets * @param $iId integer The identifier of the parent * @param $oAttDef AttributeDefinition The attribute corresponding to the hierarchical key - * @param $stable string The name of the database table containing the hierarchical key + * @param $stable string The name of the database table containing the hierarchical key */ public static function HKInsertChildUnder($iId, $oAttDef, $sTable) { @@ -2791,7 +2952,7 @@ abstract class MetaModel } else { - $iMyRight = $aRes[0]['max']+1; + $iMyRight = $aRes[0]['max'] + 1; } } else @@ -2803,14 +2964,14 @@ abstract class MetaModel $sSQLUpdateLeft = "UPDATE `$sTable` SET `".$oAttDef->GetSQLLeft()."` = `".$oAttDef->GetSQLLeft()."` + 2 WHERE `".$oAttDef->GetSQLLeft()."` > $iMyRight"; CMDBSource::Query($sSQLUpdateLeft); } - return array($oAttDef->GetSQLRight() => $iMyRight+1, $oAttDef->GetSQLLeft() => $iMyRight); + return array($oAttDef->GetSQLRight() => $iMyRight + 1, $oAttDef->GetSQLLeft() => $iMyRight); } /** * Special processing for the hierarchical keys stored as nested sets: temporary remove the branch * @param $iId integer The identifier of the parent * @param $oAttDef AttributeDefinition The attribute corresponding to the hierarchical key - * @param $sTable string The name of the database table containing the hierarchical key + * @param $sTable string The name of the database table containing the hierarchical key */ public static function HKTemporaryCutBranch($iMyLeft, $iMyRight, $oAttDef, $sTable) { @@ -2828,7 +2989,7 @@ abstract class MetaModel * Special processing for the hierarchical keys stored as nested sets: replug the temporary removed branch * @param $iId integer The identifier of the parent * @param $oAttDef AttributeDefinition The attribute corresponding to the hierarchical key - * @param $sTable string The name of the database table containing the hierarchical key + * @param $sTable string The name of the database table containing the hierarchical key */ public static function HKReplugBranch($iNewLeft, $iNewRight, $oAttDef, $sTable) { @@ -2844,30 +3005,33 @@ abstract class MetaModel /** * Check (and updates if needed) the hierarchical keys * @param $bDiagnosticsOnly boolean If true only a diagnostic pass will be run, returning true or false - * @param $bVerbose boolean Displays some information about what is done/what needs to be done - * @param $bForceComputation boolean If true, the _left and _right parameters will be recomputed even if some values already exist in the DB - */ + * @param $bVerbose boolean Displays some information about what is done/what needs to be done + * @param $bForceComputation boolean If true, the _left and _right parameters will be recomputed even if some values already exist in the DB + */ public static function CheckHKeys($bDiagnosticsOnly = false, $bVerbose = false, $bForceComputation = false) { $bChangeNeeded = false; - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { - if (!self::HasTable($sClass)) continue; + if (!self::HasTable($sClass)) + { + continue; + } - foreach(self::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef) + foreach(self::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { // Check (once) all the attributes that are hierarchical keys - if((self::GetAttributeOrigin($sClass, $sAttCode) == $sClass) && $oAttDef->IsHierarchicalKey()) + if ((self::GetAttributeOrigin($sClass, $sAttCode) == $sClass) && $oAttDef->IsHierarchicalKey()) { if ($bVerbose) { - echo "The attribute $sAttCode from $sClass is a hierarchical key.\n"; + echo "The attribute $sAttCode from $sClass is a hierarchical key.\n"; } $bResult = self::HKInit($sClass, $sAttCode, $bDiagnosticsOnly, $bVerbose, $bForceComputation); $bChangeNeeded |= $bResult; if ($bVerbose && !$bResult) { - echo "Ok, the attribute $sAttCode from class $sClass seems up to date.\n"; + echo "Ok, the attribute $sAttCode from class $sClass seems up to date.\n"; } } } @@ -2882,9 +3046,9 @@ abstract class MetaModel * @param $sClass string Name of the class to process * @param $sAttCode string Code of the attribute to process * @param $bDiagnosticsOnly boolean If true only a diagnostic pass will be run, returning true or false - * @param $bVerbose boolean Displays some information about what is done/what needs to be done + * @param $bVerbose boolean Displays some information about what is done/what needs to be done * @param $bForceComputation boolean If true, the _left and _right parameters will be recomputed even if some values already exist in the DB - * @return true if an update is needed (diagnostics only) / was performed + * @return true if an update is needed (diagnostics only) / was performed */ public static function HKInit($sClass, $sAttCode, $bDiagnosticsOnly = false, $bVerbose = false, $bForceComputation = false) { @@ -2924,7 +3088,7 @@ abstract class MetaModel echo "Ok, table '$sTable' successfully updated.\n"; } } - catch(Exception $e) + catch (Exception $e) { CMDBSource::Query('ROLLBACK'); throw new Exception("An error occured (".$e->getMessage().") while initializing the hierarchy for ($sClass, $sAttCode). The database was not modified."); @@ -2933,7 +3097,7 @@ abstract class MetaModel } return $bUpdateNeeded; } - + /** * Recursive helper function called by HKInit */ @@ -2963,21 +3127,24 @@ abstract class MetaModel */ public static function RebuildMetaEnums($bVerbose = false) { - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { - if (!self::HasTable($sClass)) continue; + if (!self::HasTable($sClass)) + { + continue; + } - foreach(self::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef) + 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 ((self::GetAttributeOrigin($sClass, $sAttCode) == $sClass) && $oAttDef instanceof AttributeEnum) { if (isset(self::$m_aEnumToMeta[$sClass][$sAttCode])) { - foreach (self::$m_aEnumToMeta[$sClass][$sAttCode] as $sMetaAttCode => $oMetaAttDef) + foreach(self::$m_aEnumToMeta[$sClass][$sAttCode] as $sMetaAttCode => $oMetaAttDef) { $aMetaValues = array(); // array of (metavalue => array of values) - foreach ($oAttDef->GetAllowedValues() as $sCode => $sLabel) + foreach($oAttDef->GetAllowedValues() as $sCode => $sLabel) { $aMappingData = $oMetaAttDef->GetMapRule($sClass); if ($aMappingData == null) @@ -3001,7 +3168,7 @@ abstract class MetaModel } $aMetaValues[$sMetaValue][] = $sCode; } - foreach ($aMetaValues as $sMetaValue => $aEnumValues) + foreach($aMetaValues as $sMetaValue => $aEnumValues) { $sMetaTable = self::DBGetTable($sClass, $sMetaAttCode); $sEnumTable = self::DBGetTable($sClass); @@ -3034,7 +3201,7 @@ abstract class MetaModel { echo "There are no Data Sources in the database.\n"; } - while($oSource = $oSet->Fetch()) + while ($oSource = $oSet->Fetch()) { if ($bVerbose) { @@ -3046,9 +3213,9 @@ abstract class MetaModel { echo "Ok.\n"; } - return $bFixNeeded; + return $bFixNeeded; } - + public static function GenerateUniqueAlias(&$aAliases, $sNewName, $sRealName) { if (!array_key_exists($sNewName, $aAliases)) @@ -3057,7 +3224,7 @@ abstract class MetaModel return $sNewName; } - for ($i = 1 ; $i < 100 ; $i++) + for($i = 1; $i < 100; $i++) { $sAnAlias = $sNewName.$i; if (!array_key_exists($sAnAlias, $aAliases)) @@ -3067,7 +3234,7 @@ abstract class MetaModel return $sAnAlias; } } - throw new CoreException('Failed to create an alias', array('aliases' => $aAliases, 'new'=>$sNewName)); + throw new CoreException('Failed to create an alias', array('aliases' => $aAliases, 'new' => $sNewName)); } public static function CheckDefinitions($bExitOnError = true) @@ -3079,7 +3246,7 @@ abstract class MetaModel $aErrors = array(); $aSugFix = array(); - foreach (self::GetClasses() as $sClass) + foreach(self::GetClasses() as $sClass) { $sTable = self::DBGetTable($sClass); $sTableLowercase = strtolower($sTable); @@ -3092,12 +3259,12 @@ abstract class MetaModel $aNameSpec = self::GetNameSpec($sClass); foreach($aNameSpec[1] as $i => $sAttCode) { - if(!self::IsValidAttCode($sClass, $sAttCode)) + if (!self::IsValidAttCode($sClass, $sAttCode)) { $aErrors[$sClass][] = "Unknown attribute code '".$sAttCode."' for the name definition"; $aSugFix[$sClass][] = "Expecting a value in ".implode(", ", self::GetAttributesList($sClass)); } - } + } foreach(self::GetReconcKeys($sClass) as $sReconcKeyAttCode) { @@ -3109,10 +3276,13 @@ abstract class MetaModel } $bHasWritableAttribute = false; - foreach(self::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef) + foreach(self::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { // It makes no sense to check the attributes again and again in the subclasses - if (self::$m_aAttribOrigins[$sClass][$sAttCode] != $sClass) continue; + if (self::$m_aAttribOrigins[$sClass][$sAttCode] != $sClass) + { + continue; + } if ($oAttDef->IsExternalKey()) { @@ -3142,57 +3312,63 @@ abstract class MetaModel } } } - else if ($oAttDef->IsLinkSet()) + else { - // Do nothing... - } - else if ($oAttDef instanceof AttributeStopWatch) - { - $aThresholds = $oAttDef->ListThresholds(); - if (is_array($aThresholds)) + if ($oAttDef->IsLinkSet()) { - foreach($aThresholds as $iPercent => $aDef) - { - if (array_key_exists('highlight', $aDef)) - { - if(!array_key_exists('code', $aDef['highlight'])) - { - $aErrors[$sClass][] = "The 'code' element is missing for the 'highlight' property of the $iPercent% threshold in the attribute: '$sAttCode'."; - $aSugFix[$sClass][] = "Add a 'code' entry specifying the value of the highlight code for this threshold."; - } - else - { - $aScale = self::GetHighlightScale($sClass); - if (!array_key_exists($aDef['highlight']['code'], $aScale)) - { - $aErrors[$sClass][] = "'{$aDef['highlight']['code']}' is not a valid value for the 'code' element of the $iPercent% threshold in the attribute: '$sAttCode'."; - $aSugFix[$sClass][] = "The possible highlight codes for this class are: ".implode(', ', array_keys($aScale))."."; - } - } - } - } - } - } - else // standard attributes - { - // Check that the default values definition is a valid object! - $oValSetDef = $oAttDef->GetValuesDef(); - if (!is_null($oValSetDef) && !$oValSetDef instanceof ValueSetDefinition) - { - $aErrors[$sClass][] = "Allowed values for attribute $sAttCode is not of the relevant type"; - $aSugFix[$sClass][] = "Please set it as an instance of a ValueSetDefinition object."; + // Do nothing... } else { - // Default value must be listed in the allowed values (if defined) - $aAllowedValues = self::GetAllowedValues_att($sClass, $sAttCode); - if (!is_null($aAllowedValues)) + if ($oAttDef instanceof AttributeStopWatch) { - $sDefaultValue = $oAttDef->GetDefaultValue(); - if (is_string($sDefaultValue) && !array_key_exists($sDefaultValue, $aAllowedValues)) + $aThresholds = $oAttDef->ListThresholds(); + if (is_array($aThresholds)) { - $aErrors[$sClass][] = "Default value '".$sDefaultValue."' for attribute $sAttCode is not an allowed value"; - $aSugFix[$sClass][] = "Please pickup the default value out of {'".implode(", ", array_keys($aAllowedValues))."'}"; + foreach($aThresholds as $iPercent => $aDef) + { + if (array_key_exists('highlight', $aDef)) + { + if (!array_key_exists('code', $aDef['highlight'])) + { + $aErrors[$sClass][] = "The 'code' element is missing for the 'highlight' property of the $iPercent% threshold in the attribute: '$sAttCode'."; + $aSugFix[$sClass][] = "Add a 'code' entry specifying the value of the highlight code for this threshold."; + } + else + { + $aScale = self::GetHighlightScale($sClass); + if (!array_key_exists($aDef['highlight']['code'], $aScale)) + { + $aErrors[$sClass][] = "'{$aDef['highlight']['code']}' is not a valid value for the 'code' element of the $iPercent% threshold in the attribute: '$sAttCode'."; + $aSugFix[$sClass][] = "The possible highlight codes for this class are: ".implode(', ', array_keys($aScale))."."; + } + } + } + } + } + } + else // standard attributes + { + // Check that the default values definition is a valid object! + $oValSetDef = $oAttDef->GetValuesDef(); + if (!is_null($oValSetDef) && !$oValSetDef instanceof ValueSetDefinition) + { + $aErrors[$sClass][] = "Allowed values for attribute $sAttCode is not of the relevant type"; + $aSugFix[$sClass][] = "Please set it as an instance of a ValueSetDefinition object."; + } + else + { + // Default value must be listed in the allowed values (if defined) + $aAllowedValues = self::GetAllowedValues_att($sClass, $sAttCode); + if (!is_null($aAllowedValues)) + { + $sDefaultValue = $oAttDef->GetDefaultValue(); + if (is_string($sDefaultValue) && !array_key_exists($sDefaultValue, $aAllowedValues)) + { + $aErrors[$sClass][] = "Default value '".$sDefaultValue."' for attribute $sAttCode is not an allowed value"; + $aSugFix[$sClass][] = "Please pickup the default value out of {'".implode(", ", array_keys($aAllowedValues))."'}"; + } + } } } } @@ -3201,7 +3377,7 @@ abstract class MetaModel if ($oAttDef->IsWritable()) { $bHasWritableAttribute = true; - foreach ($oAttDef->GetPrerequisiteAttributes() as $sDependOnAttCode) + foreach($oAttDef->GetPrerequisiteAttributes() as $sDependOnAttCode) { if (!self::IsValidAttCode($sClass, $sDependOnAttCode)) { @@ -3211,10 +3387,10 @@ abstract class MetaModel } } } - foreach(self::GetClassFilterDefs($sClass) as $sFltCode=>$oFilterDef) + foreach(self::GetClassFilterDefs($sClass) as $sFltCode => $oFilterDef) { if (method_exists($oFilterDef, '__GetRefAttribute')) - { + { $oAttDef = $oFilterDef->__GetRefAttribute(); if (!self::IsValidAttCode($sClass, $oAttDef->GetCode())) { @@ -3248,7 +3424,7 @@ abstract class MetaModel else { $aAllowedValues = array_keys($aAllowedValuesRaw); - + // Lifecycle - check the the state attribute allowed values are defined states foreach($aAllowedValues as $sValue) { @@ -3258,7 +3434,7 @@ abstract class MetaModel $aSugFix[$sClass][] = "You may define its allowed_values property as [new ValueSetEnum('".implode(", ", $aStates)."')], or reconsider the list of states"; } } - + // Lifecycle - check that defined states are allowed values foreach($aStates as $sStateValue) { @@ -3269,13 +3445,13 @@ abstract class MetaModel } } } - + // Lifecycle - check that the action handlers are defined - foreach (self::EnumStates($sClass) as $sStateCode => $aStateDef) + foreach(self::EnumStates($sClass) as $sStateCode => $aStateDef) { foreach(self::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef) { - foreach ($aTransitionDef['actions'] as $actionHandler) + foreach($aTransitionDef['actions'] as $actionHandler) { if (is_string($actionHandler)) { @@ -3298,7 +3474,7 @@ abstract class MetaModel } if (array_key_exists('highlight', $aStateDef)) { - if(!array_key_exists('code', $aStateDef['highlight'])) + if (!array_key_exists('code', $aStateDef['highlight'])) { $aErrors[$sClass][] = "The 'code' element is missing for the 'highlight' property of state: '$sStateCode'."; $aSugFix[$sClass][] = "Add a 'code' entry specifying the value of the highlight code for this state."; @@ -3331,7 +3507,7 @@ abstract class MetaModel // foreach(self::EnumZLists() as $sListCode) { - foreach (self::FlattenZList(self::GetZListItems($sClass, $sListCode)) as $sMyAttCode) + foreach(self::FlattenZList(self::GetZListItems($sClass, $sListCode)) as $sMyAttCode) { if (!self::IsValidAttCode($sClass, $sMyAttCode)) { @@ -3347,14 +3523,17 @@ abstract class MetaModel { $aTableColumns = array(); // array of column => attcode (the column is used by this attribute) $aTableColumns[self::DBGetKey($sClass)] = 'id'; - + // Check that SQL columns are declared only once // - foreach(self::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef) + foreach(self::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { // Skip this attribute if not originaly defined in this class - if (self::$m_aAttribOrigins[$sClass][$sAttCode] != $sClass) continue; - + if (self::$m_aAttribOrigins[$sClass][$sAttCode] != $sClass) + { + continue; + } + foreach($oAttDef->GetSQLColumns() as $sField => $sDBFieldType) { if (array_key_exists($sField, $aTableColumns)) @@ -3370,33 +3549,42 @@ abstract class MetaModel } } } // foreach class - + if (count($aErrors) > 0) { echo "
Wrong declaration for class $sClass
\n"; echo "Aborting...
\n"; + if ($bExitOnError) + { + echo "Aborting...
\n"; + } echo "