public function GetLabel($sClass, $sAttCodeEx)
 {
     return MetaModel::GetLabel($sClass, $sAttCodeEx);
 }
예제 #2
0
 protected function GetHTMLTableConfig($aColumns, $sSelectMode, $bViewLink)
 {
     $aAttribs = array();
     if ($sSelectMode == 'multiple') {
         $aAttribs['form::select'] = array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->iListId}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>", 'description' => Dict::S('UI:SelectAllToggle+'));
     } else {
         if ($sSelectMode == 'single') {
             $aAttribs['form::select'] = array('label' => "", 'description' => '');
         }
     }
     foreach ($this->aClassAliases as $sAlias => $sClassName) {
         foreach ($aColumns[$sAlias] as $sAttCode => $aData) {
             if ($aData['checked']) {
                 if ($sAttCode == '_key_') {
                     $aAttribs['key_' . $sAlias] = array('label' => MetaModel::GetName($sClassName), 'description' => '');
                 } else {
                     $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
                     $aAttribs[$sAttCode . '_' . $sAlias] = array('label' => MetaModel::GetLabel($sClassName, $sAttCode), 'description' => $oAttDef->GetOrderByHint());
                 }
             }
         }
     }
     return $aAttribs;
 }
예제 #3
0
    public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId)
    {
        $sHtml = '';
        // Add the extra params into the filter if they make sense for such a filter
        $bDoSearch = utils::ReadParam('dosearch', false);
        if ($this->m_oSet == null) {
            $aQueryParams = array();
            if (isset($aExtraParams['query_params'])) {
                $aQueryParams = $aExtraParams['query_params'];
            }
            if ($this->m_sStyle != 'links') {
                $oAppContext = new ApplicationContext();
                $sClass = $this->m_oFilter->GetClass();
                $aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($sClass));
                $aCallSpec = array($sClass, 'MapContextParam');
                if (is_callable($aCallSpec)) {
                    foreach ($oAppContext->GetNames() as $sContextParam) {
                        $sParamCode = call_user_func($aCallSpec, $sContextParam);
                        //Map context parameter to the value/filter code depending on the class
                        if (!is_null($sParamCode)) {
                            $sParamValue = $oAppContext->GetCurrentValue($sContextParam, null);
                            if (!is_null($sParamValue)) {
                                $aExtraParams[$sParamCode] = $sParamValue;
                            }
                        }
                    }
                }
                foreach ($aFilterCodes as $sFilterCode) {
                    $externalFilterValue = utils::ReadParam($sFilterCode, '', false, 'raw_data');
                    $condition = null;
                    if (isset($aExtraParams[$sFilterCode])) {
                        $condition = $aExtraParams[$sFilterCode];
                    }
                    if ($bDoSearch && $externalFilterValue != "") {
                        // Search takes precedence over context params...
                        unset($aExtraParams[$sFilterCode]);
                        if (!is_array($externalFilterValue)) {
                            $condition = trim($externalFilterValue);
                        } else {
                            if (count($externalFilterValue) == 1) {
                                $condition = trim($externalFilterValue[0]);
                            } else {
                                $condition = $externalFilterValue;
                            }
                        }
                    }
                    if (!is_null($condition)) {
                        $sOpCode = null;
                        // default operator
                        if (is_array($condition)) {
                            // Multiple values, add them as AND X IN (v1, v2, v3...)
                            $sOpCode = 'IN';
                        }
                        $this->AddCondition($sFilterCode, $condition, $sOpCode);
                    }
                }
                if ($bDoSearch) {
                    // Keep the table_id identifying this table if we're performing a search
                    $sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data');
                    if ($sTableId != null) {
                        $aExtraParams['table_id'] = $sTableId;
                    }
                }
            }
            $aOrderBy = array();
            if (isset($aExtraParams['order_by'])) {
                // Convert the string describing the order_by parameter into an array
                // The syntax is +attCode1,-attCode2
                // attCode1 => ascending, attCode2 => descending
                $aTemp = explode(',', $aExtraParams['order_by']);
                foreach ($aTemp as $sTemp) {
                    $aMatches = array();
                    if (preg_match('/^([+-])?(.+)$/', $sTemp, $aMatches)) {
                        $bAscending = true;
                        if ($aMatches[1] == '-') {
                            $bAscending = false;
                        }
                        $aOrderBy[$aMatches[2]] = $bAscending;
                    }
                }
            }
            $this->m_oSet = new CMDBObjectSet($this->m_oFilter, $aOrderBy, $aQueryParams);
        }
        switch ($this->m_sStyle) {
            case 'count':
                if (isset($aExtraParams['group_by'])) {
                    if (isset($aExtraParams['group_by_label'])) {
                        $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
                        $sGroupByLabel = $aExtraParams['group_by_label'];
                    } else {
                        // Backward compatibility: group_by is simply a field id
                        $sAlias = $this->m_oFilter->GetClassAlias();
                        $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
                        $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
                    }
                    $aGroupBy = array();
                    $aGroupBy['grouped_by_1'] = $oGroupByExp;
                    $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true);
                    $aRes = CMDBSource::QueryToArray($sSql);
                    $aGroupBy = array();
                    $aLabels = array();
                    $aValues = array();
                    $iTotalCount = 0;
                    foreach ($aRes as $iRow => $aRow) {
                        $sValue = $aRow['grouped_by_1'];
                        $aValues[$iRow] = $sValue;
                        $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
                        $aLabels[$iRow] = $sHtmlValue;
                        $aGroupBy[$iRow] = (int) $aRow['_itop_count_'];
                        $iTotalCount += $aRow['_itop_count_'];
                    }
                    $aData = array();
                    $oAppContext = new ApplicationContext();
                    $sParams = $oAppContext->GetForLink();
                    foreach ($aGroupBy as $iRow => $iCount) {
                        // Build the search for this subset
                        $oSubsetSearch = $this->m_oFilter->DeepClone();
                        $oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
                        $oSubsetSearch->AddConditionExpression($oCondition);
                        $sFilter = urlencode($oSubsetSearch->serialize());
                        $aData[] = array('group' => $aLabels[$iRow], 'value' => "<a href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=search&dosearch=1&{$sParams}&filter={$sFilter}\">{$iCount}</a>");
                        // TO DO: add the context information
                    }
                    $aAttribs = array('group' => array('label' => $sGroupByLabel, 'description' => ''), 'value' => array('label' => Dict::S('UI:GroupBy:Count'), 'description' => Dict::S('UI:GroupBy:Count+')));
                    $sFormat = isset($aExtraParams['format']) ? $aExtraParams['format'] : 'UI:Pagination:HeaderNoSelection';
                    $sHtml .= $oPage->GetP(Dict::Format($sFormat, $iTotalCount));
                    $sHtml .= $oPage->GetTable($aAttribs, $aData);
                } else {
                    // Simply count the number of elements in the set
                    $iCount = $this->m_oSet->Count();
                    $sFormat = 'UI:CountOfObjects';
                    if (isset($aExtraParams['format'])) {
                        $sFormat = $aExtraParams['format'];
                    }
                    $sHtml .= $oPage->GetP(Dict::Format($sFormat, $iCount));
                }
                break;
            case 'join':
                $aDisplayAliases = isset($aExtraParams['display_aliases']) ? explode(',', $aExtraParams['display_aliases']) : array();
                if (!isset($aExtraParams['group_by'])) {
                    $sHtml .= $oPage->GetP(Dict::S('UI:Error:MandatoryTemplateParameter_group_by'));
                } else {
                    $aGroupByFields = array();
                    $aGroupBy = explode(',', $aExtraParams['group_by']);
                    foreach ($aGroupBy as $sGroupBy) {
                        $aMatches = array();
                        if (preg_match('/^(.+)\\.(.+)$/', $sGroupBy, $aMatches) > 0) {
                            $aGroupByFields[] = array('alias' => $aMatches[1], 'att_code' => $aMatches[2]);
                        }
                    }
                    if (count($aGroupByFields) == 0) {
                        $sHtml .= $oPage->GetP(Dict::Format('UI:Error:InvalidGroupByFields', $aExtraParams['group_by']));
                    } else {
                        $aResults = array();
                        $aCriteria = array();
                        while ($aObjects = $this->m_oSet->FetchAssoc()) {
                            $aKeys = array();
                            foreach ($aGroupByFields as $aField) {
                                $sAlias = $aField['alias'];
                                if (is_null($aObjects[$sAlias])) {
                                    $aKeys[$sAlias . '.' . $aField['att_code']] = '';
                                } else {
                                    $aKeys[$sAlias . '.' . $aField['att_code']] = $aObjects[$sAlias]->Get($aField['att_code']);
                                }
                            }
                            $sCategory = implode($aKeys, ' ');
                            $aResults[$sCategory][] = $aObjects;
                            $aCriteria[$sCategory] = $aKeys;
                        }
                        $sHtml .= "<table>\n";
                        // Construct a new (parametric) query that will return the content of this block
                        $oBlockFilter = $this->m_oFilter->DeepClone();
                        $aExpressions = array();
                        $index = 0;
                        foreach ($aGroupByFields as $aField) {
                            $aExpressions[] = '`' . $aField['alias'] . '`.`' . $aField['att_code'] . '` = :param' . $index++;
                        }
                        $sExpression = implode(' AND ', $aExpressions);
                        $oExpression = Expression::FromOQL($sExpression);
                        $oBlockFilter->AddConditionExpression($oExpression);
                        $aExtraParams['menu'] = false;
                        foreach ($aResults as $sCategory => $aObjects) {
                            $sHtml .= "<tr><td><h1>{$sCategory}</h1></td></tr>\n";
                            if (count($aDisplayAliases) == 1) {
                                $aSimpleArray = array();
                                foreach ($aObjects as $aRow) {
                                    $oObj = $aRow[$aDisplayAliases[0]];
                                    if (!is_null($oObj)) {
                                        $aSimpleArray[] = $oObj;
                                    }
                                }
                                $oSet = CMDBObjectSet::FromArray($this->m_oFilter->GetClass(), $aSimpleArray);
                                $sHtml .= "<tr><td>" . cmdbAbstractObject::GetDisplaySet($oPage, $oSet, $aExtraParams) . "</td></tr>\n";
                            } else {
                                $index = 0;
                                $aArgs = array();
                                foreach ($aGroupByFields as $aField) {
                                    $aArgs['param' . $index] = $aCriteria[$sCategory][$aField['alias'] . '.' . $aField['att_code']];
                                    $index++;
                                }
                                $oSet = new CMDBObjectSet($oBlockFilter, array(), $aArgs);
                                $sHtml .= "<tr><td>" . cmdbAbstractObject::GetDisplayExtendedSet($oPage, $oSet, $aExtraParams) . "</td></tr>\n";
                            }
                        }
                        $sHtml .= "</table>\n";
                    }
                }
                break;
            case 'list':
                $aClasses = $this->m_oSet->GetSelectedClasses();
                $aAuthorizedClasses = array();
                if (count($aClasses) > 1) {
                    // Check the classes that can be read (i.e authorized) by this user...
                    foreach ($aClasses as $sAlias => $sClassName) {
                        if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $this->m_oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) {
                            $aAuthorizedClasses[$sAlias] = $sClassName;
                        }
                    }
                    if (count($aAuthorizedClasses) > 0) {
                        if ($this->m_oSet->Count() > 0) {
                            $sHtml .= cmdbAbstractObject::GetDisplayExtendedSet($oPage, $this->m_oSet, $aExtraParams);
                        } else {
                            // Empty set
                            $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay'));
                        }
                    } else {
                        // Not authorized
                        $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay'));
                    }
                } else {
                    // The list is made of only 1 class of objects, actions on the list are possible
                    if ($this->m_oSet->Count() > 0 && UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) {
                        $sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $aExtraParams);
                    } else {
                        $sHtml .= $oPage->GetP(Dict::S('UI:NoObjectToDisplay'));
                        $sClass = $this->m_oFilter->GetClass();
                        $bDisplayMenu = isset($aExtraParams['menu']) ? $aExtraParams['menu'] == true : true;
                        if ($bDisplayMenu) {
                            if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES) {
                                $sLinkTarget = '';
                                $oAppContext = new ApplicationContext();
                                $sParams = $oAppContext->GetForLink();
                                // 1:n links, populate the target object as a default value when creating a new linked object
                                if (isset($aExtraParams['target_attr'])) {
                                    $sLinkTarget = ' target="_blank" ';
                                    $aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id'];
                                }
                                $sDefault = '';
                                if (!empty($aExtraParams['default'])) {
                                    foreach ($aExtraParams['default'] as $sKey => $sValue) {
                                        $sDefault .= "&default[{$sKey}]={$sValue}";
                                    }
                                }
                                $sHtml .= $oPage->GetP("<a{$sLinkTarget} href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=new&class={$sClass}&{$sParams}{$sDefault}\">" . Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sClass)) . "</a>\n");
                            }
                        }
                    }
                }
                break;
            case 'links':
                //$bDashboardMode = isset($aExtraParams['dashboard']) ? ($aExtraParams['dashboard'] == 'true') : false;
                //$bSelectMode = isset($aExtraParams['select']) ? ($aExtraParams['select'] == 'true') : false;
                if ($this->m_oSet->Count() > 0 && UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_READ, $this->m_oSet) == UR_ALLOWED_YES) {
                    //$sLinkage = isset($aExtraParams['linkage']) ? $aExtraParams['linkage'] : '';
                    $sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $this->m_oSet, $aExtraParams);
                } else {
                    $sClass = $this->m_oFilter->GetClass();
                    $oAttDef = MetaModel::GetAttributeDef($sClass, $this->m_aParams['target_attr']);
                    $sTargetClass = $oAttDef->GetTargetClass();
                    $sHtml .= $oPage->GetP(Dict::Format('UI:NoObject_Class_ToDisplay', MetaModel::GetName($sTargetClass)));
                    $bDisplayMenu = isset($this->m_aParams['menu']) ? $this->m_aParams['menu'] == true : true;
                    if ($bDisplayMenu) {
                        if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY) == UR_ALLOWED_YES) {
                            $oAppContext = new ApplicationContext();
                            $sParams = $oAppContext->GetForLink();
                            $sDefaults = '';
                            if (isset($this->m_aParams['default'])) {
                                foreach ($this->m_aParams['default'] as $sName => $sValue) {
                                    $sDefaults .= '&' . urlencode($sName) . '=' . urlencode($sValue);
                                }
                            }
                            $sHtml .= $oPage->GetP("<a href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=modify_links&class={$sClass}&sParams&link_attr=" . $aExtraParams['link_attr'] . "&id=" . $aExtraParams['object_id'] . "&target_class={$sTargetClass}&addObjects=true{$sDefaults}\">" . Dict::Format('UI:ClickToCreateNew', Metamodel::GetName($sClass)) . "</a>\n");
                        }
                    }
                }
                break;
            case 'details':
                while ($oObj = $this->m_oSet->Fetch()) {
                    $sHtml .= $oObj->GetDetails($oPage);
                    // Still used ???
                }
                break;
            case 'actions':
                $sClass = $this->m_oFilter->GetClass();
                $oAppContext = new ApplicationContext();
                $bContextFilter = isset($aExtraParams['context_filter']) ? isset($aExtraParams['context_filter']) != 0 : false;
                if ($bContextFilter) {
                    $aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass()));
                    foreach ($oAppContext->GetNames() as $sFilterCode) {
                        $sContextParamValue = $oAppContext->GetCurrentValue($sFilterCode, null);
                        if (!is_null($sContextParamValue) && !empty($sContextParamValue) && MetaModel::IsValidFilterCode($sClass, $sFilterCode)) {
                            $this->AddCondition($sFilterCode, $sContextParamValue);
                        }
                    }
                    $aQueryParams = array();
                    if (isset($aExtraParams['query_params'])) {
                        $aQueryParams = $aExtraParams['query_params'];
                    }
                    $this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);
                }
                $iCount = $this->m_oSet->Count();
                $sHyperlink = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=search&' . $oAppContext->GetForLink() . '&filter=' . urlencode($this->m_oFilter->serialize());
                $sHtml .= '<p><a class="actions" href="' . $sHyperlink . '">';
                // Note: border set to 0 due to various browser interpretations (IE9 adding a 2px border)
                $sHtml .= MetaModel::GetClassIcon($sClass, true, 'float;left;margin-right:10px;border:0;');
                $sHtml .= MetaModel::GetName($sClass) . ': ' . $iCount . '</a></p>';
                $sParams = $oAppContext->GetForLink();
                $sHtml .= '<p>';
                if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY)) {
                    $sHtml .= "<a href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=new&class={$sClass}&{$sParams}\">" . Dict::Format('UI:ClickToCreateNew', MetaModel::GetName($sClass)) . "</a><br/>\n";
                }
                $sHtml .= "<a href=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=search_form&do_search=0&class={$sClass}&{$sParams}\">" . Dict::Format('UI:SearchFor_Class', MetaModel::GetName($sClass)) . "</a>\n";
                $sHtml .= '</p>';
                break;
            case 'summary':
                $sClass = $this->m_oFilter->GetClass();
                $oAppContext = new ApplicationContext();
                $sTitle = isset($aExtraParams['title[block]']) ? $aExtraParams['title[block]'] : '';
                $sLabel = isset($aExtraParams['label[block]']) ? $aExtraParams['label[block]'] : '';
                $sStateAttrCode = isset($aExtraParams['status[block]']) ? $aExtraParams['status[block]'] : 'status';
                $sStatesList = isset($aExtraParams['status_codes[block]']) ? $aExtraParams['status_codes[block]'] : '';
                $bContextFilter = isset($aExtraParams['context_filter']) ? isset($aExtraParams['context_filter']) != 0 : false;
                if ($bContextFilter) {
                    $aFilterCodes = array_keys(MetaModel::GetClassFilterDefs($this->m_oFilter->GetClass()));
                    foreach ($oAppContext->GetNames() as $sFilterCode) {
                        $sContextParamValue = $oAppContext->GetCurrentValue($sFilterCode, null);
                        if (!is_null($sContextParamValue) && !empty($sContextParamValue) && MetaModel::IsValidFilterCode($sClass, $sFilterCode)) {
                            $this->AddCondition($sFilterCode, $sContextParamValue);
                        }
                    }
                    $aQueryParams = array();
                    if (isset($aExtraParams['query_params'])) {
                        $aQueryParams = $aExtraParams['query_params'];
                    }
                    $this->m_oSet = new CMDBObjectSet($this->m_oFilter, array(), $aQueryParams);
                }
                // Summary details
                $aCounts = array();
                $aStateLabels = array();
                if (!empty($sStateAttrCode) && !empty($sStatesList)) {
                    $aStates = explode(',', $sStatesList);
                    $oAttDef = MetaModel::GetAttributeDef($sClass, $sStateAttrCode);
                    foreach ($aStates as $sStateValue) {
                        $oFilter = $this->m_oFilter->DeepClone();
                        $oFilter->AddCondition($sStateAttrCode, $sStateValue, '=');
                        $oSet = new DBObjectSet($oFilter);
                        $aCounts[$sStateValue] = $oSet->Count();
                        $aStateLabels[$sStateValue] = htmlentities($oAttDef->GetValueLabel($sStateValue), ENT_QUOTES, 'UTF-8');
                        if ($aCounts[$sStateValue] == 0) {
                            $aCounts[$sStateValue] = '-';
                        } else {
                            $sHyperlink = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=search&' . $oAppContext->GetForLink() . '&filter=' . urlencode($oFilter->serialize());
                            $aCounts[$sStateValue] = "<a href=\"{$sHyperlink}\">{$aCounts[$sStateValue]}</a>";
                        }
                    }
                }
                $sHtml .= '<div class="summary-details"><table><tr><th>' . implode('</th><th>', $aStateLabels) . '</th></tr>';
                $sHtml .= '<tr><td>' . implode('</td><td>', $aCounts) . '</td></tr></table></div>';
                // Title & summary
                $iCount = $this->m_oSet->Count();
                $sHyperlink = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=search&' . $oAppContext->GetForLink() . '&filter=' . urlencode($this->m_oFilter->serialize());
                $sHtml .= '<h1>' . Dict::S(str_replace('_', ':', $sTitle)) . '</h1>';
                $sHtml .= '<a class="summary" href="' . $sHyperlink . '">' . Dict::Format(str_replace('_', ':', $sLabel), $iCount) . '</a>';
                $sHtml .= '<div style="clear:both;"></div>';
                break;
            case 'csv':
                $bAdvancedMode = utils::ReadParam('advanced', false);
                $sCsvFile = strtolower($this->m_oFilter->GetClass()) . '.csv';
                $sDownloadLink = utils::GetAbsoluteUrlAppRoot() . 'webservices/export.php?expression=' . urlencode($this->m_oFilter->ToOQL(true)) . '&format=csv&filename=' . urlencode($sCsvFile);
                $sLinkToToggle = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=search&' . $oAppContext->GetForLink() . '&filter=' . urlencode($this->m_oFilter->serialize()) . '&format=csv';
                if ($bAdvancedMode) {
                    $sDownloadLink .= '&fields_advanced=1';
                    $sChecked = 'CHECKED';
                } else {
                    $sLinkToToggle = $sLinkToToggle . '&advanced=1';
                    $sChecked = '';
                }
                $sAjaxLink = $sDownloadLink . '&charset=UTF-8';
                // Includes &fields_advanced=1 if in advanced mode
                /*
                			$sCSVData = cmdbAbstractObject::GetSetAsCSV($this->m_oSet, array('fields_advanced' => $bAdvancedMode));
                			$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
                			if ($sCharset == 'UTF-8')
                			{
                				$bLostChars = false;
                			}
                			else
                			{
                				$sConverted = @iconv('UTF-8', $sCharset, $sCSVData);
                				$sRestored = @iconv($sCharset, 'UTF-8', $sConverted);
                				$bLostChars = ($sRestored != $sCSVData);
                			}
                			if ($bLostChars)
                			{
                				$sCharsetNotice = "&nbsp;&nbsp;<span id=\"csv_charset_issue\">";
                				$sCharsetNotice .= '<img src="../images/error.png"  style="vertical-align:middle"/>';
                				$sCharsetNotice .= "</span>";
                				$sTip = "<p>".htmlentities(Dict::S('UI:CSVExport:LostChars'), ENT_QUOTES, 'UTF-8')."</p>";
                				$sTip .= "<p>".htmlentities(Dict::Format('UI:CSVExport:LostChars+', $sCharset), ENT_QUOTES, 'UTF-8')."</p>";
                				$oPage->add_ready_script("$('#csv_charset_issue').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
                			}
                			else
                			{
                				$sCharsetNotice = '';
                			}
                */
                $sCharsetNotice = false;
                $sHtml .= "<div>";
                $sHtml .= '<table style="width:100%" class="transparent">';
                $sHtml .= '<tr>';
                $sHtml .= '<td><a href="' . $sDownloadLink . '">' . Dict::Format('UI:Download-CSV', $sCsvFile) . '</a>' . $sCharsetNotice . '</td>';
                $sHtml .= '<td style="text-align:right"><input type="checkbox" ' . $sChecked . ' onClick="window.location.href=\'' . $sLinkToToggle . '\'">&nbsp;' . Dict::S('UI:CSVExport:AdvancedMode') . '</td>';
                $sHtml .= '</tr>';
                $sHtml .= '</table>';
                if ($bAdvancedMode) {
                    $sHtml .= "<p>";
                    $sHtml .= htmlentities(Dict::S('UI:CSVExport:AdvancedMode+'), ENT_QUOTES, 'UTF-8');
                    $sHtml .= "</p>";
                }
                $sHtml .= "</div>";
                $sHtml .= "<div id=\"csv_content_loading\"><div style=\"width: 250px; height: 20px; background: url(../setup/orange-progress.gif); border: 1px #999 solid; margin-left:auto; margin-right: auto; text-align: center;\">" . Dict::S('UI:Loading') . "</div></div><textarea id=\"csv_content\" style=\"display:none;\">\n";
                //$sHtml .= htmlentities($sCSVData, ENT_QUOTES, 'UTF-8');
                $sHtml .= "</textarea>\n";
                $oPage->add_ready_script("\$.post('{$sAjaxLink}', {}, function(data) { \$('#csv_content').html(data); \$('#csv_content_loading').hide(); \$('#csv_content').show();} );");
                break;
            case 'modify':
                if (UserRights::IsActionAllowed($this->m_oSet->GetClass(), UR_ACTION_MODIFY, $this->m_oSet) == UR_ALLOWED_YES) {
                    while ($oObj = $this->m_oSet->Fetch()) {
                        $sHtml .= $oObj->GetModifyForm($oPage);
                    }
                }
                break;
            case 'search':
                $sStyle = isset($aExtraParams['open']) && $aExtraParams['open'] == 'true' ? 'SearchDrawer' : 'SearchDrawer DrawerClosed';
                $sHtml .= "<div id=\"ds_{$sId}\" class=\"{$sStyle}\">\n";
                $oPage->add_ready_script(<<<EOF
\t\$("#dh_{$sId}").click( function() {
\t\t\$("#ds_{$sId}").slideToggle('normal', function() { \$("#ds_{$sId}").parent().resize(); FixSearchFormsDisposition(); } );
\t\t\$("#dh_{$sId}").toggleClass('open');
\t});
EOF
);
                $aExtraParams['currentId'] = $sId;
                $sHtml .= cmdbAbstractObject::GetSearchForm($oPage, $this->m_oSet, $aExtraParams);
                $sHtml .= "</div>\n";
                $sHtml .= "<div class=\"HRDrawer\"></div>\n";
                $sHtml .= "<div id=\"dh_{$sId}\" class=\"DrawerHandle\">" . Dict::S('UI:SearchToggle') . "</div>\n";
                break;
            case 'open_flash_chart':
                static $iChartCounter = 0;
                $oAppContext = new ApplicationContext();
                $sContext = $oAppContext->GetForLink();
                if (!empty($sContext)) {
                    $sContext = '&' . $sContext;
                }
                $sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
                $sTitle = isset($aExtraParams['chart_title']) ? $aExtraParams['chart_title'] : '';
                $sGroupBy = isset($aExtraParams['group_by']) ? $aExtraParams['group_by'] : '';
                $sGroupByExpr = isset($aExtraParams['group_by_expr']) ? '&params[group_by_expr]=' . $aExtraParams['group_by_expr'] : '';
                $sFilter = $this->m_oFilter->serialize();
                $sHtml .= "<div id=\"my_chart_{$sId}{$iChartCounter}\">If the chart does not display, <a href=\"http://get.adobe.com/flash/\" target=\"_blank\">install Flash</a></div>\n";
                $oPage->add_script("function ofc_resize(left, width, top, height) { /* do nothing special */ }");
                if (isset($aExtraParams['group_by_label'])) {
                    $sUrl = urlencode(utils::GetAbsoluteUrlAppRoot() . "pages/ajax.render.php?operation=open_flash_chart&params[group_by]={$sGroupBy}{$sGroupByExpr}&params[group_by_label]={$aExtraParams['group_by_label']}&params[chart_type]={$sChartType}&params[chart_title]={$sTitle}&params[currentId]={$sId}&id={$sId}&filter=" . urlencode($sFilter));
                } else {
                    $sUrl = urlencode(utils::GetAbsoluteUrlAppRoot() . "pages/ajax.render.php?operation=open_flash_chart&params[group_by]={$sGroupBy}{$sGroupByExpr}&params[chart_type]={$sChartType}&params[chart_title]={$sTitle}&params[currentId]={$sId}&id={$sId}&filter=" . urlencode($sFilter));
                }
                $oPage->add_ready_script("swfobject.embedSWF(\"../images/open-flash-chart.swf\", \"my_chart_{$sId}{$iChartCounter}\", \"100%\", \"300\",\"9.0.0\", \"expressInstall.swf\",\n\t\t\t\t{\"data-file\":\"" . $sUrl . "\"}, {wmode: 'transparent'} );\n");
                $iChartCounter++;
                if (isset($aExtraParams['group_by'])) {
                    if (isset($aExtraParams['group_by_label'])) {
                        $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
                        $sGroupByLabel = $aExtraParams['group_by_label'];
                    } else {
                        // Backward compatibility: group_by is simply a field id
                        $sAlias = $this->m_oFilter->GetClassAlias();
                        $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
                        $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
                    }
                    $aGroupBy = array();
                    $aGroupBy['grouped_by_1'] = $oGroupByExp;
                    $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true);
                    $aRes = CMDBSource::QueryToArray($sSql);
                    $aGroupBy = array();
                    $aLabels = array();
                    $aValues = array();
                    $iTotalCount = 0;
                    foreach ($aRes as $iRow => $aRow) {
                        $sValue = $aRow['grouped_by_1'];
                        $aValues[$iRow] = $sValue;
                        $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
                        $aLabels[$iRow] = $sHtmlValue;
                        $aGroupBy[$iRow] = (int) $aRow['_itop_count_'];
                        $iTotalCount += $aRow['_itop_count_'];
                    }
                    $aData = array();
                    $idx = 0;
                    $aURLs = array();
                    foreach ($aGroupBy as $iRow => $iCount) {
                        // Build the search for this subset
                        $oSubsetSearch = $this->m_oFilter->DeepClone();
                        $oCondition = new BinaryExpression($oGroupByExp, '=', new ScalarExpression($aValues[$iRow]));
                        $oSubsetSearch->AddConditionExpression($oCondition);
                        $aURLs[$idx] = $oSubsetSearch->serialize();
                        $idx++;
                    }
                    $sURLList = '';
                    foreach ($aURLs as $index => $sURL) {
                        $sURLList .= "\taURLs[{$index}] = '" . utils::GetAbsoluteUrlAppRoot() . "pages/UI.php?operation=search&format=html{$sContext}&filter=" . urlencode($sURL) . "';\n";
                    }
                    $oPage->add_script(<<<EOF
function ofc_drill_down_{$sId}(index)
{
\tvar aURLs = new Array();
{$sURLList}
\twindow.location.href=aURLs[index];
}
EOF
);
                }
                break;
            case 'open_flash_chart_ajax':
                require_once APPROOT . '/pages/php-ofc-library/open-flash-chart.php';
                $sChartType = isset($aExtraParams['chart_type']) ? $aExtraParams['chart_type'] : 'pie';
                $sId = utils::ReadParam('id', '');
                $oChart = new open_flash_chart();
                switch ($sChartType) {
                    case 'bars':
                        $oChartElement = new bar_glass();
                        if (isset($aExtraParams['group_by'])) {
                            if (isset($aExtraParams['group_by_label'])) {
                                $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
                                $sGroupByLabel = $aExtraParams['group_by_label'];
                            } else {
                                // Backward compatibility: group_by is simply a field id
                                $sAlias = $this->m_oFilter->GetClassAlias();
                                $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
                                $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
                            }
                            $aGroupBy = array();
                            $aGroupBy['grouped_by_1'] = $oGroupByExp;
                            $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true);
                            $aRes = CMDBSource::QueryToArray($sSql);
                            $aGroupBy = array();
                            $aLabels = array();
                            $iTotalCount = 0;
                            foreach ($aRes as $iRow => $aRow) {
                                $sValue = $aRow['grouped_by_1'];
                                $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
                                $aLabels[$iRow] = strip_tags($sHtmlValue);
                                $aGroupBy[$iRow] = (int) $aRow['_itop_count_'];
                                $iTotalCount += $aRow['_itop_count_'];
                            }
                            $aData = array();
                            $aChartLabels = array();
                            $maxValue = 0;
                            foreach ($aGroupBy as $iRow => $iCount) {
                                $oBarValue = new bar_value($iCount);
                                $oBarValue->on_click("ofc_drill_down_{$sId}");
                                $aData[] = $oBarValue;
                                if ($iCount > $maxValue) {
                                    $maxValue = $iCount;
                                }
                                $aChartLabels[] = html_entity_decode($aLabels[$iRow], ENT_QUOTES, 'UTF-8');
                            }
                            $oYAxis = new y_axis();
                            $aMagicValues = array(1, 2, 5, 10);
                            $iMultiplier = 1;
                            $index = 0;
                            $iTop = $aMagicValues[$index % count($aMagicValues)] * $iMultiplier;
                            while ($maxValue > $iTop) {
                                $index++;
                                $iTop = $aMagicValues[$index % count($aMagicValues)] * $iMultiplier;
                                if ($index % count($aMagicValues) == 0) {
                                    $iMultiplier = $iMultiplier * 10;
                                }
                            }
                            //echo "oYAxis->set_range(0, $iTop, $iMultiplier);\n";
                            $oYAxis->set_range(0, $iTop, $iMultiplier);
                            $oChart->set_y_axis($oYAxis);
                            $oChartElement->set_values($aData);
                            $oXAxis = new x_axis();
                            $oXLabels = new x_axis_labels();
                            // set them vertical
                            $oXLabels->set_vertical();
                            // set the label text
                            $oXLabels->set_labels($aChartLabels);
                            // Add the X Axis Labels to the X Axis
                            $oXAxis->set_labels($oXLabels);
                            $oChart->set_x_axis($oXAxis);
                        }
                        break;
                    case 'pie':
                    default:
                        $oChartElement = new pie();
                        $oChartElement->set_start_angle(35);
                        $oChartElement->set_animate(true);
                        $oChartElement->set_tooltip('#label# - #val# (#percent#)');
                        $oChartElement->set_colours(array('#FF8A00', '#909980', '#2C2B33', '#CCC08D', '#596664'));
                        if (isset($aExtraParams['group_by'])) {
                            if (isset($aExtraParams['group_by_label'])) {
                                $oGroupByExp = Expression::FromOQL($aExtraParams['group_by']);
                                $sGroupByLabel = $aExtraParams['group_by_label'];
                            } else {
                                // Backward compatibility: group_by is simply a field id
                                $sAlias = $this->m_oFilter->GetClassAlias();
                                $oGroupByExp = new FieldExpression($aExtraParams['group_by'], $sAlias);
                                $sGroupByLabel = MetaModel::GetLabel($this->m_oFilter->GetClass(), $aExtraParams['group_by']);
                            }
                            $aGroupBy = array();
                            $aGroupBy['grouped_by_1'] = $oGroupByExp;
                            $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy, true);
                            $aRes = CMDBSource::QueryToArray($sSql);
                            $aGroupBy = array();
                            $aLabels = array();
                            $iTotalCount = 0;
                            foreach ($aRes as $iRow => $aRow) {
                                $sValue = $aRow['grouped_by_1'];
                                $sHtmlValue = $oGroupByExp->MakeValueLabel($this->m_oFilter, $sValue, $sValue);
                                $aLabels[$iRow] = strip_tags($sHtmlValue);
                                $aGroupBy[$iRow] = (int) $aRow['_itop_count_'];
                                $iTotalCount += $aRow['_itop_count_'];
                            }
                            $aData = array();
                            foreach ($aGroupBy as $iRow => $iCount) {
                                $sFlashLabel = html_entity_decode($aLabels[$iRow], ENT_QUOTES, 'UTF-8');
                                $PieValue = new pie_value($iCount, $sFlashLabel);
                                //@@ BUG: not passed via ajax !!!
                                $PieValue->on_click("ofc_drill_down_{$sId}");
                                $aData[] = $PieValue;
                            }
                            $oChartElement->set_values($aData);
                            $oChart->x_axis = null;
                        }
                }
                if (isset($aExtraParams['chart_title'])) {
                    // The title has been given in an url, and urlencoded...
                    // and urlencode transforms utf-8 into something similar to ISO-8859-1
                    // Example: é (C3A9 becomes %E9)
                    // As a consequence, json_encode (called within open-flash-chart.php)
                    // was returning 'null' and the graph was not displayed at all
                    // To make sure that the graph is displayed AND to get a correct title
                    // (at least for european characters) let's transform back into utf-8 !
                    $sTitle = iconv("ISO-8859-1", "UTF-8//IGNORE", $aExtraParams['chart_title']);
                    // If the title is a dictionnary entry, fetch it
                    $sTitle = Dict::S($sTitle);
                    $oTitle = new title($sTitle);
                    $oChart->set_title($oTitle);
                    $oTitle->set_style("{font-size: 16px; font-family: Tahoma; font-weight: bold; text-align: center;}");
                }
                $oChart->set_bg_colour('#FFFFFF');
                $oChart->add_element($oChartElement);
                $sHtml = $oChart->toPrettyString();
                break;
            default:
                // Unsupported style, do nothing.
                $sHtml .= Dict::format('UI:Error:UnsupportedStyleOfBlock', $this->m_sStyle);
        }
        return $sHtml;
    }
 function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
 {
     if ($bEditMode) {
         return;
     }
     // Not editable
     $oPage->add('<table style="vertical-align:top"><tr style="vertical-align:top"><td>');
     $aDetails = array();
     $sClass = get_class($this);
     $oPage->add('<fieldset>');
     $oPage->add('<legend>' . Dict::S('Core:SynchroReplica:PrivateDetails') . '</legend>');
     $aZList = MetaModel::FlattenZlist(MetaModel::GetZListItems($sClass, 'details'));
     foreach ($aZList as $sAttCode) {
         $sDisplayValue = $this->GetAsHTML($sAttCode);
         $aDetails[] = array('label' => '<span title="' . MetaModel::GetDescription($sClass, $sAttCode) . '">' . MetaModel::GetLabel($sClass, $sAttCode) . '</span>', 'value' => $sDisplayValue);
     }
     $oPage->Details($aDetails);
     $oPage->add('</fieldset>');
     if (strlen($this->Get('dest_class')) > 0) {
         $oDestObj = MetaModel::GetObject($this->Get('dest_class'), $this->Get('dest_id'), false);
         if (is_object($oDestObj)) {
             $oPage->add('<fieldset>');
             $oPage->add('<legend>' . Dict::Format('Core:SynchroReplica:TargetObject', $oDestObj->GetHyperlink()) . '</legend>');
             $oDestObj->DisplayBareProperties($oPage, false, $sPrefix, $aExtraParams);
             $oPage->add('<fieldset>');
         }
     }
     $oPage->add('</td><td>');
     $oPage->add('<fieldset>');
     $oPage->add('<legend>' . Dict::S('Core:SynchroReplica:PublicData') . '</legend>');
     $oSource = MetaModel::GetObject('SynchroDataSource', $this->Get('sync_source_id'));
     $sSQLTable = $oSource->GetDataTable();
     $aData = $this->LoadExtendedDataFromTable($sSQLTable);
     $aHeaders = array('attcode' => array('label' => 'Attribute Code', 'description' => ''), 'data' => array('label' => 'Value', 'description' => ''));
     $aRows = array();
     foreach ($aData as $sKey => $value) {
         $aRows[] = array('attcode' => $sKey, 'data' => $value);
     }
     $oPage->Table($aHeaders, $aRows);
     $oPage->add('</fieldset>');
     $oPage->add('</td></tr></table>');
 }
예제 #5
0
/**
 * Helper function to build the mapping drop-down list for a field
 * Spec: Possible choices are "writable" fields in this class plus external fields that are listed as reconciliation keys
 *       for any class pointed to by an external key in the current class.
 *       If not in advanced mode, all "id" fields (id and external keys) must be mapped to ":none:" (i.e -- ignore this field --)
 *       External fields that do not correspond to a reconciliation key must be mapped to ":none:"
 *       Otherwise, if a field equals either the 'code' or the 'label' (translated) of a field, then it's mapped automatically
 * @param string $sClassName Name of the class used for the mapping
 * @param string $sFieldName Name of the field, as it comes from the data file (header line)
 * @param integer $iFieldIndex Number of the field in the sequence
 * @param bool $bAdvancedMode Whether or not advanced mode was chosen
 * @param string $sDefaultChoice If set, this will be the item selected by default
 * @return string The HTML code corresponding to the drop-down list for this field
 */
function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMode, $sDefaultChoice)
{
    $aChoices = array('' => Dict::S('UI:CSVImport:MappingSelectOne'));
    $aChoices[':none:'] = Dict::S('UI:CSVImport:MappingNotApplicable');
    $sFieldCode = '';
    // Code of the attribute, if there is a match
    $aMatches = array();
    if (preg_match('/^(.+)\\*$/', $sFieldName, $aMatches)) {
        // Remove any trailing "star" character.
        // A star character at the end can be used to indicate a mandatory field
        $sFieldName = $aMatches[1];
    } else {
        if (preg_match('/^(.+)\\*->(.+)$/', $sFieldName, $aMatches)) {
            // Remove any trailing "star" character before the arrow (->)
            // A star character at the end can be used to indicate a mandatory field
            $sFieldName = $aMatches[1] . '->' . $aMatches[2];
        }
    }
    if ($sFieldName == 'id') {
        $sFieldCode = 'id';
    }
    if ($bAdvancedMode) {
        $aChoices['id'] = Dict::S('UI:CSVImport:idField');
    }
    foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
        $sStar = '';
        if ($oAttDef->IsExternalKey()) {
            if ($sFieldName == $oAttDef->GetLabel() || $sFieldName == $sAttCode) {
                $sFieldCode = $sAttCode;
            }
            if ($bAdvancedMode) {
                $aChoices[$sAttCode] = $oAttDef->GetLabel();
            }
            $oExtKeyAttDef = MetaModel::GetAttributeDef($sClassName, $oAttDef->GetKeyAttCode());
            if (!$oExtKeyAttDef->IsNullAllowed()) {
                $sStar = '*';
            }
            // Get fields of the external class that are considered as reconciliation keys
            $sTargetClass = $oAttDef->GetTargetClass();
            foreach (MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef) {
                if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode)) {
                    $bExtKey = $oTargetAttDef->IsExternalKey();
                    $sSuffix = '';
                    if ($bExtKey) {
                        $sSuffix = '->id';
                    }
                    if ($bAdvancedMode || !$bExtKey) {
                        // When not in advanced mode do not allow to use reconciliation keys (on external keys) if they are themselves external keys !
                        $aChoices[$sAttCode . '->' . $sTargetAttCode] = MetaModel::GetLabel($sClassName, $sAttCode . '->' . $sTargetAttCode, true);
                        if (strcasecmp($sFieldName, $oAttDef->GetLabel() . '->' . $oTargetAttDef->GetLabel() . $sSuffix) == 0 || strcasecmp($sFieldName, $sAttCode . '->' . $sTargetAttCode . $sSuffix) == 0) {
                            $sFieldCode = $sAttCode . '->' . $sTargetAttCode;
                        }
                    }
                }
            }
        } else {
            if ($oAttDef->IsWritable() && (!$oAttDef->IsLinkset() || $bAdvancedMode && $oAttDef->IsIndirect())) {
                $aChoices[$sAttCode] = MetaModel::GetLabel($sClassName, $sAttCode, true);
                if ($sFieldName == $oAttDef->GetLabel() || $sFieldName == $sAttCode) {
                    $sFieldCode = $sAttCode;
                }
            }
        }
    }
    asort($aChoices);
    $sHtml = "<select id=\"mapping_{$iFieldIndex}\" name=\"field[{$iFieldIndex}]\">\n";
    $bIsIdField = IsIdField($sClassName, $sFieldCode);
    foreach ($aChoices as $sAttCode => $sLabel) {
        $sSelected = '';
        if ($bIsIdField && !$bAdvancedMode) {
            if ($sAttCode == ':none:') {
                $sSelected = ' selected';
            }
        } else {
            if (empty($sFieldCode) && strpos($sFieldName, '->') !== false) {
                if ($sAttCode == ':none:') {
                    $sSelected = ' selected';
                }
            } else {
                if (is_null($sDefaultChoice) && $sFieldCode == $sAttCode) {
                    $sSelected = ' selected';
                } else {
                    if (!is_null($sDefaultChoice) && $sDefaultChoice == $sAttCode) {
                        $sSelected = ' selected';
                    }
                }
            }
        }
        $sHtml .= "<option value=\"{$sAttCode}\"{$sSelected}>{$sLabel}</option>\n";
    }
    $sHtml .= "</select>\n";
    return $sHtml;
}
 protected function GetFieldsList($oSet, $bFieldsAdvanced = false, $bLocalize = true, $aFields = null)
 {
     $this->aFieldsList = array();
     $oAppContext = new ApplicationContext();
     $aClasses = $oSet->GetFilter()->GetSelectedClasses();
     $this->aAuthorizedClasses = array();
     foreach ($aClasses as $sAlias => $sClassName) {
         if (UserRights::IsActionAllowed($sClassName, UR_ACTION_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) {
             $this->aAuthorizedClasses[$sAlias] = $sClassName;
         }
     }
     $aAttribs = array();
     $this->aTableHeaders = array();
     foreach ($this->aAuthorizedClasses as $sAlias => $sClassName) {
         $aList[$sAlias] = array();
         foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
             if (is_null($aFields) || count($aFields) == 0) {
                 // Standard list of attributes (no link sets)
                 if ($oAttDef->IsScalar() && ($oAttDef->IsWritable() || $oAttDef->IsExternalField())) {
                     $sAttCodeEx = $oAttDef->IsExternalField() ? $oAttDef->GetKeyAttCode() . '->' . $oAttDef->GetExtAttCode() : $sAttCode;
                     if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
                         if ($bFieldsAdvanced) {
                             $aList[$sAlias][$sAttCodeEx] = $oAttDef;
                             if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE)) {
                                 $sRemoteClass = $oAttDef->GetTargetClass();
                                 foreach (MetaModel::GetReconcKeys($sRemoteClass) as $sRemoteAttCode) {
                                     $this->aFieldsList[$sAlias][$sAttCode . '->' . $sRemoteAttCode] = MetaModel::GetAttributeDef($sRemoteClass, $sRemoteAttCode);
                                 }
                             }
                         }
                     } else {
                         // Any other attribute
                         $this->aFieldsList[$sAlias][$sAttCodeEx] = $oAttDef;
                     }
                 }
             } else {
                 // User defined list of attributes
                 if (in_array($sAttCode, $aFields) || in_array($sAlias . '.' . $sAttCode, $aFields)) {
                     $this->aFieldsList[$sAlias][$sAttCode] = $oAttDef;
                 }
             }
         }
         if ($bFieldsAdvanced) {
             $this->aTableHeaders['id'] = '0';
         }
         foreach ($this->aFieldsList[$sAlias] as $sAttCodeEx => $oAttDef) {
             $sLabel = $bLocalize ? MetaModel::GetLabel($sClassName, $sAttCodeEx, isset($aParams['showMandatoryFields'])) : $sAttCodeEx;
             if ($oAttDef instanceof AttributeDateTime) {
                 $this->aTableHeaders[$sLabel] = 'datetime';
             } else {
                 $this->aTableHeaders[$sLabel] = 'string';
             }
         }
     }
 }
예제 #7
0
/**
 * Create form to apply a stimulus
 * @param WebPage $oP The current web page
 * @param Object $oObj The target object
 * @param String $sStimulusCode Stimulus that will be applied
 * @param Array $aEditAtt List of attributes to edit
 * @return void
 */
function MakeStimulusForm(WebPage $oP, $oObj, $sStimulusCode, $aEditAtt)
{
    static $bHasStimulusForm = false;
    $sDialogId = $sStimulusCode . "_dialog";
    $sFormId = $sStimulusCode . "_form";
    $sCancelButtonLabel = Dict::S('UI:Button:Cancel');
    $oP->add('<div id="' . $sDialogId . '" style="display: none;">');
    $sClass = get_class($oObj);
    $oP->add('<form id="' . $sFormId . '" method="post">');
    $sTransactionId = utils::GetNewTransactionId();
    $oP->add("<input type=\"hidden\" id=\"transaction_id\" name=\"transaction_id\" value=\"{$sTransactionId}\">\n");
    $oP->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">");
    $oP->add("<input type=\"hidden\" name=\"id\" value=\"" . $oObj->GetKey() . "\">");
    $oP->add("<input type=\"hidden\" name=\"operation\" value=\"update_request\">");
    $oP->add("<input type=\"hidden\" id=\"stimulus_to_apply\" name=\"apply_stimulus\" value=\"{$sStimulusCode}\">\n");
    foreach ($aEditAtt as $sAttCode) {
        $sValue = $oObj->Get($sAttCode);
        $sDisplayValue = $oObj->GetEditValue($sAttCode);
        $aArgs = array('this' => $oObj, 'formPrefix' => '');
        $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
        $sInputId = 'input_' . $sAttCode;
        $sHTMLValue = "<span id=\"field_{$sStimulusCode}_{$sInputId}\">" . cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', 0, $aArgs) . '</span>';
        $oP->add('<h1>' . MetaModel::GetLabel($sClass, $sAttCode) . '</h1>');
        $oP->add($sHTMLValue);
    }
    $oP->add('</form>');
    $oP->add('</div>');
    if (!$bHasStimulusForm) {
        $bHasStimulusForm = true;
        $oP->add_script(<<<EOF

function RunStimulusDialog(sStimulusCode, sTitle, sOkButtonLabel)
{
\tvar sWidth = 'auto';
\tif (sStimulusCode == 'ev_reopen')
\t{
\t\t// Avoid having a dialog spanning the complete width of the window
\t\t// just because it contains a CaseLog entry
\t\tsWidth = '80%';
\t}
\t\t\t\t
\t\$('#'+sStimulusCode+'_dialog').dialog({
\t\theight: 'auto',
\t\twidth: sWidth,
\t\tmodal: true,
\t\ttitle: sTitle,
\t\tbuttons: [
\t\t{ text: sOkButtonLabel, click: function() {
\t\t\t\$(this).find('#'+sStimulusCode+'_form').submit();
\t\t} },
\t\t{ text: "{$sCancelButtonLabel}", click: function() {
\t\t\t\$(this).dialog( "close" );
\t\t} }
\t\t]
\t});
\t// Start the validation
\tCheckFields(sStimulusCode+'_form', false);
\t\$('#'+sStimulusCode+'_form').submit( function() {
\t\treturn OnSubmit(sStimulusCode+'_form');
\t});
}
EOF
);
    }
}
예제 #8
0
    /**
     * Process the CSV data, for real or as a simulation
     * @param WebPage $oPage The page used to display the wizard
     * @param bool $bSimulate Whether or not to simulate the data load
     * @return array The CSV lines in error that were rejected from the load (with the header line - if any) or null
     */
    function ProcessCSVData(WebPage $oPage, $bSimulate = true)
    {
        $aResult = array();
        $sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
        $sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '', false, 'raw_data');
        $sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
        $sTextQualifier = utils::ReadParam('text_qualifier', '"', false, 'raw_data');
        $bHeaderLine = utils::ReadParam('header_line', '0') == 1;
        $iSkippedLines = 0;
        if (utils::ReadParam('box_skiplines', '0') == 1) {
            $iSkippedLines = utils::ReadParam('nb_skipped_lines', '0');
        }
        $sClassName = utils::ReadParam('class_name', '', false, 'class');
        $aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data');
        $aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name');
        $iCurrentStep = $bSimulate ? 4 : 5;
        $bAdvanced = utils::ReadParam('advanced', 0);
        $sEncoding = utils::ReadParam('encoding', 'UTF-8');
        $sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
        if (!empty($sSynchroScope)) {
            $oSearch = DBObjectSearch::FromOQL($sSynchroScope);
            $sClassName = $oSearch->GetClass();
            // If a synchronization scope is set, then the class is fixed !
            $oSet = new DBObjectSet($oSearch);
            $iCount = $oSet->Count();
            DisplaySynchroBanner($oPage, $sClassName, $iCount);
            $sClassesSelect = "<select id=\"select_class_name\" name=\"class_name\"><option value=\"{$sClassName}\" selected>" . MetaModel::GetName($sClassName) . "</option>";
            $aSynchroUpdate = utils::ReadParam('synchro_update', array());
        } else {
            $sSynchroScope = '';
            $aSynchroUpdate = null;
        }
        // Parse the data set
        $oCSVParser = new CSVParser($sCSVData, $sSeparator, $sTextQualifier);
        $aData = $oCSVParser->ToArray($iSkippedLines);
        $iRealSkippedLines = $iSkippedLines;
        if ($bHeaderLine) {
            $aResult[] = $sTextQualifier . implode($sTextQualifier . $sSeparator . $sTextQualifier, array_shift($aData)) . $sTextQualifier;
            // Remove the first line and store it in case of error
            $iRealSkippedLines++;
        }
        // Format for the line numbers
        $sMaxLen = strlen('' . count($aData)) < 3 ? 3 : strlen('' . count($aData));
        // Pad line numbers to the appropriate number of chars, but at least 3
        // Compute the list of search/reconciliation criteria
        $aSearchKeys = array();
        foreach ($aSearchFields as $index => $sDummy) {
            $sSearchField = $aFieldsMapping[$index];
            $aMatches = array();
            if (preg_match('/(.+)->(.+)/', $sSearchField, $aMatches) > 0) {
                $sSearchField = $aMatches[1];
                $aSearchKeys[$aMatches[1]] = '';
            } else {
                $aSearchKeys[$sSearchField] = '';
            }
            if (!MetaModel::IsValidFilterCode($sClassName, $sSearchField)) {
                // Remove invalid or unmapped search fields
                $aSearchFields[$index] = null;
                unset($aSearchKeys[$sSearchField]);
            }
        }
        // Compute the list of fields and external keys to process
        $aExtKeys = array();
        $aAttributes = array();
        $aExternalKeysByColumn = array();
        foreach ($aFieldsMapping as $iNumber => $sAttCode) {
            $iIndex = $iNumber - 1;
            if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') {
                if (preg_match('/(.+)->(.+)/', $sAttCode, $aMatches) > 0) {
                    $sAttribute = $aMatches[1];
                    $sField = $aMatches[2];
                    $aExtKeys[$sAttribute][$sField] = $iIndex;
                    $aExternalKeysByColumn[$iIndex] = $sAttribute;
                } else {
                    if ($sAttCode == 'id') {
                        $aAttributes['id'] = $iIndex;
                    } else {
                        $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
                        if ($oAttDef->IsExternalKey()) {
                            $aExtKeys[$sAttCode]['id'] = $iIndex;
                            $aExternalKeysByColumn[$iIndex] = $sAttCode;
                        } else {
                            $aAttributes[$sAttCode] = $iIndex;
                        }
                    }
                }
            }
        }
        $oMyChange = null;
        if (!$bSimulate) {
            // We're doing it for real, let's create a change
            $sUserString = CMDBChange::GetCurrentUserName() . ' (CSV)';
            CMDBObject::SetTrackInfo($sUserString);
            CMDBObject::SetTrackOrigin('csv-interactive');
            $oMyChange = CMDBObject::GetCurrentChange();
        }
        $oBulk = new BulkChange($sClassName, $aData, $aAttributes, $aExtKeys, array_keys($aSearchKeys), empty($sSynchroScope) ? null : $sSynchroScope, $aSynchroUpdate, null, true);
        $oBulk->SetReportHtml();
        $oPage->add('<input type="hidden" name="csvdata_truncated" id="csvdata_truncated" value="' . htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8') . '"/>');
        $aRes = $oBulk->Process($oMyChange);
        $sHtml = '<table id="bulk_preview" style="border-collapse: collapse;">';
        $sHtml .= '<tr><th style="padding:2px;border-right: 2px #fff solid;">Line</th>';
        $sHtml .= '<th style="padding:2px;border-right: 2px #fff solid;">Status</th>';
        $sHtml .= '<th style="padding:2px;border-right: 2px #fff solid;">Object</th>';
        foreach ($aFieldsMapping as $iNumber => $sAttCode) {
            if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') {
                $sHtml .= "<th style=\"padding:2px;border-right: 2px #fff solid;\">" . MetaModel::GetLabel($sClassName, $sAttCode) . "</th>";
            }
        }
        $sHtml .= '<th>Message</th>';
        $sHtml .= '</tr>';
        $iErrors = 0;
        $iCreated = 0;
        $iModified = 0;
        $iUnchanged = 0;
        foreach ($aRes as $iLine => $aResRow) {
            $oStatus = $aResRow['__STATUS__'];
            $sUrl = '';
            $sMessage = '';
            $sCSSRowClass = '';
            $sCSSMessageClass = 'cell_ok';
            switch (get_class($oStatus)) {
                case 'RowStatus_NoChange':
                    $iUnchanged++;
                    $sFinalClass = $aResRow['finalclass'];
                    $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
                    $sUrl = $oObj->GetHyperlink();
                    $sStatus = '<img src="../images/unchanged.png" title="' . Dict::S('UI:CSVReport-Icon-Unchanged') . '">';
                    $sCSSRowClass = 'row_unchanged';
                    break;
                case 'RowStatus_Modify':
                    $iModified++;
                    $sFinalClass = $aResRow['finalclass'];
                    $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
                    $sUrl = $oObj->GetHyperlink();
                    $sStatus = '<img src="../images/modified.png" title="' . Dict::S('UI:CSVReport-Icon-Modified') . '">';
                    $sCSSRowClass = 'row_modified';
                    break;
                case 'RowStatus_Disappeared':
                    $iModified++;
                    $sFinalClass = $aResRow['finalclass'];
                    $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
                    $sUrl = $oObj->GetHyperlink();
                    $sStatus = '<img src="../images/delete.png" title="' . Dict::S('UI:CSVReport-Icon-Missing') . '">';
                    $sCSSRowClass = 'row_modified';
                    if ($bSimulate) {
                        $sMessage = Dict::S('UI:CSVReport-Object-MissingToUpdate');
                    } else {
                        $sMessage = Dict::S('UI:CSVReport-Object-MissingUpdated');
                    }
                    break;
                case 'RowStatus_NewObj':
                    $iCreated++;
                    $sFinalClass = $aResRow['finalclass'];
                    $sStatus = '<img src="../images/added.png" title="' . Dict::S('UI:CSVReport-Icon-Created') . '">';
                    $sCSSRowClass = 'row_added';
                    if ($bSimulate) {
                        $sMessage = Dict::S('UI:CSVReport-Object-ToCreate');
                    } else {
                        $sFinalClass = $aResRow['finalclass'];
                        $oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
                        $sUrl = $oObj->GetHyperlink();
                        $sMessage = Dict::S('UI:CSVReport-Object-Created');
                    }
                    break;
                case 'RowStatus_Issue':
                    $iErrors++;
                    $sMessage .= $oPage->GetP($oStatus->GetDescription());
                    $sStatus = '<img src="../images/error.png" title="' . Dict::S('UI:CSVReport-Icon-Error') . '">';
                    //translate
                    $sCSSMessageClass = 'cell_error';
                    $sCSSRowClass = 'row_error';
                    if (array_key_exists($iLine, $aData)) {
                        $aRow = $aData[$iLine];
                        $aResult[] = $sTextQualifier . implode($sTextQualifier . $sSeparator . $sTextQualifier, $aRow) . $sTextQualifier;
                        // Remove the first line and store it in case of error
                    }
                    break;
            }
            $sHtml .= '<tr class="' . $sCSSRowClass . '">';
            $sHtml .= "<td style=\"background-color:#f1f1f1;border-right:2px #fff solid;\">" . sprintf("%0{$sMaxLen}d", 1 + $iLine + $iRealSkippedLines) . "</td>";
            $sHtml .= "<td style=\"text-align:center;background-color:#f1f1f1;border-right:2px #fff solid;\">{$sStatus}</td>";
            $sHtml .= "<td style=\"text-align:center;background-color:#f1f1f1;\">{$sUrl}</td>";
            foreach ($aFieldsMapping as $iNumber => $sAttCode) {
                if (!empty($sAttCode) && $sAttCode != ':none:' && $sAttCode != 'finalclass') {
                    $oCellStatus = $aResRow[$iNumber - 1];
                    $sCellMessage = '';
                    if (isset($aExternalKeysByColumn[$iNumber - 1])) {
                        $sExtKeyName = $aExternalKeysByColumn[$iNumber - 1];
                        $oExtKeyCellStatus = $aResRow[$sExtKeyName];
                        switch (get_class($oExtKeyCellStatus)) {
                            case 'CellStatus_Issue':
                            case 'CellStatus_SearchIssue':
                            case 'CellStatus_NullIssue':
                                $sCellMessage .= $oPage->GetP($oExtKeyCellStatus->GetDescription());
                                break;
                            case 'CellStatus_Ambiguous':
                                $sCellMessage .= $oPage->GetP($oExtKeyCellStatus->GetDescription());
                                break;
                            default:
                                // Do nothing
                        }
                    }
                    $sHtmlValue = $oCellStatus->GetDisplayableValue();
                    switch (get_class($oCellStatus)) {
                        case 'CellStatus_Issue':
                            $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription());
                            $sHtml .= '<td class="cell_error" style="border-right:1px #eee solid;">' . Dict::Format('UI:CSVReport-Object-Error', $sHtmlValue) . $sCellMessage . '</td>';
                            break;
                        case 'CellStatus_SearchIssue':
                            $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription());
                            $sHtml .= '<td class="cell_error">ERROR: ' . $sHtmlValue . $sCellMessage . '</td>';
                            break;
                        case 'CellStatus_Ambiguous':
                            $sCellMessage .= $oPage->GetP($oCellStatus->GetDescription());
                            $sHtml .= '<td class="cell_error" style="border-right:1px #eee solid;">' . Dict::Format('UI:CSVReport-Object-Ambiguous', $sHtmlValue) . $sCellMessage . '</td>';
                            break;
                        case 'CellStatus_Modify':
                            $sHtml .= '<td class="cell_modified" style="border-right:1px #eee solid;"><b>' . $sHtmlValue . '</b></td>';
                            break;
                        default:
                            $sHtml .= '<td class="cell_ok" style="border-right:1px #eee solid;">' . $sHtmlValue . $sCellMessage . '</td>';
                    }
                }
            }
            $sHtml .= "<td class=\"{$sCSSMessageClass}\" style=\"background-color:#f1f1f1;\">{$sMessage}</td>";
            $sHtml .= '</tr>';
        }
        $iUnchanged = count($aRes) - $iErrors - $iModified - $iCreated;
        $sHtml .= '</table>';
        $oPage->add('<div class="wizContainer" style="width:auto;display:inline-block;">');
        $oPage->add('<form enctype="multipart/form-data" id="wizForm" method="post">');
        $oPage->add('<input type="hidden" name="step" value="' . ($iCurrentStep + 1) . '"/>');
        $oPage->add('<input type="hidden" name="separator" value="' . htmlentities($sSeparator, ENT_QUOTES, 'UTF-8') . '"/>');
        $oPage->add('<input type="hidden" name="text_qualifier" value="' . htmlentities($sTextQualifier, ENT_QUOTES, 'UTF-8') . '"/>');
        $oPage->add('<input type="hidden" name="header_line" value="' . $bHeaderLine . '"/>');
        $oPage->add('<input type="hidden" name="nb_skipped_lines" value="' . utils::ReadParam('nb_skipped_lines', '0') . '"/>');
        $oPage->add('<input type="hidden" name="box_skiplines" value="' . utils::ReadParam('box_skiplines', '0') . '"/>');
        $oPage->add('<input type="hidden" name="csvdata" value="' . htmlentities($sCSVData, ENT_QUOTES, 'UTF-8') . '"/>');
        $oPage->add('<input type="hidden" name="csvdata_truncated" value="' . htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8') . '"/>');
        $oPage->add('<input type="hidden" name="class_name" value="' . $sClassName . '"/>');
        $oPage->add('<input type="hidden" name="advanced" value="' . $bAdvanced . '"/>');
        $oPage->add('<input type="hidden" name="encoding" value="' . $sEncoding . '"/>');
        $oPage->add('<input type="hidden" name="synchro_scope" value="' . $sSynchroScope . '"/>');
        if (!empty($sSynchroScope)) {
            foreach ($aSynchroUpdate as $sKey => $value) {
                $oPage->add('<input type="hidden" name="synchro_update[' . $sKey . ']" value="' . $value . '"/>');
            }
        }
        foreach ($aFieldsMapping as $iNumber => $sAttCode) {
            $oPage->add('<input type="hidden" name="field[' . $iNumber . ']" value="' . $sAttCode . '"/>');
        }
        foreach ($aSearchFields as $index => $sDummy) {
            $oPage->add('<input type="hidden" name="search_field[' . $index . ']" value="1"/>');
        }
        $aDisplayFilters = array();
        if ($bSimulate) {
            $aDisplayFilters['unchanged'] = Dict::S('UI:CSVImport:ObjectsWillStayUnchanged');
            $aDisplayFilters['modified'] = Dict::S('UI:CSVImport:ObjectsWillBeModified');
            $aDisplayFilters['added'] = Dict::S('UI:CSVImport:ObjectsWillBeAdded');
            $aDisplayFilters['errors'] = Dict::S('UI:CSVImport:ObjectsWillHaveErrors');
        } else {
            $aDisplayFilters['unchanged'] = Dict::S('UI:CSVImport:ObjectsRemainedUnchanged');
            $aDisplayFilters['modified'] = Dict::S('UI:CSVImport:ObjectsWereModified');
            $aDisplayFilters['added'] = Dict::S('UI:CSVImport:ObjectsWereAdded');
            $aDisplayFilters['errors'] = Dict::S('UI:CSVImport:ObjectsHadErrors');
        }
        $oPage->add('<p><input type="checkbox" checked id="show_unchanged" onClick="ToggleRows(\'row_unchanged\')"/>&nbsp;<img src="../images/unchanged.png">&nbsp;' . sprintf($aDisplayFilters['unchanged'], $iUnchanged) . '&nbsp&nbsp;');
        $oPage->add('<input type="checkbox" checked id="show_modified" onClick="ToggleRows(\'row_modified\')"/>&nbsp;<img src="../images/modified.png">&nbsp;' . sprintf($aDisplayFilters['modified'], $iModified) . '&nbsp&nbsp;');
        $oPage->add('<input type="checkbox" checked id="show_created" onClick="ToggleRows(\'row_added\')"/>&nbsp;<img src="../images/added.png">&nbsp;' . sprintf($aDisplayFilters['added'], $iCreated) . '&nbsp&nbsp;');
        $oPage->add('<input type="checkbox" checked id="show_errors" onClick="ToggleRows(\'row_error\')"/>&nbsp;<img src="../images/error.png">&nbsp;' . sprintf($aDisplayFilters['errors'], $iErrors) . '</p>');
        $oPage->add('<div class="white" style="display:inline-block">');
        $oPage->add($sHtml);
        $oPage->add('</div> <!-- end of preview -->');
        $oPage->add('<p>');
        if ($bSimulate) {
            $oPage->add('<input type="button" value="' . Dict::S('UI:Button:Restart') . '" onClick="CSVRestart()"/>&nbsp;&nbsp;');
        }
        $oPage->add('<input type="button" value="' . Dict::S('UI:Button:Back') . '" onClick="CSVGoBack()"/>&nbsp;&nbsp;');
        $bShouldConfirm = false;
        if ($bSimulate) {
            // if there are *too many* changes, we should ask the user for a confirmation
            if (count($aRes) >= MetaModel::GetConfig()->Get('csv_import_min_object_confirmation')) {
                $fErrorsPercentage = 100.0 * $iErrors / count($aRes);
                if ($fErrorsPercentage >= MetaModel::GetConfig()->Get('csv_import_errors_percentage')) {
                    $sMessage = Dict::Format('UI:CSVReport-Stats-Errors', $fErrorsPercentage);
                    $bShouldConfirm = true;
                }
                $fCreatedPercentage = 100.0 * $iCreated / count($aRes);
                if ($fCreatedPercentage >= MetaModel::GetConfig()->Get('csv_import_creations_percentage')) {
                    $sMessage = Dict::Format('UI:CSVReport-Stats-Created', $fCreatedPercentage);
                    $bShouldConfirm = true;
                }
                $fModifiedPercentage = 100.0 * $iModified / count($aRes);
                if ($fModifiedPercentage >= MetaModel::GetConfig()->Get('csv_import_modifications_percentage')) {
                    $sMessage = Dict::Format('UI:CSVReport-Stats-Modified', $fModifiedPercentage);
                    $bShouldConfirm = true;
                }
            }
            $iCount = count($aRes);
            //$oPage->add('<input type="submit" value="'.Dict::S('UI:Button:DoImport').'" onClick="$(\'#wizForm\').block();"/></p>');
            $sConfirm = $bShouldConfirm ? 'true' : 'false';
            $oPage->add('<input type="button" value="' . Dict::S('UI:Button:DoImport') . "\" onClick=\"return DoSubmit({$sConfirm});\"/></p>");
        } else {
            $oPage->add('<input type="submit" value="' . Dict::S('UI:Button:Done') . '"/></p>');
        }
        $oPage->add('</form>');
        $oPage->add('</div> <!-- end of wizForm -->');
        if ($bShouldConfirm) {
            $sYesButton = Dict::S('UI:Button:Ok');
            $sNoButton = Dict::S('UI:Button:Cancel');
            $oPage->add('<div id="dlg_confirmation" title="' . htmlentities(Dict::S('UI:CSVImportConfirmTitle'), ENT_QUOTES, 'UTF-8') . '">');
            $oPage->add('<p style="text-align:center"><b>' . $sMessage . '</b></p>');
            $oPage->add('<p style="text-align:center">' . htmlentities(Dict::S('UI:CSVImportConfirmMessage'), ENT_QUOTES, 'UTF-8') . '</p>');
            $oPage->add('<div id="confirmation_chart"></div>');
            $oPage->add('</div> <!-- end of dlg_confirmation -->');
            $oPage->add_ready_script(<<<EOF
\t\$('#dlg_confirmation').dialog( 
\t\t{
\t\t\theight: 'auto',
\t\t\twidth: 500,
\t\t\tmodal:true, 
\t\t\tautoOpen: false, 
\t\t\tbuttons:
\t\t\t{
\t\t\t\t'{$sYesButton}': RunImport,
\t\t\t\t'{$sNoButton}': CancelImport 
\t\t\t} 
\t\t});
\t\tswfobject.embedSWF(\t"../images/open-flash-chart.swf", 
\t\t\t\t\t\t\t"confirmation_chart", 
\t\t\t\t\t\t\t"100%", "300","9.0.0",
\t\t\t\t\t\t\t"expressInstall.swf",
\t\t\t\t\t\t\t{}, 
\t\t\t\t\t\t\t{'wmode': 'transparent'}
\t\t\t\t\t\t);
EOF
);
        }
        $sErrors = addslashes(Dict::Format('UI:CSVImportError_items', $iErrors));
        $sCreated = addslashes(Dict::Format('UI:CSVImportCreated_items', $iCreated));
        $sModified = addslashes(Dict::Format('UI:CSVImportModified_items', $iModified));
        $sUnchanged = addslashes(Dict::Format('UI:CSVImportUnchanged_items', $iUnchanged));
        $oPage->add_script(<<<EOF
function CSVGoBack()
{
\t\$('input[name=step]').val({$iCurrentStep}-1);
\t\$('#wizForm').submit();
\t
}

function CSVRestart()
{
\t\$('input[name=step]').val(1);
\t\$('#wizForm').submit();
\t
}

function ToggleRows(sCSSClass)
{
\t\$('.'+sCSSClass).toggle();
}

function DoSubmit(bConfirm)
{
\tif (bConfirm) //Ask for a confirmation
\t{
\t\t\$('#dlg_confirmation').dialog('open');
\t}
\telse
\t{
\t\t// Submit the form
\t\t\$('#wizForm').block();
\t\t\$('#wizForm').submit();
\t}
\treturn false;
}

function CancelImport()
{
\t\$('#dlg_confirmation').dialog('close');
}

function RunImport()
{
\t\$('#dlg_confirmation').dialog('close');
\t// Submit the form
\t\$('#wizForm').block();
\t\$('#wizForm').submit();
}

function open_flash_chart_data()
{
\tvar iErrors = {$iErrors};
\tvar iModified = {$iModified};
\tvar iCreated = {$iCreated};
\tvar iUnchanged = {$iUnchanged};
\tvar fAlpha = 0.9;
\t
\tvar oResult = {
\t\t"elements": [
\t\t\t{
\t\t\t\t"type": "pie",
\t\t\t\t"tip": "#label# (#percent#)",
\t\t\t\t"gradient-fill": true,
\t\t\t\t"font-size": 14,
\t\t\t\t"colours":[],
\t\t\t\t"values": [],
\t\t\t\t"animate":[
\t\t\t        {
\t\t\t          "type": "fade"
\t\t\t        }
\t\t        ]
\t\t\t}
\t\t],
\t\t"x_axis": null,
\t\t"font-size": 14,
\t\t"bg_colour": "#EEEEEE"
\t};

\tif (iErrors > 0)
\t{
\t\tvar oErrors =
\t\t{
\t\t\t"value":  iErrors,
\t\t\t"label": "{$sErrors}",
\t\t\t"alpha": fAlpha,
\t\t\t"label-colour": "#CC3333",
\t\t};
\t\toResult.elements[0].values.push(oErrors);
\t\toResult.elements[0].colours.push('#FF6666');
\t}
\tif (iModified > 0)
\t{
\t\tvar oModified =
\t\t{
\t\t\t"value":  iModified,
\t\t\t"label": "{$sModified}",
\t\t\t"alpha": fAlpha,
\t\t\t"label-colour": "#3333CC",
\t\t};
\t\toResult.elements[0].values.push(oModified);
\t\toResult.elements[0].colours.push('#6666FF');
\t}
\tif (iCreated > 0)
\t{
\t\tvar oCreated =
\t\t{
\t\t\t"value":  iCreated,
\t\t\t"label": "{$sCreated}",
\t\t\t"alpha": fAlpha,
\t\t\t"label-colour": "#33CC33",
\t\t\t
\t\t};
\t\toResult.elements[0].values.push(oCreated);
\t\toResult.elements[0].colours.push('#66FF66');
\t}
\tif (iUnchanged > 0)
\t{
\t\tvar oUnchanged =
\t\t{
\t\t\t"value":  iUnchanged,
\t\t\t"label": "{$sUnchanged}",
\t\t\t"alpha": fAlpha,
\t\t\t"label-colour": "#333333",
\t\t\t
\t\t};
\t\toResult.elements[0].values.push(oUnchanged);
\t\toResult.elements[0].colours.push('#666666');
\t}

\treturn JSON.stringify(oResult);
}
EOF
);
        if ($iErrors > 0) {
            return $aResult;
        } else {
            return null;
        }
    }
 public function ReadParameters()
 {
     parent::ReadParameters();
     $sQueryId = utils::ReadParam('query', null, true);
     $sFields = utils::ReadParam('fields', null, true, 'raw_data');
     if (($sFields === null || $sFields === '') && $sQueryId === null) {
         throw new BulkExportMissingParameterException('fields');
     } else {
         if ($sQueryId !== null && $sQueryId !== null) {
             $oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
             $oQueries = new DBObjectSet($oSearch);
             if ($oQueries->Count() > 0) {
                 $oQuery = $oQueries->Fetch();
                 if ($sFields === null || $sFields === '') {
                     // No 'fields' parameter supplied, take the fields from the query phrasebook definition
                     $sFields = trim($oQuery->Get('fields'));
                     if ($sFields === '') {
                         throw new BulkExportMissingParameterException('fields');
                     }
                 }
             } else {
                 throw BulkExportException('Invalid value for the parameter: query. There is no Query Phrasebook with id = ' . $sQueryId, Dict::Format('Core:BulkExport:InvalidParameter_Query', $sQueryId));
             }
         }
     }
     // Interpret (and check) the list of fields
     //
     $aSelectedClasses = $this->oSearch->GetSelectedClasses();
     $aAliases = array_keys($aSelectedClasses);
     $aAuthorizedClasses = array();
     foreach ($aSelectedClasses as $sAlias => $sClassName) {
         if (UserRights::IsActionAllowed($sClassName, UR_ACTION_BULK_READ) == UR_ALLOWED_YES) {
             $aAuthorizedClasses[$sAlias] = $sClassName;
         }
     }
     $aFields = explode(',', $sFields);
     $this->aStatusInfo['fields'] = array();
     foreach ($aFields as $sFieldSpec) {
         // Trim the values since it's natural to write: fields=name, first_name, org_name instead of fields=name,first_name,org_name
         $sExtendedAttCode = trim($sFieldSpec);
         if (preg_match('/^([^\\.]+)\\.(.+)$/', $sExtendedAttCode, $aMatches)) {
             $sAlias = $aMatches[1];
             $sAttCode = $aMatches[2];
         } else {
             $sAlias = reset($aAliases);
             $sAttCode = $sExtendedAttCode;
         }
         if (!array_key_exists($sAlias, $aSelectedClasses)) {
             throw new Exception("Invalid alias '{$sAlias}' for the column '{$sExtendedAttCode}'. Availables aliases: '" . implode("', '", $aAliases) . "'");
         }
         $sClass = $aSelectedClasses[$sAlias];
         if (!array_key_exists($sAlias, $aAuthorizedClasses)) {
             throw new Exception("You do not have enough permissions to bulk read data of class '{$sClass}' (alias: {$sAlias})");
         }
         if ($this->bLocalizeOutput) {
             try {
                 $sLabel = MetaModel::GetLabel($sClass, $sAttCode);
             } catch (Exception $e) {
                 throw new Exception("Wrong field specification '{$sFieldSpec}': " . $e->getMessage());
             }
         } else {
             $sLabel = $sAttCode;
         }
         if (count($aAuthorizedClasses) > 1) {
             $sColLabel = $sAlias . '.' . $sLabel;
         } else {
             $sColLabel = $sLabel;
         }
         $this->aStatusInfo['fields'][] = array('sFieldSpec' => $sExtendedAttCode, 'sAlias' => $sAlias, 'sClass' => $sClass, 'sAttCode' => $sAttCode, 'sLabel' => $sLabel, 'sColLabel' => $sColLabel);
     }
 }
 public function GetHeader()
 {
     $oSet = new DBObjectSet($this->oSearch);
     $this->aStatusInfo['status'] = 'running';
     $this->aStatusInfo['position'] = 0;
     $this->aStatusInfo['total'] = $oSet->Count();
     $aSelectedClasses = $this->oSearch->GetSelectedClasses();
     $aData = array();
     foreach ($this->aStatusInfo['fields'] as $sExtendedAttCode) {
         if (preg_match('/^([^\\.]+)\\.(.+)$/', $sExtendedAttCode, $aMatches)) {
             $sAlias = $aMatches[1];
             $sAttCode = $aMatches[2];
         } else {
             $sAlias = reset($aSelectedClasses);
             $sAttCode = $sExtendedAttCode;
         }
         if (!array_key_exists($sAlias, $aSelectedClasses)) {
             throw new Exception("Invalid alias '{$sAlias}' for the column '{$sExtendedAttCode}'. Availables aliases: '" . implode("', '", array_keys($aSelectedClasses)) . "'");
         }
         $sClass = $aSelectedClasses[$sAlias];
         switch ($sAttCode) {
             case 'id':
                 if (count($aSelectedClasses) > 1) {
                     $aData[] = $sAlias . '.id';
                     //@@@
                 } else {
                     $aData[] = 'id';
                     //@@@
                 }
                 break;
             default:
                 $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
                 $sColLabel = $this->aStatusInfo['localize'] ? MetaModel::GetLabel($sClass, $sAttCode) : $sAttCode;
                 $oFinalAttDef = $oAttDef->GetFinalAttDef();
                 if (get_class($oFinalAttDef) == 'AttributeDateTime') {
                     if (count($aSelectedClasses) > 1) {
                         $aData[] = $sAlias . '.' . $sColLabel . ' (' . Dict::S('UI:SplitDateTime-Date') . ')';
                         $aData[] = $sAlias . '.' . $sColLabel . ' (' . Dict::S('UI:SplitDateTime-Time') . ')';
                     } else {
                         $aData[] = $sColLabel . ' (' . Dict::S('UI:SplitDateTime-Date') . ')';
                         $aData[] = $sColLabel . ' (' . Dict::S('UI:SplitDateTime-Time') . ')';
                     }
                 } else {
                     if (count($aSelectedClasses) > 1) {
                         $aData[] = $sAlias . '.' . $sColLabel;
                     } else {
                         $aData[] = $sColLabel;
                     }
                 }
         }
     }
     $sData = "<table border=\"1\">\n";
     $sData .= "<tr>\n";
     foreach ($aData as $sLabel) {
         $sData .= "<td>" . $sLabel . "</td>\n";
     }
     $sData .= "</tr>\n";
     return $sData;
 }
 protected function GetTableConfig()
 {
     $aAttribs = array();
     $aAttribs['form::select'] = array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$this->sInputid}:not(:disabled)', this.checked);\" class=\"checkAll\"></input>", 'description' => Dict::S('UI:SelectAllToggle+'));
     foreach ($this->aZlist as $sLinkedAttCode) {
         $oAttDef = MetaModel::GetAttributeDef($this->sLinkedClass, $sLinkedAttCode);
         $aAttribs[$sLinkedAttCode] = array('label' => MetaModel::GetLabel($this->sLinkedClass, $sLinkedAttCode), 'description' => $oAttDef->GetOrderByHint());
     }
     return $aAttribs;
 }
예제 #12
0
             $aExtKeys[$sExtKeyAttCode][$sRemoteAttCode] = $iFieldId;
         } else {
             $aAttList[$sFieldName] = $iFieldId;
         }
     }
 }
 // Make sure there are some reconciliation keys
 //
 if (empty($sReconcKeys)) {
     $aReconcSpec = array();
     // Base reconciliation scheme on the default one
     // The reconciliation attributes not present in the data will be ignored
     foreach (MetaModel::GetReconcKeys($sClass) as $sReconcKeyAttCode) {
         if (in_array($sReconcKeyAttCode, $aFieldList)) {
             if ($bLocalize) {
                 $aReconcSpec[] = MetaModel::GetLabel($sClass, $sReconcKeyAttCode);
             } else {
                 $aReconcSpec[] = $sReconcKeyAttCode;
             }
         }
     }
     if (count($aReconcSpec) == 0) {
         throw new BulkLoadException("No reconciliation scheme could be defined, please add a column corresponding to one defined reconciliation key (class: '{$sClass}', reconciliation:" . implode(',', MetaModel::GetReconcKeys($sClass)) . ")");
     }
     $sReconcKeys = implode(',', $aReconcSpec);
 }
 // Interpret the list of reconciliation keys
 //
 $aFinalReconcilKeys = array();
 $aReconcilKeysReport = array();
 foreach (explode(',', $sReconcKeys) as $sReconcKey) {
예제 #13
0
 function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
 {
     if ($bEditMode) {
         return array();
     }
     // Not editable
     $aDetails = array();
     $sClass = get_class($this);
     $aZList = MetaModel::FlattenZlist(MetaModel::GetZListItems($sClass, 'details'));
     foreach ($aZList as $sAttCode) {
         $sDisplayValue = $this->GetAsHTML($sAttCode);
         $aDetails[] = array('label' => '<span title="' . MetaModel::GetDescription($sClass, $sAttCode) . '">' . MetaModel::GetLabel($sClass, $sAttCode) . '</span>', 'value' => $sDisplayValue);
     }
     $oPage->Details($aDetails);
     return array();
 }
예제 #14
0
 function test_search()
 {
     echo "<h4>Two searches</h4>";
     $oFilterAllDevs = new DBObjectSearch("cmdbTeam");
     $oAllDevs = new DBObjectSet($oFilterAllDevs);
     echo "Found " . $oAllDevs->Count() . " items.</br>\n";
     while ($oDev = $oAllDevs->Fetch()) {
         $aValues = array();
         foreach (MetaModel::GetAttributesList($oAllDevs->GetClass()) as $sAttCode) {
             $aValues[] = MetaModel::GetLabel(get_class($oDev), $sAttCode) . " (" . MetaModel::GetDescription(get_class($oDev), $sAttCode) . ") = " . $oDev->GetAsHTML($sAttCode);
         }
         echo $oDev->GetKey() . " => " . implode(", ", $aValues) . "</br>\n";
     }
     // a second one
     $oMyFilter = new DBObjectSearch("cmdbContact");
     //$oMyFilter->AddCondition("name", "aii", "Finishes with");
     $oMyFilter->AddCondition("name", "aii");
     $this->search_and_show_list($oMyFilter);
 }
 protected function GetFieldAsHtml($sClass, $sAttCode, $sStateAttCode)
 {
     $retVal = null;
     if ($this->IsNew()) {
         $iFlags = $this->GetInitialStateAttributeFlags($sAttCode);
     } else {
         $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 .= "<br/>" . Dict::Format('UI:OpenDocumentInNewWindow_', $oDocument->GetDisplayLink(get_class($this), $this->GetKey(), $sAttCode)) . ", \n";
                 $sDisplayValue .= "<br/>" . Dict::Format('UI:DownloadDocument_', $oDocument->GetDownloadLink(get_class($this), $this->GetKey(), $sAttCode)) . ", \n";
             } else {
                 $sDisplayValue = $this->GetAsHTML($sAttCode);
             }
         }
         $retVal = array('label' => '<span title="' . MetaModel::GetDescription($sClass, $sAttCode) . '">' . MetaModel::GetLabel($sClass, $sAttCode) . '</span>', 'value' => $sDisplayValue);
     }
     return $retVal;
 }
예제 #16
0
 public function DisplayDetails(WebPage $oPage, $bEditMode = false)
 {
     $oPage->add('<h1>' . MetaModel::GetName(get_class($this)) . ': ' . $this->GetName() . '</h1>');
     $aValues = array();
     $aList = MetaModel::FlattenZList(MetaModel::GetZListItems(get_class($this), 'details'));
     if (empty($aList)) {
         $aList = array_keys(MetaModel::ListAttributeDefs(get_class($this)));
     }
     foreach ($aList as $sAttCode) {
         $aValues[$sAttCode] = array('label' => MetaModel::GetLabel(get_class($this), $sAttCode), 'value' => $this->GetAsHTML($sAttCode));
     }
     $oPage->details($aValues);
 }
 /**
  * Display the attributes of an object (no title, no form)
  * @param Object $oObj Any kind of object
  * @param aAttList The list of attributes to display
  * @return void
  */
 public function DisplayObjectDetails($oObj, $aAttList)
 {
     $sClass = get_class($oObj);
     $aDetails = array();
     foreach ($aAttList as $sAttCode) {
         $iFlags = $oObj->GetAttributeFlags($sAttCode);
         $oAttDef = MetaModel::GetAttributeDef(get_class($oObj), $sAttCode);
         if (!$oAttDef->IsLinkSet() && ($iFlags & OPT_ATT_HIDDEN) == 0) {
             // Don't display linked set and non-visible attributes (in this state)
             $sDisplayValue = $oObj->GetAsHTML($sAttCode);
             $aDetails[] = array('label' => '<span title="' . MetaModel::GetDescription($sClass, $sAttCode) . '">' . MetaModel::GetLabel($sClass, $sAttCode) . '</span>', 'value' => $sDisplayValue);
         }
     }
     $this->details($aDetails);
 }
예제 #18
0
 /**
  * Display the details of an import
  */
 static function DisplayImportHistoryDetails(iTopWebPage $oPage, $iChange)
 {
     if ($iChange == 0) {
         throw new Exception("Missing parameter changeid");
     }
     $oChange = MetaModel::GetObject('CMDBChange', $iChange, false);
     if (is_null($oChange)) {
         throw new Exception("Unknown change: {$iChange}");
     }
     $oPage->add("<div><p><h1>" . Dict::Format('UI:History:BulkImportDetails', $oChange->Get('date'), $oChange->GetUserName()) . "</h1></p></div>\n");
     // Assumption : change made one single class of objects
     $aObjects = array();
     $aAttributes = array();
     // array of attcode => occurences
     $oOpSearch = DBObjectSearch::FromOQL("SELECT CMDBChangeOp WHERE change = :change_id");
     $oOpSet = new DBObjectSet($oOpSearch, array(), array('change_id' => $iChange));
     while ($oOperation = $oOpSet->Fetch()) {
         $sClass = $oOperation->Get('objclass');
         $iKey = $oOperation->Get('objkey');
         $iObjId = "{$sClass}::{$iKey}";
         if (!isset($aObjects[$iObjId])) {
             $aObjects[$iObjId] = array();
             $aObjects[$iObjId]['__class__'] = $sClass;
             $aObjects[$iObjId]['__id__'] = $iKey;
         }
         if (get_class($oOperation) == 'CMDBChangeOpCreate') {
             $aObjects[$iObjId]['__created__'] = true;
         } elseif ($oOperation instanceof CMDBChangeOpSetAttribute) {
             $sAttCode = $oOperation->Get('attcode');
             if (get_class($oOperation) == 'CMDBChangeOpSetAttributeScalar') {
                 $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
                 if ($oAttDef->IsExternalKey()) {
                     $sOldValue = Dict::S('UI:UndefinedObject');
                     if ($oOperation->Get('oldvalue') != 0) {
                         $oOldTarget = MetaModel::GetObject($oAttDef->GetTargetClass(), $oOperation->Get('oldvalue'));
                         $sOldValue = $oOldTarget->GetHyperlink();
                     }
                     $sNewValue = Dict::S('UI:UndefinedObject');
                     if ($oOperation->Get('newvalue') != 0) {
                         $oNewTarget = MetaModel::GetObject($oAttDef->GetTargetClass(), $oOperation->Get('newvalue'));
                         $sNewValue = $oNewTarget->GetHyperlink();
                     }
                 } else {
                     $sOldValue = $oOperation->GetAsHTML('oldvalue');
                     $sNewValue = $oOperation->GetAsHTML('newvalue');
                 }
                 $aObjects[$iObjId][$sAttCode] = $sOldValue . ' -&gt; ' . $sNewValue;
             } else {
                 $aObjects[$iObjId][$sAttCode] = 'n/a';
             }
             if (isset($aAttributes[$sAttCode])) {
                 $aAttributes[$sAttCode]++;
             } else {
                 $aAttributes[$sAttCode] = 1;
             }
         }
     }
     $aDetails = array();
     foreach ($aObjects as $iUId => $aObjData) {
         $aRow = array();
         $oObject = MetaModel::GetObject($aObjData['__class__'], $aObjData['__id__'], false);
         if (is_null($oObject)) {
             $aRow['object'] = $aObjData['__class__'] . '::' . $aObjData['__id__'] . ' (deleted)';
         } else {
             $aRow['object'] = $oObject->GetHyperlink();
         }
         if (isset($aObjData['__created__'])) {
             $aRow['operation'] = Dict::S('Change:ObjectCreated');
         } else {
             $aRow['operation'] = Dict::S('Change:ObjectModified');
         }
         foreach ($aAttributes as $sAttCode => $iOccurences) {
             if (isset($aObjData[$sAttCode])) {
                 $aRow[$sAttCode] = $aObjData[$sAttCode];
             } elseif (!is_null($oObject)) {
                 // This is the current vaslue: $oObject->GetAsHtml($sAttCode)
                 // whereas we are displaying the value that was set at the time
                 // the object was created
                 // This requires addtional coding...let's do that later
                 $aRow[$sAttCode] = '';
             } else {
                 $aRow[$sAttCode] = '';
             }
         }
         $aDetails[] = $aRow;
     }
     $aConfig = array();
     $aConfig['object'] = array('label' => MetaModel::GetName($sClass), 'description' => MetaModel::GetClassDescription($sClass));
     $aConfig['operation'] = array('label' => Dict::S('UI:History:Changes'), 'description' => Dict::S('UI:History:Changes+'));
     foreach ($aAttributes as $sAttCode => $iOccurences) {
         $aConfig[$sAttCode] = array('label' => MetaModel::GetLabel($sClass, $sAttCode), 'description' => MetaModel::GetDescription($sClass, $sAttCode));
     }
     $oPage->table($aConfig, $aDetails);
 }