isAbstract()) { $sAbstract = ''; } return "$sAbstract $sName ($sClass)"; } /** * Get class hierarchy as breadcrumb. * * @param string $sClass * @param string $sContext * * @return string * @throws CoreException * @throws ReflectionException */ function GetClassHierarchy(string $sClass, string $sContext): string { $sClassSpacer = ''; $aParentClasses = []; foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass) { $aParentClasses[] = MakeClassHLink($sParentClass, $sContext, "ibo-button ibo-button ibo-block ibo-is-alternative ibo-is-neutral", true); } if (count($aParentClasses) > 0) { $sParents = $sClassSpacer.implode($sClassSpacer, $aParentClasses); } else { $sParents = ''; } return "
"; } /** * Make a class link. * * @param string $sClass * @param string $sContext * @param string $sCssClasses * * @return string * @throws CoreException * @throws DictExceptionMissingString * @throws ReflectionException */ function MakeClassHLink(string $sClass, string $sContext, string $sCssClasses = ''): string { $sLabel = GetClassLabel($sClass); return "$sLabel"; } /** * Display class information. * * @param string $sClass * @param string $sContext * * @return array * @throws CoreException * @throws DictExceptionMissingString * @throws ReflectionException */ function GetClassInformation(string $sClass, string $sContext): array { // List the attributes of the object $aForwardChangeTracking = MetaModel::GetTrackForwardExternalKeys($sClass); $aDetails = []; $aOrigins = []; foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { if ($oAttDef->IsExternalKey()) { $sValue = Dict::Format('UI:Schema:ExternalKey_To', MakeClassHLink($oAttDef->GetTargetClass(), $sContext)); if (array_key_exists($sAttCode, $aForwardChangeTracking)) { $oLinkSet = $aForwardChangeTracking[$sAttCode]; $sRemoteClass = $oLinkSet->GetHostClass(); $sValue = $sValue."*"; } } elseif ($oAttDef->IsLinkSet()) { $sValue = MakeClassHLink($oAttDef->GetLinkedClass(), $sContext); } else { $sValue = $oAttDef->GetDescription(); } [$classShortName, $label, $description] = array_values($oAttDef->GetTypeInformation()); $sOrigin = MetaModel::GetAttributeOrigin($sClass, $sAttCode); $aOrigins[$sOrigin] = true; $sMoreInfo = ""; $sDefaultNullValue = ''; if (call_user_func([get_class($oAttDef), 'IsBasedOnDBColumns'])) { $aMoreInfo = []; if ($oAttDef->IsNullAllowed()) { $aMoreInfo[] = Dict::S('UI:Schema:NullAllowed'); $sDefaultNullValue = (!is_null($oAttDef->GetNullValue()) ? $oAttDef->GetNullValue() : null); if (!is_null($sDefaultNullValue) && !is_string($sDefaultNullValue)) { $sDefaultNullValue = json_encode($sDefaultNullValue); } $sDefaultNullValue = (!is_null($sDefaultNullValue) ? Dict::Format( 'UI:Schema:DefaultNullValue', $sDefaultNullValue ) : ''); } else { $aMoreInfo[] = Dict::S('UI:Schema:NullNotAllowed'); } if ($oAttDef->GetDefaultValue()) { $sDefaultValue = $oAttDef->GetDefaultValue(); if (!is_string($sDefaultValue)) { $sDefaultValue = json_encode($sDefaultValue); } $aMoreInfo[] = Dict::Format("UI:Schema:Default_Description", $sDefaultValue); } $sMoreInfo .= implode(', ', $aMoreInfo); } $sAttrCode = $oAttDef->GetCode(); if ($oAttDef instanceof AttributeEnum) { // Display localized values for the enum (which depend on the localization provided by the class) $aLocalizedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, []); $aDescription = []; foreach ($aLocalizedValues as $val => $sDisplay) { $aDescription[] = $sDisplay." (".$val.")"; } $sAllowedValues = implode(', ', $aDescription); } elseif (is_object($oAllowedValuesDef = $oAttDef->GetValuesDef())) { $sAllowedValues = str_replace("Filter: ", "", $oAllowedValuesDef->GetValuesDescription()); $sAllowedValuesEscpd = utils::HtmlEntities($sAllowedValues); $sFilterURL = urlencode($sAllowedValues); $sAllowedValues = ' '.Dict::S('UI:Schema:Attribute/Filter').""; } else { $sAllowedValues = ''; } $sAttrValueEscpd = utils::HtmlEntities($sValue); $sAttrTypeDescEscpd = utils::HtmlEntities($description); $sAttrOriginEscpd = utils::HtmlEntities($sOrigin); $sDefaultNullValueEscpd = utils::HtmlEntities($sDefaultNullValue); $aDetails[] = [ 'code' => ''.$oAttDef->GetLabel().' ('.$oAttDef->GetCode().')', 'type' => ''.$label.' ('.$classShortName.')', 'origincolor' => '', 'origin' => "$sOrigin", 'values' => $sAllowedValues, 'moreinfo' => ''.$sMoreInfo.'', ]; } return [ 'details' => $aDetails, 'origins' => $aOrigins, ]; } /** * Display class attributes. * * @param iTopWebPage $oPage * @param string $sClass * @param string $sContext * * @return void */ function DisplayClassAttributes(iTopWebPage $oPage, string $sClass, string $sContext): void { $aClassInformation = GetClassInformation($sClass, $sContext); $aConfig = [ 'origincolor' => ['label' => "", 'description' => ""], 'code' => ['label' => Dict::S('UI:Schema:AttributeCode'), 'description' => Dict::S('UI:Schema:AttributeCode+')], 'type' => ['label' => Dict::S('UI:Schema:Type'), 'description' => Dict::S('UI:Schema:Type+')], 'values' => ['label' => Dict::S('UI:Schema:AllowedValues'), 'description' => Dict::S('UI:Schema:AllowedValues+')], 'moreinfo' => ['label' => Dict::S('UI:Schema:MoreInfo'), 'description' => Dict::S('UI:Schema:MoreInfo+')], 'origin' => ['label' => Dict::S('UI:Schema:Origin'), 'description' => Dict::S('UI:Schema:Origin+')], ]; $oTablePanel = PanelUIBlockFactory::MakeForClass($sClass, ''); $oTablePanel->AddCSSClass('ibo-datatable-panel'); $oAttributesTable = DataTableUIBlockFactory::MakeForStaticData('', $aConfig, $aClassInformation['details'], 'ibo-datamodel-viewer--attributes-table', [], "", ['pageLength' => -1]); $oTablePanel->AddSubBlock($oAttributesTable); $oPage->AddUiBlock($oTablePanel); $sOrigins = json_encode(array_keys($aClassInformation['origins'])); //color calculation in order to keep 1 color for 1 extended class. Colors are interpolated and will be used for // graph scheme color too $oPage->add_ready_script( <<< EOF var aOrigins = $sOrigins; var aColors = d3.scale.linear().domain([1,aOrigins.length]) .interpolate(d3.interpolateHcl) .range([d3.rgb("#007AFF"), d3.rgb('#FFF500')]); $.each(aOrigins,function(idx, origin){ $('.originColor'+origin).css('background-color',aColors(aOrigins.indexOf(origin))); }); Array.prototype.forEach.call($(".listResults").find('td:nth-child(1),th:nth-child(1)'), function(e){ $(e).removeClass("header").addClass("ibo-datamodel-viewer--origin-cell"); }); EOF ); } /** * Helper for the global list and the details of a given class */ function DisplaySubclasses($oPage, $sClass, $sContext) { $aChildClasses = MetaModel::EnumChildClasses($sClass); if (count($aChildClasses) != 0) { $oPage->add("