* @author Romain Quetiez * @author Denis Flaven * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL */ define('OBJECT_PROPERTIES_TAB', 'ObjectProperties'); define('HILIGHT_CLASS_CRITICAL', 'red'); define('HILIGHT_CLASS_WARNING', 'orange'); define('HILIGHT_CLASS_OK', 'green'); define('HILIGHT_CLASS_NONE', ''); require_once(APPROOT.'/core/cmdbobject.class.inc.php'); require_once(APPROOT.'/application/utils.inc.php'); require_once(APPROOT.'/application/applicationcontext.class.inc.php'); require_once(APPROOT.'/application/ui.linkswidget.class.inc.php'); require_once(APPROOT.'/application/ui.passwordwidget.class.inc.php'); require_once(APPROOT.'/application/ui.extkeywidget.class.inc.php'); require_once(APPROOT.'/application/ui.htmleditorwidget.class.inc.php'); abstract class cmdbAbstractObject extends CMDBObject { protected $m_iFormId; // The ID of the form used to edit the object (when in edition mode !) public static function GetUIPage() { return '../pages/UI.php'; } public static function ComputeUIPage($sClass) { static $aUIPagesCache = array(); // Cache to store the php page used to display each class of object if (!isset($aUIPagesCache[$sClass])) { $UIPage = false; if (is_callable("$sClass::GetUIPage")) { $UIPage = eval("return $sClass::GetUIPage();"); // May return false in case of error } $aUIPagesCache[$sClass] = $UIPage === false ? './UI.php' : $UIPage; } $sPage = $aUIPagesCache[$sClass]; return $sPage; } protected static function MakeHyperLink($sObjClass, $sObjKey, $sLabel = '') { if ($sObjKey <= 0) return ''.Dict::S('UI:UndefinedObject').''; // Objects built in memory have negative IDs $oAppContext = new ApplicationContext(); $sPage = self::ComputeUIPage($sObjClass); $sAbsoluteUrl = utils::GetAbsoluteUrlPath(); // Safety net // if (empty($sLabel)) { $sLabel = MetaModel::GetName($sObjClass)." #$sObjKey"; } $sHint = MetaModel::GetName($sObjClass)."::$sObjKey"; return "GetForLink()."\" title=\"$sHint\">$sLabel"; } function DisplayBareHeader(WebPage $oPage, $bEditMode = false) { // Standard Header with name, actions menu and history block // // action menu $oSingletonFilter = new DBObjectSearch(get_class($this)); $oSingletonFilter->AddCondition('id', $this->GetKey(), '='); $oBlock = new MenuBlock($oSingletonFilter, 'popup', false); $oBlock->Display($oPage, -1); $oPage->add("

".$this->GetIcon()." \n"); $oPage->add(MetaModel::GetName(get_class($this)).": ".$this->GetName()."

\n"); $oPage->add("
\n"); } function DisplayBareHistory(WebPage $oPage, $bEditMode = false) { // history block (with as a tab) $oHistoryFilter = new DBObjectSearch('CMDBChangeOp'); $oHistoryFilter->AddCondition('objkey', $this->GetKey(), '='); $oHistoryFilter->AddCondition('objclass', get_class($this), '='); $oBlock = new HistoryBlock($oHistoryFilter, 'table', false); $oBlock->Display($oPage, -1); } function DisplayBareProperties(WebPage $oPage, $bEditMode = false) { $oPage->add($this->GetBareProperties($oPage, $bEditMode)); } function DisplayBareRelations(WebPage $oPage, $bEditMode = false) { // Related objects: display all the linkset attributes, each as a separate tab // In the order described by the 'display' ZList $aList = $this->FlattenZList(MetaModel::GetZListItems(get_class($this), 'details')); if (count($aList) == 0) { // Empty ZList defined, display all the linkedset attributes defined $aList = array_keys(MetaModel::ListAttributeDefs(get_class($this))); } $sClass = get_class($this); foreach($aList as $sAttCode) { $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode); // Display mode if (!$oAttDef->IsLinkset()) continue; // Process only linkset attributes... $oPage->SetCurrentTab($oAttDef->GetLabel()); if ($bEditMode) { $iFlags = $this->GetAttributeFlags($sAttCode); $sInputId = $this->m_iFormId.'_'.$sAttCode; if (get_class($oAttDef) == 'AttributeLinkedSet') { // 1:n links $sTargetClass = $oAttDef->GetLinkedClass(); if ($this->IsNew()) { $oPage->p(Dict::Format('UI:BeforeAdding_Class_ObjectsSaveThisObject', MetaModel::GetName($sTargetClass))); } else { $oPage->p(MetaModel::GetClassIcon($sTargetClass)." ".$oAttDef->GetDescription()); $oFilter = new DBObjectSearch($sTargetClass); $oFilter->AddCondition($oAttDef->GetExtKeyToMe(), $this->GetKey(),'='); $aDefaults = array($oAttDef->GetExtKeyToMe() => $this->GetKey()); $oAppContext = new ApplicationContext(); foreach($oAppContext->GetNames() as $sKey) { // The linked object inherits the parent's value for the context if (MetaModel::IsValidAttCode($sClass, $sKey)) { $aDefaults[$sKey] = $this->Get($sKey); } } $aParams = array( 'target_attr' => $oAttDef->GetExtKeyToMe(), 'object_id' => $this->GetKey(), 'menu' => true, 'default' => $aDefaults, ); $oBlock = new DisplayBlock($oFilter, 'list', false); $oBlock->Display($oPage, $sInputId, $aParams); } } else // get_class($oAttDef) == 'AttributeLinkedSetIndirect' { // n:n links $sLinkedClass = $oAttDef->GetLinkedClass(); $oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $oAttDef->GetExtKeyToRemote()); $sTargetClass = $oLinkingAttDef->GetTargetClass(); $oPage->p(MetaModel::GetClassIcon($sTargetClass)." ".$oAttDef->GetDescription().''); $sValue = $this->Get($sAttCode); $sDisplayValue = $this->GetEditValue($sAttCode); $aArgs = array('this' => $this); $sHTMLValue = "".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).''; $aFieldsMap[$sAttCode] = $sInputId; $oPage->add($sHTMLValue); } } else { // Display mode if (!$oAttDef->IsIndirect()) { // 1:n links $sTargetClass = $oAttDef->GetLinkedClass(); $aDefaults = array($oAttDef->GetExtKeyToMe() => $this->GetKey()); $oAppContext = new ApplicationContext(); foreach($oAppContext->GetNames() as $sKey) { // The linked object inherits the parent's value for the context if (MetaModel::IsValidAttCode($sClass, $sKey)) { $aDefaults[$sKey] = $this->Get($sKey); } } $aParams = array( 'target_attr' => $oAttDef->GetExtKeyToMe(), 'object_id' => $this->GetKey(), 'menu' => false, 'default' => $aDefaults, ); } else { // n:n links $sLinkedClass = $oAttDef->GetLinkedClass(); $oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $oAttDef->GetExtKeyToRemote()); $sTargetClass = $oLinkingAttDef->GetTargetClass(); $bMenu = ($this->Get($sAttCode)->Count() > 0); // The menu is enabled only if there are already some elements... $aParams = array( 'link_attr' => $oAttDef->GetExtKeyToMe(), 'object_id' => $this->GetKey(), 'target_attr' => $oAttDef->GetExtKeyToRemote(), 'view_link' => false, 'menu' => false, 'display_limit' => true, // By default limit the list to speed up the initial load & display ); } $oPage->p(MetaModel::GetClassIcon($sTargetClass)." ".$oAttDef->GetDescription()); $oBlock = new DisplayBlock($this->Get($sAttCode)->GetFilter(), 'list', false); $oBlock->Display($oPage, 'rel_'.$sAttCode, $aParams); } } $oPage->SetCurrentTab(''); if (!$bEditMode) { // Get the actual class of the current object // And look for triggers referring to it // If any trigger has been found then display a tab with notifications // $sClass = get_class($this); $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL)); $oTriggerSet = new CMDBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObject AS T WHERE T.target_class IN ('$sClassList')")); if ($oTriggerSet->Count() > 0) { $oPage->SetCurrentTab(Dict::S('UI:NotificationsTab')); // Display notifications regarding the object $iId = $this->GetKey(); $oBlock = new DisplayBlock(DBObjectSearch::FromOQL("SELECT EventNotificationEmail AS Ev JOIN TriggerOnObject AS T ON Ev.trigger_id = T.id WHERE T.target_class IN ('$sClassList') AND Ev.object_id = $iId"), 'list', false); $oBlock->Display($oPage, 'notifications', array()); } } } function GetBareProperties(WebPage $oPage, $bEditMode = false) { $sHtml = ''; $oAppContext = new ApplicationContext(); $sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this)); $aDetails = array(); $sClass = get_class($this); $aDetailsList = MetaModel::GetZListItems($sClass, 'details'); $aDetailsStruct = self::ProcessZlist($aDetailsList, array('UI:PropertiesTab' => array()), 'UI:PropertiesTab', 'col1', ''); // Compute the list of properties to display, first the attributes in the 'details' list, then // all the remaining attributes that are not external fields $sHtml = ''; $aDetails = array(); foreach($aDetailsStruct as $sTab => $aCols ) { $aDetails[$sTab] = array(); ksort($aCols); $oPage->SetCurrentTab(Dict::S($sTab)); $oPage->add(''); foreach($aCols as $sColIndex => $aFieldsets) { $oPage->add(''); } $oPage->add('
'); //$aDetails[$sTab][$sColIndex] = array(); $sLabel = ''; $sPreviousLabel = ''; $aDetails[$sTab][$sColIndex] = array(); foreach($aFieldsets as $sFieldsetName => $aFields) { if (!empty($sFieldsetName) && ($sFieldsetName[0] != '_')) { $sLabel = $sFieldsetName; } else { $sLabel = ''; } if ($sLabel != $sPreviousLabel) { if (!empty($sPreviousLabel)) { $oPage->add('
'); $oPage->add(''.Dict::S($sPreviousLabel).''); } $oPage->Details($aDetails[$sTab][$sColIndex]); if (!empty($sPreviousLabel)) { $oPage->add('
'); } $aDetails[$sTab][$sColIndex] = array(); $sPreviousLabel = $sLabel; } foreach($aFields as $sAttCode) { $val = $this->GetFieldAsHtml($sClass, $sAttCode, $sStateAttCode); if ($val != null) { // The field is visible, add it to the current column $aDetails[$sTab][$sColIndex][] = $val; } } } if (!empty($sPreviousLabel)) { $oPage->add('
'); $oPage->add(''.Dict::S($sFieldsetName).''); } $oPage->Details($aDetails[$sTab][$sColIndex]); if (!empty($sPreviousLabel)) { $oPage->add('
'); } $oPage->add('
'); } return $sHtml; } function DisplayDetails(WebPage $oPage, $bEditMode = false) { $sTemplate = Utils::ReadFromFile(MetaModel::GetDisplayTemplate(get_class($this))); if (!empty($sTemplate)) { $oTemplate = new DisplayTemplate($sTemplate); // Note: to preserve backward compatibility with home-made templates, the placeholder '$pkey$' has been preserved // but the preferred method is to use '$id$' $oTemplate->Render($oPage, array('class_name'=> MetaModel::GetName(get_class($this)),'class'=> get_class($this), 'pkey'=> $this->GetKey(), 'id'=> $this->GetKey(), 'name' => $this->Get('friendlyname'))); } else { // Object's details // template not found display the object using the *old style* $this->DisplayBareHeader($oPage, $bEditMode); $oPage->AddTabContainer(OBJECT_PROPERTIES_TAB); $oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB); $oPage->SetCurrentTab(Dict::S('UI:PropertiesTab')); $this->DisplayBareProperties($oPage, $bEditMode); $this->DisplayBareRelations($oPage, $bEditMode); $oPage->SetCurrentTab(Dict::S('UI:HistoryTab')); $this->DisplayBareHistory($oPage, $bEditMode); } } function DisplayPreview(WebPage $oPage) { $aDetails = array(); $sClass = get_class($this); $aList = MetaModel::GetZListItems($sClass, 'preview'); foreach($aList as $sAttCode) { $aDetails[] = array('label' => MetaModel::GetLabel($sClass, $sAttCode), 'value' =>$this->GetAsHTML($sAttCode)); } $oPage->details($aDetails); } public static function DisplaySet(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { $oPage->add(self::GetDisplaySet($oPage, $oSet, $aExtraParams)); } /** * Get the HTML fragment corresponding to the display of a table representing a set of objects * @param WebPage $oPage The page object is used for out-of-band information (mostly scripts) output * @param CMDBObjectSet The set of objects to display * @param Hash $aExtraParams Some extra configuration parameters to tweak the behavior of the display * @return String The HTML fragment representing the table of objects */ public static function GetDisplaySet(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { if (empty($aExtraParams['currentId'])) { $iListId = $oPage->GetUniqueId(); // Works only if not in an Ajax page !! } else { $iListId = $aExtraParams['currentId']; } // Initialize and check the parameters $bViewLink = isset($aExtraParams['view_link']) ? $aExtraParams['view_link'] : true; $sLinkageAttribute = isset($aExtraParams['link_attr']) ? $aExtraParams['link_attr'] : ''; $iLinkedObjectId = isset($aExtraParams['object_id']) ? $aExtraParams['object_id'] : 0; $sTargetAttr = isset($aExtraParams['target_attr']) ? $aExtraParams['target_attr'] : ''; if (!empty($sLinkageAttribute)) { if($iLinkedObjectId == 0) { // if 'links' mode is requested the id of the object to link to must be specified throw new ApplicationException(Dict::S('UI:Error:MandatoryTemplateParameter_object_id')); } if($sTargetAttr == '') { // if 'links' mode is requested the d of the object to link to must be specified throw new ApplicationException(Dict::S('UI:Error:MandatoryTemplateParameter_target_attr')); } } $bDisplayMenu = isset($aExtraParams['menu']) ? $aExtraParams['menu'] == true : true; $bTruncated = isset($aExtraParams['truncated']) ? $aExtraParams['truncated'] == true : true; $bSelectMode = isset($aExtraParams['selection_mode']) ? $aExtraParams['selection_mode'] == true : false; $bSingleSelectMode = isset($aExtraParams['selection_type']) ? ($aExtraParams['selection_type'] == 'single') : false; $aExtraFields = isset($aExtraParams['extra_fields']) ? explode(',', trim($aExtraParams['extra_fields'])) : array(); $sHtml = ''; $oAppContext = new ApplicationContext(); $sClassName = $oSet->GetFilter()->GetClass(); $aAttribs = array(); $sZListName = isset($aExtraParams['zlist']) ? ($aExtraParams['zlist']) : 'list'; $aList = self::FlattenZList(MetaModel::GetZListItems($sClassName, $sZListName)); $aList = array_merge($aList, $aExtraFields); // Filter the list to removed linked set since we are not able to display them here foreach($aList as $index => $sAttCode) { $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode); if ($oAttDef instanceof AttributeLinkedSet) { // Removed from the display list unset($aList[$index]); } } if (!empty($sLinkageAttribute)) { // The set to display is in fact a set of links between the object specified in the $sLinkageAttribute // and other objects... // The display will then group all the attributes related to the link itself: // | Link_attr1 | link_attr2 | ... || Object_attr1 | Object_attr2 | Object_attr3 | .. | Object_attr_n | $aDisplayList = array(); $aAttDefs = MetaModel::ListAttributeDefs($sClassName); assert(isset($aAttDefs[$sLinkageAttribute])); $oAttDef = $aAttDefs[$sLinkageAttribute]; assert($oAttDef->IsExternalKey()); // First display all the attributes specific to the link record foreach($aList as $sLinkAttCode) { $oLinkAttDef = $aAttDefs[$sLinkAttCode]; if ( (!$oLinkAttDef->IsExternalKey()) && (!$oLinkAttDef->IsExternalField()) ) { $aDisplayList[] = $sLinkAttCode; } } // Then display all the attributes neither specific to the link record nor to the 'linkage' object (because the latter are constant) foreach($aList as $sLinkAttCode) { $oLinkAttDef = $aAttDefs[$sLinkAttCode]; if (($oLinkAttDef->IsExternalKey() && ($sLinkAttCode != $sLinkageAttribute)) || ($oLinkAttDef->IsExternalField() && ($oLinkAttDef->GetKeyAttCode()!=$sLinkageAttribute)) ) { $aDisplayList[] = $sLinkAttCode; } } // First display all the attributes specific to the link // Then display all the attributes linked to the other end of the relationship $aList = $aDisplayList; } if ($bSelectMode) { if (!$bSingleSelectMode) { $aAttribs['form::select'] = array('label' => "", 'description' => Dict::S('UI:SelectAllToggle+')); } else { $aAttribs['form::select'] = array('label' => "", 'description' => ''); } } if ($bViewLink) { $aAttribs['key'] = array('label' => MetaModel::GetName($sClassName), 'description' => ''); } foreach($aList as $sAttCode) { $aAttribs[$sAttCode] = array('label' => MetaModel::GetLabel($sClassName, $sAttCode), 'description' => MetaModel::GetDescription($sClassName, $sAttCode)); } $aValues = array(); $bDisplayLimit = isset($aExtraParams['display_limit']) ? $aExtraParams['display_limit'] : true; $iMaxObjects = -1; if ($bDisplayLimit && $bTruncated) { if ($oSet->Count() > MetaModel::GetConfig()->GetMaxDisplayLimit()) { $iMaxObjects = MetaModel::GetConfig()->GetMinDisplayLimit(); $oSet->SetLimit($iMaxObjects); } } $oSet->Seek(0); while (($oObj = $oSet->Fetch()) && ($iMaxObjects != 0)) { $aRow = array(); $sHilightClass = $oObj->GetHilightClass(); if ($sHilightClass != '') { $aRow['@class'] = $sHilightClass; } if ($bViewLink) { $aRow['key'] = $oObj->GetHyperLink(); } if ($bSelectMode) { if ($bSingleSelectMode) { $aRow['form::select'] = "GetKey()."\">"; } else { $aRow['form::select'] = "GetKey()."\">"; } } foreach($aList as $sAttCode) { $aRow[$sAttCode] = $oObj->GetAsHTML($sAttCode); } $aValues[] = $aRow; $iMaxObjects--; } $sHtml .= ''; $sColspan = ''; // if (isset($aExtraParams['block_id'])) // { // $divId = $aExtraParams['block_id']; // } // else // { // $divId = 'missingblockid'; // } $sFilter = $oSet->GetFilter()->serialize(); $iMinDisplayLimit = MetaModel::GetConfig()->GetMinDisplayLimit(); $sCollapsedLabel = Dict::Format('UI:TruncatedResults', $iMinDisplayLimit, $oSet->Count()); $sLinkLabel = Dict::S('UI:DisplayAll'); foreach($oSet->GetFilter()->GetInternalParams() as $sName => $sValue) { $aExtraParams['query_params'][$sName] = $sValue; } if ($bDisplayLimit && $bTruncated && ($oSet->Count() > MetaModel::GetConfig()->GetMaxDisplayLimit())) { // list truncated $aExtraParams['display_limit'] = true; $sHtml .= ''; } $sHtml .= "'; $sHtml .= '
'.$sCollapsedLabel.'  '.$sLinkLabel.''; $oPage->add_ready_script( <<Count() > MetaModel::GetConfig()->GetMaxDisplayLimit())) { // Collapsible list $aExtraParams['display_limit'] = true; $sHtml .= '
'.Dict::Format('UI:CountOfResults', $oSet->Count()).''.Dict::S('UI:CollapseList').''; } $aExtraParams['truncated'] = false; // To expand the full list when clicked $sExtraParamsExpand = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them $oPage->add_ready_script( <<GetFilter()); $sColspan = 'colspan="2"'; $aMenuExtraParams = $aExtraParams; if (!empty($sLinkageAttribute)) { //$aMenuExtraParams['linkage'] = $sLinkageAttribute; $aMenuExtraParams = $aExtraParams; } $sHtml .= $oMenuBlock->GetRenderContent($oPage, $aMenuExtraParams, $iListId); $sHtml .= '
"; $sHtml .= $oPage->GetTable($aAttribs, $aValues); $sHtml .= '
'; return $sHtml; } public static function GetDisplayExtendedSet(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { static $iListId = 0; $iListId++; $aList = array(); // Initialize and check the parameters $bViewLink = isset($aExtraParams['view_link']) ? $aExtraParams['view_link'] : true; $bDisplayMenu = isset($aExtraParams['menu']) ? $aExtraParams['menu'] == true : true; // Check if there is a list of aliases to limit the display to... $aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',', $aExtraParams['display_aliases']) : array(); $sHtml = ''; $oAppContext = new ApplicationContext(); $aClasses = $oSet->GetFilter()->GetSelectedClasses(); $aAuthorizedClasses = array(); foreach($aClasses as $sAlias => $sClassName) { if ( (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) && ( (count($aDisplayAliases) == 0) || (in_array($sAlias, $aDisplayAliases))) ) { $aAuthorizedClasses[$sAlias] = $sClassName; } } $aAttribs = array(); foreach($aAuthorizedClasses as $sAlias => $sClassName) // TO DO: check if the user has enough rights to view the classes of the list... { $aList[$sClassName] = MetaModel::GetZListItems($sClassName, 'list'); if ($bViewLink) { $aAttribs['key_'.$sAlias] = array('label' => MetaModel::GetName($sClassName), 'description' => ''); } foreach($aList[$sClassName] as $sAttCode) { $aAttribs[$sAttCode.'_'.$sAlias] = array('label' => MetaModel::GetLabel($sClassName, $sAttCode), 'description' => MetaModel::GetDescription($sClassName, $sAttCode)); } } $aValues = array(); $oSet->Seek(0); $bDisplayLimit = isset($aExtraParams['display_limit']) ? $aExtraParams['display_limit'] : true; $iMaxObjects = -1; if ($bDisplayLimit) { if ($oSet->Count() > MetaModel::GetConfig()->GetMaxDisplayLimit()) { $iMaxObjects = MetaModel::GetConfig()->GetMinDisplayLimit(); } } while (($aObjects = $oSet->FetchAssoc()) && ($iMaxObjects != 0)) { $aRow = array(); foreach($aAuthorizedClasses as $sAlias => $sClassName) // TO DO: check if the user has enough rights to view the classes of the list... { if ($bViewLink) { $aRow['key_'.$sAlias] = $aObjects[$sAlias]->GetHyperLink(); } foreach($aList[$sClassName] as $sAttCode) { $aRow[$sAttCode.'_'.$sAlias] = $aObjects[$sAlias]->GetAsHTML($sAttCode); } } $aValues[] = $aRow; $iMaxObjects--; } $sHtml .= ''; $sColspan = ''; if ($bDisplayMenu) { $oMenuBlock = new MenuBlock($oSet->GetFilter()); $sColspan = 'colspan="2"'; $aMenuExtraParams = $aExtraParams; if (!empty($sLinkageAttribute)) { $aMenuExtraParams = $aExtraParams; } if ($bDisplayLimit && ($oSet->Count() > MetaModel::GetConfig()->GetMaxDisplayLimit())) { // list truncated $divId = $aExtraParams['block_id']; $sFilter = $oSet->GetFilter()->serialize(); $aExtraParams['display_limit'] = false; // To expand the full list $sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them $sHtml .= ''; } $sHtml .= "'; $sHtml .= '
'.Dict::Format('UI:TruncatedResults', MetaModel::GetConfig()->GetMinDisplayLimit(), $oSet->Count()).'  '.Dict::S('UI:DisplayAll').''; $oPage->add_ready_script("$('#{$divId} table.listResults').addClass('truncated');"); $oPage->add_ready_script("$('#{$divId} table.listResults tr:last td').addClass('truncated');"); } else { // Full list $sHtml .= '
 '.Dict::Format('UI:CountOfResults', $oSet->Count()).''; } $sHtml .= $oMenuBlock->GetRenderContent($oPage, $aMenuExtraParams); $sHtml .= '
"; $sHtml .= $oPage->GetTable($aAttribs, $aValues); $sHtml .= '
'; return $sHtml; } static function DisplaySetAsCSV(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array()) { $oPage->add(self::GetSetAsCSV($oSet, $aParams)); } static function GetSetAsCSV(DBObjectSet $oSet, $aParams = array()) { $sSeparator = isset($aParams['separator']) ? $aParams['separator'] : ','; // default separator is comma $sTextQualifier = isset($aParams['text_qualifier']) ? $aParams['text_qualifier'] : '"'; // default text qualifier is double quote $aList = array(); $oAppContext = new ApplicationContext(); $aClasses = $oSet->GetFilter()->GetSelectedClasses(); $aAuthorizedClasses = array(); foreach($aClasses as $sAlias => $sClassName) { if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) { $aAuthorizedClasses[$sAlias] = $sClassName; } } $aAttribs = array(); $aHeader = array(); foreach($aAuthorizedClasses as $sAlias => $sClassName) { foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) { if ((($oAttDef->IsExternalField()) || ($oAttDef->IsWritable())) && $oAttDef->IsScalar()) { $aList[$sClassName][$sAttCode] = $oAttDef; } } $aHeader[] = 'id'; foreach($aList[$sClassName] as $sAttCode => $oAttDef) { $sStar = ''; if ($oAttDef->IsExternalField()) { $sExtKeyLabel = MetaModel::GetLabel($sClassName, $oAttDef->GetKeyAttCode()); $oExtKeyAttDef = MetaModel::GetAttributeDef($sClassName, $oAttDef->GetKeyAttCode()); if (!$oExtKeyAttDef->IsNullAllowed() && isset($aParams['showMandatoryFields'])) { $sStar = '*'; } $sRemoteAttLabel = MetaModel::GetLabel($oAttDef->GetTargetClass(), $oAttDef->GetExtAttCode()); $oTargetAttDef = MetaModel::GetAttributeDef($oAttDef->GetTargetClass(), $oAttDef->GetExtAttCode()); $sSuffix = ''; if ($oTargetAttDef->IsExternalKey()) { $sSuffix = '->id'; } $aHeader[] = $sExtKeyLabel.'->'.$sRemoteAttLabel.$sSuffix.$sStar; } else { if (!$oAttDef->IsNullAllowed() && isset($aParams['showMandatoryFields'])) { $sStar = '*'; } $aHeader[] = MetaModel::GetLabel($sClassName, $sAttCode).$sStar; } } } $sHtml = implode($sSeparator, $aHeader)."\n"; $oSet->Seek(0); while ($aObjects = $oSet->FetchAssoc()) { $aRow = array(); foreach($aAuthorizedClasses as $sAlias => $sClassName) { $oObj = $aObjects[$sAlias]; $aRow[] = $oObj->GetKey(); foreach($aList[$sClassName] as $sAttCode => $oAttDef) { $aRow[] = $oObj->GetAsCSV($sAttCode, $sSeparator, '\\'); } } $sHtml .= implode($sSeparator, $aRow)."\n"; } return $sHtml; } static function DisplaySetAsXML(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array()) { $oAppContext = new ApplicationContext(); $aClasses = $oSet->GetFilter()->GetSelectedClasses(); $aAuthorizedClasses = array(); foreach($aClasses as $sAlias => $sClassName) { if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) { $aAuthorizedClasses[$sAlias] = $sClassName; } } $aAttribs = array(); $aList = array(); $aList[$sClassName] = MetaModel::GetZListItems($sClassName, 'details'); $oPage->add("\n"); $oSet->Seek(0); while ($aObjects = $oSet->FetchAssoc()) { if (count($aAuthorizedClasses) > 1) { $oPage->add("\n"); } foreach($aAuthorizedClasses as $sAlias => $sClassName) { $oObj = $aObjects[$sAlias]; $sClassName = get_class($oObj); $oPage->add("<$sClassName alias=\"$sAlias\" id=\"".$oObj->GetKey()."\">\n"); foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode=>$oAttDef) { if (($oAttDef->IsWritable()) && ($oAttDef->IsScalar())) { $sValue = $oObj->GetAsXML($sAttCode); $oPage->add("<$sAttCode>$sValue\n"); } } $oPage->add("\n"); } if (count($aAuthorizedClasses) > 1) { $oPage->add("\n"); } } $oPage->add("\n"); } public static function DisplaySearchForm(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { $oPage->add(self::GetSearchForm($oPage, $oSet, $aExtraParams)); } public static function GetSearchForm(WebPage $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { static $iSearchFormId = 0; $oAppContext = new ApplicationContext(); $sHtml = ''; $numCols=4; $sClassName = $oSet->GetFilter()->GetClass(); // Romain: temporarily removed the tab "OQL query" because it was not finalized // (especially when used to add a link) /* $sHtml .= "\n"; */ // Simple search form if (isset($aExtraParams['currentId'])) { $sSearchFormId = $aExtraParams['currentId']; } else { $iSearchFormId = $oPage->GetUniqueId(); $sSearchFormId = 'SimpleSearchForm'.$iSearchFormId; $sHtml .= "
\n"; } // Check if the current class has some sub-classes if (isset($aExtraParams['baseClass'])) { $sRootClass = $aExtraParams['baseClass']; } else { $sRootClass = $sClassName; } $aSubClasses = MetaModel::GetSubclasses($sRootClass); if (count($aSubClasses) > 0) { $aOptions = array(); $aOptions[MetaModel::GetName($sRootClass)] = "
\n"; } /* // OQL query builder $sHtml .= "
\n"; $sHtml .= "

".Dict::S('UI:OQLQueryBuilderTitle')."

\n"; $sHtml .= "
\n"; $sHtml .= "\n"; $sHtml .= "\n"; $sHtml .= "\n"; foreach($aExtraParams as $sName => $sValue) { $sHtml .= "\n"; } $sHtml .= "\n"; $sHtml .= $oAppContext->GetForForm(); $sHtml .= "
 \n"; $sHtml .= "
\n"; $sHtml .= "
\n"; */ return $sHtml; } public static function GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value = '', $sDisplayValue = '', $iId = '', $sNameSuffix = '', $iFlags = 0, $aArgs = array()) { static $iInputId = 0; $sFieldPrefix = ''; $sFormPrefix = isset($aArgs['formPrefix']) ? $aArgs['formPrefix'] : ''; $sFieldPrefix = isset($aArgs['prefix']) ? $sFormPrefix.$aArgs['prefix'] : $sFormPrefix; if (isset($aArgs[$sAttCode]) && empty($value)) { // default value passed by the context (either the app context of the operation) $value = $aArgs[$sAttCode]; } if (!empty($iId)) { $iInputId = $iId; } else { $iInputId = $oPage->GetUniqueId(); } if (!$oAttDef->IsExternalField()) { $bMandatory = 'false'; if ( (!$oAttDef->IsNullAllowed()) || ($iFlags & OPT_ATT_MANDATORY)) { $bMandatory = 'true'; } $sValidationField = ""; $sHelpText = $oAttDef->GetHelpOnEdition(); $aEventsList = array(); switch($oAttDef->GetEditClass()) { case 'Date': case 'DateTime': $aEventsList[] ='validate'; $aEventsList[] ='keyup'; $aEventsList[] ='change'; $sHTMLValue = " {$sValidationField}"; break; case 'Password': $aEventsList[] ='validate'; $aEventsList[] ='keyup'; $aEventsList[] ='change'; $sHTMLValue = " {$sValidationField}"; break; case 'Text': $aEventsList[] ='validate'; $aEventsList[] ='keyup'; $aEventsList[] ='change'; $sEditValue = $oAttDef->GetEditValue($value); $sHTMLValue = "
{$sValidationField}
"; break; case 'HTML': $oWidget = new UIHTMLEditorWidget($iId, $sAttCode, $sNameSuffix, $sFieldPrefix, $sHelpText, $sValidationField, $value, $bMandatory); $sHTMLValue = $oWidget->Display($oPage, $aArgs); break; case 'LinkedSet': $aEventsList[] ='validate'; $aEventsList[] ='change'; $oWidget = new UILinksWidget($sClass, $sAttCode, $iId, $sNameSuffix, $oAttDef->DuplicatesAllowed()); $sHTMLValue = $oWidget->Display($oPage, $value); break; case 'Document': $aEventsList[] ='validate'; $aEventsList[] ='change'; $oDocument = $value; // Value is an ormDocument object $sFileName = ''; if (is_object($oDocument)) { $sFileName = $oDocument->GetFileName(); } $iMaxFileSize = utils::ConvertToBytes(ini_get('upload_max_filesize')); $sHTMLValue = "\n"; $sHTMLValue .= "\n"; $sHTMLValue .= "$sFileName
\n"; $sHTMLValue .= " {$sValidationField}\n"; break; case 'List': // Not editable for now... $sHTMLValue = ''; break; case 'One Way Password': $aEventsList[] ='validate'; $oWidget = new UIPasswordWidget($sAttCode, $iId, $sNameSuffix); $sHTMLValue = $oWidget->Display($oPage, $aArgs); // Event list & validation is handled directly by the widget break; case 'ExtKey': $aEventsList[] ='validate'; $aEventsList[] ='change'; $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); $iFieldSize = $oAttDef->GetMaxSize(); $iMaxComboLength = $oAttDef->GetMaximumComboLength(); $oWidget = new UIExtKeyWidget($sAttCode, $sClass, $oAttDef->GetLabel(), $aAllowedValues, $value, $iId, $bMandatory, $sNameSuffix, $sFieldPrefix, $sFormPrefix); $sHTMLValue = $oWidget->Display($oPage, $aArgs); break; case 'String': default: $aEventsList[] ='validate'; // #@# todo - add context information (depending on dimensions) $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); $iFieldSize = $oAttDef->GetMaxSize(); if ($aAllowedValues !== null) { // Discrete list of values, use a SELECT $sHTMLValue = " {$sValidationField}\n"; $aEventsList[] ='change'; } else { $sHTMLValue = " {$sValidationField}"; $aEventsList[] ='keyup'; $aEventsList[] ='change'; } break; } $sPattern = addslashes($oAttDef->GetValidationPattern()); //'^([0-9]+)$'; if (!empty($aEventsList)) { $sNullValue = $oAttDef->GetNullValue(); if (!is_numeric($sNullValue)) { $sNullValue = "'$sNullValue'"; // Add quotes to turn this into a JS string if it's not a number } $oPage->add_ready_script("$('#$iId').bind('".implode(' ', $aEventsList)."', function(evt, sFormId) { return ValidateField('$iId', '$sPattern', $bMandatory, sFormId, $sNullValue) } );\n"); // Bind to a custom event: validate } $aDependencies = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that depend on the current one if (count($aDependencies) > 0) { $oPage->add_ready_script("$('#$iId').bind('change', function(evt, sFormId) { return oWizardHelper{$sFormPrefix}.UpdateDependentFields(['".implode("','", $aDependencies)."']) } );\n"); // Bind to a custom event: validate } } return "
{$sHTMLValue}
"; } public function DisplayModifyForm(WebPage $oPage, $aExtraParams = array()) { static $iGlobalFormId = 1; $iGlobalFormId++; $sPrefix = ''; if (isset($aExtraParams['formPrefix'])) { $sPrefix = $aExtraParams['formPrefix']; } $this->m_iFormId = $sPrefix.$iGlobalFormId; $sClass = get_class($this); $oAppContext = new ApplicationContext(); $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); $iKey = $this->GetKey(); $aDetails = array(); $aFieldsMap = array(); if (!isset($aExtraParams['action'])) { $sFormAction = $_SERVER['SCRIPT_NAME']; // No parameter in the URL, the only parameter will be the ones passed through the form } else { $sFormAction = $aExtraParams['action']; } $oPage->add("
m_iFormId}\" enctype=\"multipart/form-data\" method=\"post\" onSubmit=\"return CheckFields('form_{$this->m_iFormId}', true)\">\n"); $oPage->AddTabContainer(OBJECT_PROPERTIES_TAB, $sPrefix); $oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB); $oPage->SetCurrentTab(Dict::S('UI:PropertiesTab')); // $aDetailsList = $this->FLattenZList(MetaModel::GetZListItems($sClass, 'details')); //$aFullList = MetaModel::ListAttributeDefs($sClass); $aList = array(); // Compute the list of properties to display, first the attributes in the 'details' list, then // all the remaining attributes that are not external fields // foreach($aDetailsList as $sAttCode) // { // $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); // if (!$oAttDef->IsExternalField()) // { // $aList[] = $sAttCode; // } // } $aDetailsList = MetaModel::GetZListItems($sClass, 'details'); $aDetailsStruct = self::ProcessZlist($aDetailsList, array('UI:PropertiesTab' => array()), 'UI:PropertiesTab', 'col1', ''); $sHtml = ''; $aDetails = array(); foreach($aDetailsStruct as $sTab => $aCols ) { $aDetails[$sTab] = array(); ksort($aCols); $oPage->SetCurrentTab(Dict::S($sTab)); $oPage->add(''); foreach($aCols as $sColIndex => $aFieldsets) { $sLabel = ''; $sPreviousLabel = ''; $aDetails[$sTab][$sColIndex] = array(); $oPage->add(''); } $oPage->add('
'); //$aDetails[$sTab][$sColIndex] = array(); foreach($aFieldsets as $sFieldsetName => $aFields) { if (!empty($sFieldsetName) && ($sFieldsetName[0]!='_')) { $sLabel = $sFieldsetName; } else { $sLabel = ''; } if ($sLabel != $sPreviousLabel) { if (!empty($sPreviousLabel)) { $oPage->add('
'); $oPage->add(''.Dict::S($sPreviousLabel).''); } $oPage->Details($aDetails[$sTab][$sColIndex]); if (!empty($sPreviousLabel)) { $oPage->add('
'); } $aDetails[$sTab][$sColIndex] = array(); $sPreviousLabel = $sLabel; } foreach($aFields as $sAttCode) { $aVal = null; $iFlags = $this->GetAttributeFlags($sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); if ( (!$oAttDef->IsLinkSet()) && (($iFlags & OPT_ATT_HIDDEN) == 0)) { if ($oAttDef->IsWritable()) { if ($sStateAttCode == $sAttCode) { // State attribute is always read-only from the UI $sHTMLValue = $this->GetStateLabel(); $aVal = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue); } else { $iFlags = $this->GetAttributeFlags($sAttCode); $sInputId = $this->m_iFormId.'_'.$sAttCode; if ($iFlags & OPT_ATT_HIDDEN) { // Attribute is hidden, add a hidden input $oPage->add(''); $aFieldsMap[$sAttCode] = $sInputId; } else { if ($iFlags & OPT_ATT_READONLY) { // Attribute is read-only $sHTMLValue = $this->GetAsHTML($sAttCode); $sHTMLValue .= ''; $aFieldsMap[$sAttCode] = $sInputId; } else { $sValue = $this->Get($sAttCode); $sDisplayValue = $this->GetEditValue($sAttCode); $aArgs = array('this' => $this, 'formPrefix' => $sPrefix); $sHTMLValue = "".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).''; $aFieldsMap[$sAttCode] = $sInputId; } $aVal = array('label' => ''.$oAttDef->GetLabel().'', 'value' => $sHTMLValue); } } } else { $aVal = array('label' => ''.$oAttDef->GetLabel().'', 'value' => $this->GetAsHTML($sAttCode)); } } if ($aVal != null) { // The field is visible, add it to the current column $aDetails[$sTab][$sColIndex][] = $aVal; } } } if (!empty($sPreviousLabel)) { $oPage->add('
'); $oPage->add(''.Dict::S($sPreviousLabel).''); } $oPage->Details($aDetails[$sTab][$sColIndex]); if (!empty($sPreviousLabel)) { $oPage->add('
'); } $oPage->add('
'); } // Now display the relations, one tab per relation if (!isset($aExtraParams['noRelations'])) { $this->DisplayBareRelations($oPage, true); // Edit mode } $oPage->SetCurrentTab(''); $oPage->add("\n"); $oPage->add("\n"); foreach($aExtraParams as $sName => $value) { $oPage->add("\n"); } $oPage->add($oAppContext->GetForForm()); if ($iKey > 0) { // The object already exists in the database, it's modification $oPage->add("\n"); $oPage->add("\n"); // $oPage->add("    \n"); $oPage->add("    \n"); $oPage->add("\n"); } else { // The object does not exist in the database it's a creation $oPage->add("\n"); // $oPage->add("    \n"); $oPage->add("    \n"); $oPage->add("\n"); } // Hook the cancel button via jQuery so that it can be unhooked easily as well if needed $sDefaultUrl = '../pages/UI.php?operation=cancel'; $oPage->add_ready_script("$('#form_{$this->m_iFormId} button.cancel').click( function() { BackToDetails('$sClass', $iKey, '$sDefaultUrl')} );"); $oPage->add("
\n"); $iFieldsCount = count($aFieldsMap); $sJsonFieldsMap = json_encode($aFieldsMap); $oPage->add_script( <<add_ready_script( <<m_iFormId}', false); EOF ); } public static function DisplayCreationForm(WebPage $oPage, $sClass, $oObjectToClone = null, $aArgs = array(), $aExtraParams = array()) { $oAppContext = new ApplicationContext(); $sClass = ($oObjectToClone == null) ? $sClass : get_class($oObjectToClone); $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); $aStates = MetaModel::EnumStates($sClass); if ($oObjectToClone == null) { $oObj = MetaModel::NewObject($sClass); if (!empty($sStateAttCode)) { $sTargetState = MetaModel::GetDefaultState($sClass); $oObj->Set($sStateAttCode, $sTargetState); } } else { $oObj = clone $oObjectToClone; } // Pre-fill the object with default values, when there is only on possible choice // AND the field is mandatory (otherwise there is always the possiblity to let it empty) $aArgs['this'] = $oObj; $aDetailsList = self::FLattenZList(MetaModel::GetZListItems($sClass, 'details')); // Order the fields based on their dependencies $aDeps = array(); foreach($aDetailsList as $sAttCode) { $aDeps[$sAttCode] = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode); } $aList = self::OrderDependentFields($aDeps); // Now fill-in the fields with default/supplied values foreach($aList as $sAttCode) { $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); if (isset($aArgs['default'][$sAttCode])) { $oObj->Set($sAttCode, $aArgs['default'][$sAttCode]); } elseif (count($aAllowedValues) == 1) { // If the field is mandatory, set it to the only possible value $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $iFlags = $oObj->GetAttributeFlags($sAttCode); if ( (!$oAttDef->IsNullAllowed()) || ($iFlags & OPT_ATT_MANDATORY)) { $aValues = array_keys($aAllowedValues); $oObj->Set($sAttCode, $aValues[0]); } } } return $oObj->DisplayModifyForm( $oPage, $aExtraParams); } protected static function ProcessZlist($aList, $aDetails, $sCurrentTab, $sCurrentCol, $sCurrentSet) { //echo "
ZList: ";
		//print_r($aList);
		//echo "
\n"; $index = 0; foreach($aList as $sKey => $value) { if (is_array($value)) { if (preg_match('/^(.*):(.*)$/U', $sKey, $aMatches)) { $sCode = $aMatches[1]; $sName = $aMatches[2]; switch($sCode) { case 'tab': //echo "

Found a tab: $sName ($sKey)

\n"; if(!isset($aDetails[$sName])) { $aDetails[$sName] = array('col1' => array()); } $aDetails = self::ProcessZlist($value, $aDetails, $sName, 'col1', ''); break; case 'fieldset': //echo "

Found a fieldset: $sName ($sKey)

\n"; if(!isset($aDetailsStruct[$sCurrentTab][$sCurrentCol][$sName])) { $aDetails[$sCurrentTab][$sCurrentCol][$sName] = array(); } $aDetails = self::ProcessZlist($value, $aDetails, $sCurrentTab, $sCurrentCol, $sName); break; default: case 'col': //echo "

Found a column: $sName ($sKey)

\n"; if(!isset($aDetails[$sCurrentTab][$sName])) { $aDetails[$sCurrentTab][$sName] = array(); } $aDetails = self::ProcessZlist($value, $aDetails, $sCurrentTab, $sName, ''); break; } } } else { //echo "

Scalar value: $value, in [$sCurrentTab][$sCurrentCol][$sCurrentSet][]

\n"; if (empty($sCurrentSet)) { $aDetails[$sCurrentTab][$sCurrentCol]['_'.$index][] = $value; } else { $aDetails[$sCurrentTab][$sCurrentCol][$sCurrentSet][] = $value; } } $index++; } return $aDetails; } protected static function FlattenZList($aList) { $aResult = array(); foreach($aList as $value) { if (!is_array($value)) { $aResult[] = $value; } else { $aResult = array_merge($aResult,self::FlattenZList($value)); } } return $aResult; } protected function GetFieldAsHtml($sClass, $sAttCode, $sStateAttCode) { $retVal = null; $iFlags = $this->GetAttributeFlags($sAttCode); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); if ( (!$oAttDef->IsLinkSet()) && (($iFlags & OPT_ATT_HIDDEN) == 0) ) { // The field is visible in the current state of the object if ($sStateAttCode == $sAttCode) { // Special display for the 'state' attribute itself $sDisplayValue = $this->GetStateLabel(); } else if ($oAttDef->GetEditClass() == 'Document') { $oDocument = $this->Get($sAttCode); $sDisplayValue = $this->GetAsHTML($sAttCode); $sDisplayValue .= "
".Dict::Format('UI:OpenDocumentInNewWindow_', $oDocument->GetDisplayLink(get_class($this), $this->GetKey(), $sAttCode)).", \n"; $sDisplayValue .= "
".Dict::Format('UI:DownloadDocument_', $oDocument->GetDisplayLink(get_class($this), $this->GetKey(), $sAttCode)).", \n"; } else { $sDisplayValue = $this->GetAsHTML($sAttCode); } $retVal = array('label' => ''.MetaModel::GetLabel($sClass, $sAttCode).'', 'value' => $sDisplayValue); } return $retVal; } /** * Displays a blob document *inline* (if possible, depending on the type of the document) * @return string */ public function DisplayDocumentInline(WebPage $oPage, $sAttCode) { $oDoc = $this->Get($sAttCode); $sClass = get_class($this); $Id = $this->GetKey(); switch ($oDoc->GetMainMimeType()) { case 'text': case 'html': $data = $oDoc->GetData(); switch($oDoc->GetMimeType()) { case 'text/html': case 'text/xml': $oPage->add("\n"); break; default: $oPage->add("
".htmlentities(MyHelpers::beautifulstr($data, 1000, true))."
\n"); } break; case 'application': switch($oDoc->GetMimeType()) { case 'application/pdf': $oPage->add("\n"); break; default: $oPage->add(Dict::S('UI:Document:NoPreview')); } break; case 'image': $oPage->add("\n"); break; default: $oPage->add(Dict::S('UI:Document:NoPreview')); } } /** * This function returns a 'hilight' CSS class, used to hilight a given row in a table * There are currently (i.e defined in the CSS) 4 possible values HILIGHT_CLASS_CRITICAL, * HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE * To Be overridden by derived classes * @param void * @return String The desired higlight class for the object/row */ public function GetHilightClass() { // Possible return values are: // HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE return HILIGHT_CLASS_NONE; // Not hilighted by default } /** * Re-order the fields based on their inter-dependencies * @params hash @aFields field_code => array_of_depencies * @return array Ordered array of fields or throws an exception */ public static function OrderDependentFields($aFields) { $bCircular = false; $aResult = array(); $iCount = 0; do { $bSet = false; $iCount++; foreach($aFields as $sFieldCode => $aDeps) { foreach($aDeps as $key => $sDependency) { if (in_array($sDependency, $aResult)) { // Dependency is resolved, remove it unset($aFields[$sFieldCode][$key]); } } if (count($aFields[$sFieldCode]) == 0) { // No more pending depencies for this field, add it to the list $aResult[] = $sFieldCode; unset($aFields[$sFieldCode]); $bSet = true; } } } while($bSet && (count($aFields) > 0)); if (count($aFields) > 0) { $sMessage = "Error: Circular dependencies between the fields !
".print_r($aFields, true)."
"; throw(new Exception($sMessage)); } return $aResult; } /** * Maps the given context parameter name to the appropriate filter/search code for this class * @param string $sContextParam Name of the context parameter, i.e. 'org_id' * @return string Filter code, i.e. 'customer_id' */ public static function MapContextParam($sContextParam) { if ($sContextParam == 'menu') { return null; } else { return $sContextParam; } } /** * Updates the object from the POSTed parameters */ public function UpdateObject($sFormPrefix = '') { foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef) { if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect()) { $aLinks = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", ''); $sLinkedClass = $oAttDef->GetLinkedClass(); $sExtKeyToRemote = $oAttDef->GetExtKeyToRemote(); $sExtKeyToMe = $oAttDef->GetExtKeyToMe(); $oLinkedSet = DBObjectSet::FromScratch($sLinkedClass); if (is_array($aLinks)) { foreach($aLinks as $id => $aData) { if (is_numeric($id)) { if ($id < 0) { // New link to be created, the opposite of the id (-$id) is the ID of the remote object $oLink = MetaModel::NewObject($sLinkedClass); $oLink->Set($sExtKeyToRemote, -$id); $oLink->Set($sExtKeyToMe, $this->GetKey()); } else { // Existing link, potentially to be updated... $oLink = MetaModel::GetObject($sLinkedClass, $id); } // Now populate the attributes foreach($aData as $sName => $value) { if (MetaModel::IsValidAttCode($sLinkedClass, $sName)) { $oLinkAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sName); if ($oLinkAttDef->IsWritable()) { $oLink->Set($sName, $value); } } } $oLinkedSet->AddObject($oLink); } } } $this->Set($sAttCode, $oLinkedSet); } else if ($oAttDef->IsWritable()) { $iFlags = $this->GetAttributeFlags($sAttCode); if ($iFlags & (OPT_ATT_HIDDEN | OPT_ATT_READONLY)) { // Non-visible, or read-only attribute, do nothing } elseif ($oAttDef->GetEditClass() == 'Document') { // There should be an uploaded file with the named attr_ $oDocument = utils::ReadPostedDocument("file_{$sFormPrefix}{$sAttCode}"); if (!$oDocument->IsEmpty()) { // A new file has been uploaded $this->Set($sAttCode, $oDocument); } } elseif ($oAttDef->GetEditClass() == 'One Way Password') { // Check if the password was typed/changed $bChanged = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_changed", false); if ($bChanged) { // The password has been changed or set $rawValue = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null); $this->Set($sAttCode, $rawValue); } } else { $rawValue = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null); if (!is_null($rawValue)) { $aAttributes[$sAttCode] = trim($rawValue); $previousValue = $this->Get($sAttCode); if ($previousValue !== $aAttributes[$sAttCode]) { $this->Set($sAttCode, $aAttributes[$sAttCode]); } } } } } } } ?>