diff --git a/application/ui.linkswidget.class.inc.php b/application/ui.linkswidget.class.inc.php index 41dec06c0..820f8e74e 100644 --- a/application/ui.linkswidget.class.inc.php +++ b/application/ui.linkswidget.class.inc.php @@ -387,36 +387,42 @@ EOF * @param WebPage $oPage * @param DBObject $oCurrentObj * @param $sJson + * @param array $aAlreadyLinkedIds * * @throws \CoreException * @throws \DictExceptionMissingString * @throws \Exception */ - public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson) + public function GetObjectPickerDialog($oPage, $oCurrentObj, $sJson, $aAlreadyLinkedIds = array()) { $bOpen = MetaModel::GetConfig()->Get('legacy_search_drawer_open'); $sHtml = "
\n"; $oFilter = new DBObjectSearch($this->m_sRemoteClass); - $this->SetSearchDefaultFromContext($oCurrentObj, $oFilter); + if (!$this->m_bDuplicatesAllowed && count($aAlreadyLinkedIds) > 0) + { + $oFilter->AddCondition('id', $aAlreadyLinkedIds, 'NOTIN'); + } + //$this->SetSearchDefaultFromContext($oCurrentObj, $oFilter); $oBlock = new DisplayBlock($oFilter, 'search', false); $sHtml .= $oBlock->GetDisplay($oPage, "SearchFormToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}", array( 'menu' => false, 'open' => $bOpen, 'table_id' => "SearchResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}", + 'table_id2' => 'add_'.$this->m_sAttCode, 'table_inner_id' => "ResultsToAdd_{$this->m_sAttCode}{$this->m_sNameSuffix}", 'selection_mode' => true, 'json' => $sJson, 'cssCount' => '#count_'.$this->m_sAttCode.$this->m_sNameSuffix )); - $sHtml .= "
m_sAttCode}{$this->m_sNameSuffix}\" OnSubmit=\"return oWidget{$this->m_iInputId}.DoAddObjects(this.id);\">\n"; + $sHtml .= "
m_sAttCode}{$this->m_sNameSuffix}\">\n"; $sHtml .= "
m_sAttCode}{$this->m_sNameSuffix}\" style=\"vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;\">\n"; $sHtml .= "

".Dict::S('UI:Message:EmptyList:UseSearchForm')."

\n"; $sHtml .= "
\n"; $sHtml .= "m_sAttCode}{$this->m_sNameSuffix}\" value=\"0\"/>"; - $sHtml .= "m_sAttCode}{$this->m_sNameSuffix}').dialog('close');\">  m_sAttCode}{$this->m_sNameSuffix}\" disabled=\"disabled\" type=\"submit\" value=\"".Dict::S('UI:Button:Add')."\">"; + $sHtml .= "m_sAttCode}{$this->m_sNameSuffix}').dialog('close');\">  m_sAttCode}{$this->m_sNameSuffix}\" disabled=\"disabled\" type=\"button\" onclick=\"return oWidget{$this->m_iInputId}.DoAddObjects(this.id);\" value=\"".Dict::S('UI:Button:Add')."\">"; + $sHtml .= "
\n"; $sHtml .= "
\n"; - $sHtml .= "\n"; $oPage->add($sHtml); $oPage->add_ready_script("$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, resizeStop: oWidget{$this->m_iInputId}.UpdateSizes });"); $oPage->add_ready_script("$('#dlg_{$this->m_sAttCode}{$this->m_sNameSuffix}').dialog('option', {title:'".addslashes(Dict::Format('UI:AddObjectsOf_Class_LinkedWith_Class', MetaModel::GetName($this->m_sLinkedClass), MetaModel::GetName($this->m_sClass)))."'});"); diff --git a/pages/ajax.render.php b/pages/ajax.render.php index d27d54949..78c553b13 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -39,389 +39,225 @@ try { require_once(APPROOT.'/application/startup.inc.php'); require_once(APPROOT.'/application/user.preferences.class.inc.php'); - + require_once(APPROOT.'/application/loginwebpage.class.inc.php'); LoginWebPage::DoLoginEx(null /* any portal */, false); - + $oPage = new ajax_page(""); $oPage->no_cache(); - + $operation = utils::ReadParam('operation', ''); $sFilter = stripslashes(utils::ReadParam('filter', '', false, 'raw_data')); $sEncoding = utils::ReadParam('encoding', 'serialize'); $sClass = utils::ReadParam('class', 'MissingAjaxParam', false, 'class'); $sStyle = utils::ReadParam('style', 'list'); - switch($operation) + switch ($operation) { case 'datatable': case 'pagination': - $oPage->SetContentType('text/html'); - $extraParams = utils::ReadParam('extra_param', '', false, 'raw_data'); - $aExtraParams = array(); - if (is_array($extraParams)) - { - $aExtraParams = $extraParams; - } - else - { - $sExtraParams = stripslashes($extraParams); - if (!empty($sExtraParams)) + $oPage->SetContentType('text/html'); + $extraParams = utils::ReadParam('extra_param', '', false, 'raw_data'); + $aExtraParams = array(); + if (is_array($extraParams)) { - $val = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */); - if ($val !== null) + $aExtraParams = $extraParams; + } + else + { + $sExtraParams = stripslashes($extraParams); + if (!empty($sExtraParams)) { - $aExtraParams = $val; + $val = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */); + if ($val !== null) + { + $aExtraParams = $val; + } } } - } - if ($sEncoding == 'oql') - { - $oFilter = DBSearch::FromOQL($sFilter); - } - else - { - $oFilter = DBSearch::unserialize($sFilter); - } - $iStart = utils::ReadParam('start',0); - $iEnd = utils::ReadParam('end',1); - $iSortCol = utils::ReadParam('sort_col','null'); - $sSelectMode = utils::ReadParam('select_mode', ''); - if (!empty($sSelectMode) && ($sSelectMode != 'none')) - { - // The first column is used for the selection (radio / checkbox) and is not sortable - $iSortCol--; - } - $bDisplayKey = utils::ReadParam('display_key', 'true') == 'true'; - $aColumns = utils::ReadParam('columns', array(), false, 'raw_data'); - $aClassAliases = utils::ReadParam('class_aliases', array()); - $iListId = utils::ReadParam('list_id', 0); - - // Filter the list to removed linked set since we are not able to display them here - $aOrderBy = array(); - $iSortIndex = 0; - - $aColumnsLoad = array(); - foreach($aClassAliases as $sAlias => $sClassName) - { - $aColumnsLoad[$sAlias] = array(); - foreach($aColumns[$sAlias] as $sAttCode => $aData) + if ($sEncoding == 'oql') { - if ($aData['checked'] == 'true') + $oFilter = DBSearch::FromOQL($sFilter); + } + else + { + $oFilter = DBSearch::unserialize($sFilter); + } + $iStart = utils::ReadParam('start', 0); + $iEnd = utils::ReadParam('end', 1); + $iSortCol = utils::ReadParam('sort_col', 'null'); + $sSelectMode = utils::ReadParam('select_mode', ''); + if (!empty($sSelectMode) && ($sSelectMode != 'none')) + { + // The first column is used for the selection (radio / checkbox) and is not sortable + $iSortCol--; + } + $bDisplayKey = utils::ReadParam('display_key', 'true') == 'true'; + $aColumns = utils::ReadParam('columns', array(), false, 'raw_data'); + $aClassAliases = utils::ReadParam('class_aliases', array()); + $iListId = utils::ReadParam('list_id', 0); + + // Filter the list to removed linked set since we are not able to display them here + $aOrderBy = array(); + $iSortIndex = 0; + + $aColumnsLoad = array(); + foreach($aClassAliases as $sAlias => $sClassName) + { + $aColumnsLoad[$sAlias] = array(); + foreach($aColumns[$sAlias] as $sAttCode => $aData) { - $aColumns[$sAlias][$sAttCode]['checked'] = true; - if ($sAttCode == '_key_') + if ($aData['checked'] == 'true') { - if ($iSortCol == $iSortIndex) + $aColumns[$sAlias][$sAttCode]['checked'] = true; + if ($sAttCode == '_key_') { - if (!MetaModel::HasChildrenClasses($oFilter->GetClass())) + if ($iSortCol == $iSortIndex) { - $aNameSpec = MetaModel::GetNameSpec($oFilter->GetClass()); - if ($aNameSpec[0] == '%1$s') + if (!MetaModel::HasChildrenClasses($oFilter->GetClass())) { - // The name is made of a single column, let's sort according to the sort algorithm for this column - $aOrderBy[$sAlias.'.'.$aNameSpec[1][0]] = (utils::ReadParam('sort_order', 'asc') == 'asc'); + $aNameSpec = MetaModel::GetNameSpec($oFilter->GetClass()); + if ($aNameSpec[0] == '%1$s') + { + // The name is made of a single column, let's sort according to the sort algorithm for this column + $aOrderBy[$sAlias.'.'.$aNameSpec[1][0]] = (utils::ReadParam('sort_order', 'asc') == 'asc'); + } + else + { + $aOrderBy[$sAlias.'.'.'friendlyname'] = (utils::ReadParam('sort_order', 'asc') == 'asc'); + } } else { $aOrderBy[$sAlias.'.'.'friendlyname'] = (utils::ReadParam('sort_order', 'asc') == 'asc'); } } - else - { - $aOrderBy[$sAlias.'.'.'friendlyname'] = (utils::ReadParam('sort_order', 'asc') == 'asc'); - } - } - } - else - { - $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode); - if ($oAttDef instanceof AttributeLinkedSet) - { - // Removed from the display list - unset($aColumns[$sAlias][$sAttCode]); } else { - $aColumnsLoad[$sAlias][] = $sAttCode; - } - if ($iSortCol == $iSortIndex) - { - if ($oAttDef->IsExternalKey()) + $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode); + if ($oAttDef instanceof AttributeLinkedSet) { - $sSortCol = $sAttCode.'_friendlyname'; + // Removed from the display list + unset($aColumns[$sAlias][$sAttCode]); } else { - $sSortCol = $sAttCode; + $aColumnsLoad[$sAlias][] = $sAttCode; + } + if ($iSortCol == $iSortIndex) + { + if ($oAttDef->IsExternalKey()) + { + $sSortCol = $sAttCode.'_friendlyname'; + } + else + { + $sSortCol = $sAttCode; + } + $aOrderBy[$sAlias.'.'.$sSortCol] = (utils::ReadParam('sort_order', 'asc') == 'asc'); } - $aOrderBy[$sAlias.'.'.$sSortCol] = (utils::ReadParam('sort_order', 'asc') == 'asc'); } + $iSortIndex++; + } + else + { + $aColumns[$sAlias][$sAttCode]['checked'] = false; } - $iSortIndex++; - } - else - { - $aColumns[$sAlias][$sAttCode]['checked'] = false; } + } - } - - // Load only the requested columns - $oSet = new DBObjectSet($oFilter, $aOrderBy, $aExtraParams, null, $iEnd-$iStart, $iStart); - $oSet->OptimizeColumnLoad($aColumnsLoad); + // Load only the requested columns + $oSet = new DBObjectSet($oFilter, $aOrderBy, $aExtraParams, null, $iEnd - $iStart, $iStart); + $oSet->OptimizeColumnLoad($aColumnsLoad); - if (isset($aExtraParams['show_obsolete_data'])) - { - $bShowObsoleteData = $aExtraParams['show_obsolete_data']; - } - else - { - $bShowObsoleteData = utils::ShowObsoleteData(); - } - $oSet->SetShowObsoleteData($bShowObsoleteData); - - $oDataTable = new DataTable($iListId, $oSet, $oSet->GetSelectedClasses()); - if ($operation == 'datatable') - { - // Redraw the whole table - $sHtml = $oDataTable->UpdatePager($oPage, $iEnd-$iStart, $iStart); // Set the default page size - $sHtml .= $oDataTable->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iEnd-$iStart, $bDisplayKey, $aExtraParams); - } - else - { - // redraw just the needed rows - $sHtml = $oDataTable->GetAsHTMLTableRows($oPage, $iEnd-$iStart, $aColumns, $sSelectMode, $bDisplayKey, $aExtraParams); - } - $oPage->add($sHtml); - break; - - case 'datatable_save_settings': - $oPage->SetContentType('text/plain'); - $iPageSize = utils::ReadParam('page_size', 10); - $sTableId = utils::ReadParam('table_id', null, false, 'raw_data'); - $bSaveAsDefaults = (utils::ReadParam('defaults', 'true') == 'true'); - $aClassAliases = utils::ReadParam('class_aliases', array(), false, 'raw_data'); - $aColumns = utils::ReadParam('columns', array(), false, 'raw_data'); - - foreach($aColumns as $sAlias => $aList) - { - foreach($aList as $sAttCode => $aData) + if (isset($aExtraParams['show_obsolete_data'])) { - $aColumns[$sAlias][$sAttCode]['checked'] = ($aData['checked'] == 'true'); - $aColumns[$sAlias][$sAttCode]['disabled'] = ($aData['disabled'] == 'true'); - $aColumns[$sAlias][$sAttCode]['sort'] = ($aData['sort']); - } - } - - $oSettings = new DataTableSettings($aClassAliases, $sTableId); - $oSettings->iDefaultPageSize = $iPageSize; - $oSettings->aColumns = $aColumns; - - if ($bSaveAsDefaults) - { - if ($sTableId != null) - { - $oCurrSettings = DataTableSettings::GetTableSettings($aClassAliases, $sTableId, true /* bOnlyTable */ ); - if ($oCurrSettings) - { - $oCurrSettings->ResetToDefault(false); // Reset this table to the defaults - } - } - $bRet = $oSettings->SaveAsDefault(); - } - else - { - $bRet = $oSettings->Save(); - } - $oPage->add($bRet ? 'Ok' : 'KO'); - break; - - case 'datatable_reset_settings': - $oPage->SetContentType('text/plain'); - $sTableId = utils::ReadParam('table_id', null, false, 'raw_data'); - $aClassAliases = utils::ReadParam('class_aliases', array(), false, 'raw_data'); - $bResetAll = (utils::ReadParam('defaults', 'true') == 'true'); - - $oSettings = new DataTableSettings($aClassAliases, $sTableId); - $bRet = $oSettings->ResetToDefault($bResetAll); - $oPage->add($bRet ? 'Ok' : 'KO'); - break; - - // ui.linkswidget - case 'addObjects': - $oPage->SetContentType('text/html'); - $sAttCode = utils::ReadParam('sAttCode', ''); - $iInputId = utils::ReadParam('iInputId', ''); - $sSuffix = utils::ReadParam('sSuffix', ''); - $bDuplicates = (utils::ReadParam('bDuplicates', 'false') == 'false') ? false : true; - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - if (!empty($sJson)) - { - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - } - else - { - // Search form: no current object - $oObj = null; - } - $oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId, $sSuffix, $bDuplicates); - $oWidget->GetObjectPickerDialog($oPage, $oObj, $sJson); - break; - - // ui.linkswidget - case 'searchObjectsToAdd': - $oPage->SetContentType('text/html'); - $sRemoteClass = utils::ReadParam('sRemoteClass', '', false, 'class'); - $sAttCode = utils::ReadParam('sAttCode', ''); - $iInputId = utils::ReadParam('iInputId', ''); - $sSuffix = utils::ReadParam('sSuffix', ''); - $bDuplicates = (utils::ReadParam('bDuplicates', 'false') == 'false') ? false : true; - $aAlreadyLinked = utils::ReadParam('aAlreadyLinked', array()); - $oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId, $sSuffix, $bDuplicates); - $oWidget->SearchObjectsToAdd($oPage, $sRemoteClass, $aAlreadyLinked); - break; - - //ui.linksdirectwidget - case 'createObject': - $oPage->SetContentType('text/html'); - $sClass = utils::ReadParam('class', '', false, 'class'); - $sRealClass = utils::ReadParam('real_class', '', false, 'class'); - $sAttCode = utils::ReadParam('att_code', ''); - $iInputId = utils::ReadParam('iInputId', ''); - $oPage->SetContentType('text/html'); - $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); - $oWidget->GetObjectCreationDlg($oPage, $sRealClass); - break; - - // ui.linksdirectwidget - case 'getLinksetRow': - $oPage->SetContentType('text/html'); - $sClass = utils::ReadParam('class', '', false, 'class'); - $sRealClass = utils::ReadParam('real_class', '', false, 'class'); - $sAttCode = utils::ReadParam('att_code', ''); - $iInputId = utils::ReadParam('iInputId', ''); - $iTempId = utils::ReadParam('tempId', ''); - $aValues = utils::ReadParam('values', array(), false, 'raw_data'); - $oPage->SetContentType('text/html'); - $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); - $oPage->add($oWidget->GetRow($oPage, $sRealClass, $aValues, -$iTempId)); - break; - - // ui.linksdirectwidget - case 'selectObjectsToAdd': - $oPage->SetContentType('text/html'); - $sClass = utils::ReadParam('class', '', false, 'class'); - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - $oObj = null; - if ($sJson != '') - { - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - } - $sRealClass = utils::ReadParam('real_class', '', false, 'class'); - $sAttCode = utils::ReadParam('att_code', ''); - $iInputId = utils::ReadParam('iInputId', ''); - $iCurrObjectId = utils::ReadParam('iObjId', 0); - $oPage->SetContentType('text/html'); - $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); - $oWidget->GetObjectsSelectionDlg($oPage, $oObj); - break; - - // ui.linksdirectwidget - case 'searchObjectsToAdd2': - $oPage->SetContentType('text/html'); - $sClass = utils::ReadParam('class', '', false, 'class'); - $sRealClass = utils::ReadParam('real_class', '', false, 'class'); - $sAttCode = utils::ReadParam('att_code', ''); - $iInputId = utils::ReadParam('iInputId', ''); - $aAlreadyLinked = utils::ReadParam('aAlreadyLinked', array()); - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - $oObj = null; - if ($sJson != '') - { - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - } - $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); - $oWidget->SearchObjectsToAdd($oPage, $sRealClass, $aAlreadyLinked, $oObj); - break; - - // ui.linksdirectwidget - case 'doAddObjects2': - $oPage->SetContentType('text/html'); - $oPage->SetContentType('text/html'); - $sClass = utils::ReadParam('class', '', false, 'class'); - $sRealClass = utils::ReadParam('real_class', '', false, 'class'); - $sAttCode = utils::ReadParam('att_code', ''); - $iInputId = utils::ReadParam('iInputId', ''); - $iCurrObjectId = utils::ReadParam('iObjId', 0); - $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); - if ($sFilter != '') - { - $oFullSetFilter = DBObjectSearch::unserialize($sFilter); - } - else - { - $oLinksetDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - $valuesDef = $oLinksetDef->GetValuesDef(); - if ($valuesDef === null) - { - $oFullSetFilter = new DBObjectSearch($oLinksetDef->GetLinkedClass()); + $bShowObsoleteData = $aExtraParams['show_obsolete_data']; } else { - if (!$valuesDef instanceof ValueSetObjects) + $bShowObsoleteData = utils::ShowObsoleteData(); + } + $oSet->SetShowObsoleteData($bShowObsoleteData); + + $oDataTable = new DataTable($iListId, $oSet, $oSet->GetSelectedClasses()); + if ($operation == 'datatable') + { + // Redraw the whole table + $sHtml = $oDataTable->UpdatePager($oPage, $iEnd - $iStart, $iStart); // Set the default page size + $sHtml .= $oDataTable->GetHTMLTable($oPage, $aColumns, $sSelectMode, $iEnd - $iStart, $bDisplayKey, $aExtraParams); + } + else + { + // redraw just the needed rows + $sHtml = $oDataTable->GetAsHTMLTableRows($oPage, $iEnd - $iStart, $aColumns, $sSelectMode, $bDisplayKey, $aExtraParams); + } + $oPage->add($sHtml); + break; + + case 'datatable_save_settings': + $oPage->SetContentType('text/plain'); + $iPageSize = utils::ReadParam('page_size', 10); + $sTableId = utils::ReadParam('table_id', null, false, 'raw_data'); + $bSaveAsDefaults = (utils::ReadParam('defaults', 'true') == 'true'); + $aClassAliases = utils::ReadParam('class_aliases', array(), false, 'raw_data'); + $aColumns = utils::ReadParam('columns', array(), false, 'raw_data'); + + foreach($aColumns as $sAlias => $aList) + { + foreach($aList as $sAttCode => $aData) { - throw new Exception('Error: only ValueSetObjects are supported for "allowed_values" in AttributeLinkedSet ('.$this->sClass.'/'.$this->sAttCode.').'); + $aColumns[$sAlias][$sAttCode]['checked'] = ($aData['checked'] == 'true'); + $aColumns[$sAlias][$sAttCode]['disabled'] = ($aData['disabled'] == 'true'); + $aColumns[$sAlias][$sAttCode]['sort'] = ($aData['sort']); } - $oFullSetFilter = DBObjectSearch::FromOQL($valuesDef->GetFilterExpression()); - } - } - $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); - $oWidget->DoAddObjects($oPage, $oFullSetFilter); - break; - - //////////////////////////////////////////////////////////// - - // ui.extkeywidget - case 'searchObjectsToSelect': - $oPage->SetContentType('text/html'); - $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); - $iInputId = utils::ReadParam('iInputId', ''); - $sRemoteClass = utils::ReadParam('sRemoteClass', '', false, 'class'); - $sFilter = utils::ReadParam('sFilter', '', false, 'raw_data'); - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - $sAttCode = utils::ReadParam('sAttCode', ''); - $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); - if (!empty($sJson)) - { - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - } - else - { - // Search form: no current object - $oObj = null; - } - $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode); - $oWidget->SearchObjectsToSelect($oPage, $sFilter, $sRemoteClass, $oObj); - break; - - // ui.extkeywidget: autocomplete - case 'ac_extkey': - $oPage->SetContentType('text/plain'); - $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); - $iInputId = utils::ReadParam('iInputId', ''); - $sFilter = utils::ReadParam('sFilter', '', false, 'raw_data'); - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - $sContains = utils::ReadParam('q', '', false, 'raw_data'); - $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); - if ($sContains !='') - { + } + + $oSettings = new DataTableSettings($aClassAliases, $sTableId); + $oSettings->iDefaultPageSize = $iPageSize; + $oSettings->aColumns = $aColumns; + + if ($bSaveAsDefaults) + { + if ($sTableId != null) + { + $oCurrSettings = DataTableSettings::GetTableSettings($aClassAliases, $sTableId, true /* bOnlyTable */); + if ($oCurrSettings) + { + $oCurrSettings->ResetToDefault(false); // Reset this table to the defaults + } + } + $bRet = $oSettings->SaveAsDefault(); + } + else + { + $bRet = $oSettings->Save(); + } + $oPage->add($bRet ? 'Ok' : 'KO'); + break; + + case 'datatable_reset_settings': + $oPage->SetContentType('text/plain'); + $sTableId = utils::ReadParam('table_id', null, false, 'raw_data'); + $aClassAliases = utils::ReadParam('class_aliases', array(), false, 'raw_data'); + $bResetAll = (utils::ReadParam('defaults', 'true') == 'true'); + + $oSettings = new DataTableSettings($aClassAliases, $sTableId); + $bRet = $oSettings->ResetToDefault($bResetAll); + $oPage->add($bRet ? 'Ok' : 'KO'); + break; + + // ui.linkswidget + case 'addObjects': + $oPage->SetContentType('text/html'); + $sAttCode = utils::ReadParam('sAttCode', ''); + $iInputId = utils::ReadParam('iInputId', ''); + $sSuffix = utils::ReadParam('sSuffix', ''); + $bDuplicates = (utils::ReadParam('bDuplicates', 'false') == 'false') ? false : true; + $sJson = utils::ReadParam('json', '', false, 'raw_data'); if (!empty($sJson)) { $oWizardHelper = WizardHelper::FromJSON($sJson); @@ -432,721 +268,884 @@ try // Search form: no current object $oObj = null; } - $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, '', $bSearchMode); - $oWidget->AutoComplete($oPage, $sFilter, $oObj, $sContains); - } - break; - + $oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId, $sSuffix, $bDuplicates); + $aAlreadyLinked = utils::ReadParam('aAlreadyLinked', array()); + $oWidget->GetObjectPickerDialog($oPage, $oObj, $sJson, $aAlreadyLinked); + break; + + // ui.linkswidget + case 'searchObjectsToAdd': + $oPage->SetContentType('text/html'); + $sRemoteClass = utils::ReadParam('sRemoteClass', '', false, 'class'); + $sAttCode = utils::ReadParam('sAttCode', ''); + $iInputId = utils::ReadParam('iInputId', ''); + $sSuffix = utils::ReadParam('sSuffix', ''); + $bDuplicates = (utils::ReadParam('bDuplicates', 'false') == 'false') ? false : true; + $aAlreadyLinked = utils::ReadParam('aAlreadyLinked', array()); + $oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId, $sSuffix, $bDuplicates); + $oWidget->SearchObjectsToAdd($oPage, $sRemoteClass, $aAlreadyLinked); + break; + + //ui.linksdirectwidget + case 'createObject': + $oPage->SetContentType('text/html'); + $sClass = utils::ReadParam('class', '', false, 'class'); + $sRealClass = utils::ReadParam('real_class', '', false, 'class'); + $sAttCode = utils::ReadParam('att_code', ''); + $iInputId = utils::ReadParam('iInputId', ''); + $oPage->SetContentType('text/html'); + $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); + $oWidget->GetObjectCreationDlg($oPage, $sRealClass); + break; + + // ui.linksdirectwidget + case 'getLinksetRow': + $oPage->SetContentType('text/html'); + $sClass = utils::ReadParam('class', '', false, 'class'); + $sRealClass = utils::ReadParam('real_class', '', false, 'class'); + $sAttCode = utils::ReadParam('att_code', ''); + $iInputId = utils::ReadParam('iInputId', ''); + $iTempId = utils::ReadParam('tempId', ''); + $aValues = utils::ReadParam('values', array(), false, 'raw_data'); + $oPage->SetContentType('text/html'); + $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); + $oPage->add($oWidget->GetRow($oPage, $sRealClass, $aValues, -$iTempId)); + break; + + // ui.linksdirectwidget + case 'selectObjectsToAdd': + $oPage->SetContentType('text/html'); + $sClass = utils::ReadParam('class', '', false, 'class'); + $sJson = utils::ReadParam('json', '', false, 'raw_data'); + $oObj = null; + if ($sJson != '') + { + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + } + $sRealClass = utils::ReadParam('real_class', '', false, 'class'); + $sAttCode = utils::ReadParam('att_code', ''); + $iInputId = utils::ReadParam('iInputId', ''); + $iCurrObjectId = utils::ReadParam('iObjId', 0); + $oPage->SetContentType('text/html'); + $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); + $oWidget->GetObjectsSelectionDlg($oPage, $oObj); + break; + + // ui.linksdirectwidget + case 'searchObjectsToAdd2': + $oPage->SetContentType('text/html'); + $sClass = utils::ReadParam('class', '', false, 'class'); + $sRealClass = utils::ReadParam('real_class', '', false, 'class'); + $sAttCode = utils::ReadParam('att_code', ''); + $iInputId = utils::ReadParam('iInputId', ''); + $aAlreadyLinked = utils::ReadParam('aAlreadyLinked', array()); + $sJson = utils::ReadParam('json', '', false, 'raw_data'); + $oObj = null; + if ($sJson != '') + { + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + } + $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); + $oWidget->SearchObjectsToAdd($oPage, $sRealClass, $aAlreadyLinked, $oObj); + break; + + // ui.linksdirectwidget + case 'doAddObjects2': + $oPage->SetContentType('text/html'); + $oPage->SetContentType('text/html'); + $sClass = utils::ReadParam('class', '', false, 'class'); + $sRealClass = utils::ReadParam('real_class', '', false, 'class'); + $sAttCode = utils::ReadParam('att_code', ''); + $iInputId = utils::ReadParam('iInputId', ''); + $iCurrObjectId = utils::ReadParam('iObjId', 0); + $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); + if ($sFilter != '') + { + $oFullSetFilter = DBObjectSearch::unserialize($sFilter); + } + else + { + $oLinksetDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + $valuesDef = $oLinksetDef->GetValuesDef(); + if ($valuesDef === null) + { + $oFullSetFilter = new DBObjectSearch($oLinksetDef->GetLinkedClass()); + } + else + { + if (!$valuesDef instanceof ValueSetObjects) + { + throw new Exception('Error: only ValueSetObjects are supported for "allowed_values" in AttributeLinkedSet ('.$this->sClass.'/'.$this->sAttCode.').'); + } + $oFullSetFilter = DBObjectSearch::FromOQL($valuesDef->GetFilterExpression()); + } + } + $oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iInputId); + $oWidget->DoAddObjects($oPage, $oFullSetFilter); + break; + + //////////////////////////////////////////////////////////// + + // ui.extkeywidget + case 'searchObjectsToSelect': + $oPage->SetContentType('text/html'); + $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); + $iInputId = utils::ReadParam('iInputId', ''); + $sRemoteClass = utils::ReadParam('sRemoteClass', '', false, 'class'); + $sFilter = utils::ReadParam('sFilter', '', false, 'raw_data'); + $sJson = utils::ReadParam('json', '', false, 'raw_data'); + $sAttCode = utils::ReadParam('sAttCode', ''); + $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); + if (!empty($sJson)) + { + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + } + else + { + // Search form: no current object + $oObj = null; + } + $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode); + $oWidget->SearchObjectsToSelect($oPage, $sFilter, $sRemoteClass, $oObj); + break; + + // ui.extkeywidget: autocomplete + case 'ac_extkey': + $oPage->SetContentType('text/plain'); + $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); + $iInputId = utils::ReadParam('iInputId', ''); + $sFilter = utils::ReadParam('sFilter', '', false, 'raw_data'); + $sJson = utils::ReadParam('json', '', false, 'raw_data'); + $sContains = utils::ReadParam('q', '', false, 'raw_data'); + $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); + if ($sContains != '') + { + if (!empty($sJson)) + { + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + } + else + { + // Search form: no current object + $oObj = null; + } + $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, '', $bSearchMode); + $oWidget->AutoComplete($oPage, $sFilter, $oObj, $sContains); + } + break; + // ui.extkeywidget case 'objectSearchForm': - $oPage->SetContentType('text/html'); - $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); - $iInputId = utils::ReadParam('iInputId', ''); - $sTitle = utils::ReadParam('sTitle', '', false, 'raw_data'); - $sAttCode = utils::ReadParam('sAttCode', ''); - $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); - $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode); - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - if (!empty($sJson)) - { - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - } - else - { - // Search form: no current object - $oObj = null; - } - $oWidget->GetSearchDialog($oPage, $sTitle, $oObj); - break; + $oPage->SetContentType('text/html'); + $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); + $iInputId = utils::ReadParam('iInputId', ''); + $sTitle = utils::ReadParam('sTitle', '', false, 'raw_data'); + $sAttCode = utils::ReadParam('sAttCode', ''); + $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); + $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode); + $sJson = utils::ReadParam('json', '', false, 'raw_data'); + if (!empty($sJson)) + { + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + } + else + { + // Search form: no current object + $oObj = null; + } + $oWidget->GetSearchDialog($oPage, $sTitle, $oObj); + break; // ui.extkeywidget case 'objectCreationForm': - $oPage->SetContentType('text/html'); - // Retrieving parameters - $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); - $iInputId = utils::ReadParam('iInputId', ''); - $sAttCode = utils::ReadParam('sAttCode', ''); - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - // Building form, if target class is abstract we ask the user for the desired leaf class - $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, false); - if(MetaModel::IsAbstract($sTargetClass)) - { - $oWidget->GetClassSelectionForm($oPage); - } - else - { - if (!empty($sJson)) - { - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - } - else - { - // Search form: no current object - $oObj = null; - } - $oWidget->GetObjectCreationForm($oPage, $oObj); - } - break; - + $oPage->SetContentType('text/html'); + // Retrieving parameters + $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); + $iInputId = utils::ReadParam('iInputId', ''); + $sAttCode = utils::ReadParam('sAttCode', ''); + $sJson = utils::ReadParam('json', '', false, 'raw_data'); + // Building form, if target class is abstract we ask the user for the desired leaf class + $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, false); + if (MetaModel::IsAbstract($sTargetClass)) + { + $oWidget->GetClassSelectionForm($oPage); + } + else + { + if (!empty($sJson)) + { + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + } + else + { + // Search form: no current object + $oObj = null; + } + $oWidget->GetObjectCreationForm($oPage, $oObj); + } + break; + // ui.extkeywidget case 'doCreateObject': - $oPage->SetContentType('application/json'); - $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); - $iInputId = utils::ReadParam('iInputId', ''); - $sFormPrefix = utils::ReadParam('sFormPrefix', ''); - $sAttCode = utils::ReadParam('sAttCode', ''); - $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, false); - $aResult = $oWidget->DoCreateObject($oPage); - echo json_encode($aResult); - break; - + $oPage->SetContentType('application/json'); + $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); + $iInputId = utils::ReadParam('iInputId', ''); + $sFormPrefix = utils::ReadParam('sFormPrefix', ''); + $sAttCode = utils::ReadParam('sAttCode', ''); + $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, false); + $aResult = $oWidget->DoCreateObject($oPage); + echo json_encode($aResult); + break; + // ui.extkeywidget case 'getObjectName': - $oPage->SetContentType('application/json'); - $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); - $iInputId = utils::ReadParam('iInputId', ''); - $iObjectId = utils::ReadParam('iObjectId', ''); - $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); - $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, '', $bSearchMode); - $sName = $oWidget->GetObjectName($iObjectId); - echo json_encode(array('name' => $sName)); - break; - + $oPage->SetContentType('application/json'); + $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); + $iInputId = utils::ReadParam('iInputId', ''); + $iObjectId = utils::ReadParam('iObjectId', ''); + $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); + $oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, '', $bSearchMode); + $sName = $oWidget->GetObjectName($iObjectId); + echo json_encode(array('name' => $sName)); + break; + // ui.extkeywidget case 'displayHierarchy': - $oPage->SetContentType('text/html'); - $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); - $sInputId = utils::ReadParam('sInputId', ''); - $sFilter = utils::ReadParam('sFilter', '', false, 'raw_data'); - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - $currValue = utils::ReadParam('value', ''); - $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); - if (!empty($sJson)) - { - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - } - else - { - // Search form: no current object - $oObj = null; - } - $oWidget = new UIExtKeyWidget($sTargetClass, $sInputId, '', $bSearchMode); - $oWidget->DisplayHierarchy($oPage, $sFilter, $currValue, $oObj); - break; - + $oPage->SetContentType('text/html'); + $sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class'); + $sInputId = utils::ReadParam('sInputId', ''); + $sFilter = utils::ReadParam('sFilter', '', false, 'raw_data'); + $sJson = utils::ReadParam('json', '', false, 'raw_data'); + $currValue = utils::ReadParam('value', ''); + $bSearchMode = (utils::ReadParam('bSearchMode', 'false') == 'true'); + if (!empty($sJson)) + { + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + } + else + { + // Search form: no current object + $oObj = null; + } + $oWidget = new UIExtKeyWidget($sTargetClass, $sInputId, '', $bSearchMode); + $oWidget->DisplayHierarchy($oPage, $sFilter, $currValue, $oObj); + break; + //////////////////////////////////////////////////// - + // ui.linkswidget case 'doAddObjects': - $oPage->SetContentType('text/html'); - $sAttCode = utils::ReadParam('sAttCode', ''); - $iInputId = utils::ReadParam('iInputId', ''); - $sSuffix = utils::ReadParam('sSuffix', ''); - $sRemoteClass = utils::ReadParam('sRemoteClass', $sClass, false, 'class'); - $bDuplicates = (utils::ReadParam('bDuplicates', 'false') == 'false') ? false : true; - $sJson = utils::ReadParam('json', '', false, 'raw_data'); - $iMaxAddedId = utils::ReadParam('max_added_id'); - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - $oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId, $sSuffix, $bDuplicates); - if ($sFilter != '') - { - $oFullSetFilter = DBObjectSearch::unserialize($sFilter); - } - else - { - $oFullSetFilter = new DBObjectSearch($sRemoteClass); - } - $oWidget->DoAddObjects($oPage, $iMaxAddedId, $oFullSetFilter, $oObj); - break; - - //////////////////////////////////////////////////////////// - - case 'wizard_helper_preview': - $oPage->SetContentType('text/html'); - $sJson = utils::ReadParam('json_obj', '', false, 'raw_data'); - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - $oObj->DisplayBareProperties($oPage); - break; - - case 'wizard_helper': - $oPage->SetContentType('text/html'); - $sJson = utils::ReadParam('json_obj', '', false, 'raw_data'); - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - $sClass = $oWizardHelper->GetTargetClass(); - foreach($oWizardHelper->GetFieldsForDefaultValue() as $sAttCode) - { - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - $defaultValue = $oAttDef->GetDefaultValue($oObj); - $oWizardHelper->SetDefaultValue($sAttCode, $defaultValue); - $oObj->Set($sAttCode, $defaultValue); - } - $sFormPrefix = $oWizardHelper->GetFormPrefix(); - $aExpectedAttributes = ($oWizardHelper->GetStimulus() === null) ? array() : $oObj->GetTransitionAttributes($oWizardHelper->GetStimulus(), $oWizardHelper->GetInitialState()); - foreach($oWizardHelper->GetFieldsForAllowedValues() as $sAttCode) - { - $sId = $oWizardHelper->GetIdForField($sAttCode); - if ($sId != '') + $oPage->SetContentType('text/html'); + $sAttCode = utils::ReadParam('sAttCode', ''); + $iInputId = utils::ReadParam('iInputId', ''); + $sSuffix = utils::ReadParam('sSuffix', ''); + $sRemoteClass = utils::ReadParam('sRemoteClass', $sClass, false, 'class'); + $bDuplicates = (utils::ReadParam('bDuplicates', 'false') == 'false') ? false : true; + $sJson = utils::ReadParam('json', '', false, 'raw_data'); + $iMaxAddedId = utils::ReadParam('max_added_id'); + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + $oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId, $sSuffix, $bDuplicates); + if ($sFilter != '') { - if(array_key_exists($sAttCode, $aExpectedAttributes)) - { - $iFlags = $aExpectedAttributes[$sAttCode]; - } - elseif ($oObj->IsNew()) + $oFullSetFilter = DBObjectSearch::unserialize($sFilter); + } + else + { + $oFullSetFilter = new DBObjectSearch($sRemoteClass); + } + $oWidget->DoAddObjects($oPage, $iMaxAddedId, $oFullSetFilter, $oObj); + break; + + //////////////////////////////////////////////////////////// + + case 'wizard_helper_preview': + $oPage->SetContentType('text/html'); + $sJson = utils::ReadParam('json_obj', '', false, 'raw_data'); + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + $oObj->DisplayBareProperties($oPage); + break; + + case 'wizard_helper': + $oPage->SetContentType('text/html'); + $sJson = utils::ReadParam('json_obj', '', false, 'raw_data'); + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + $sClass = $oWizardHelper->GetTargetClass(); + foreach($oWizardHelper->GetFieldsForDefaultValue() as $sAttCode) + { + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + $defaultValue = $oAttDef->GetDefaultValue($oObj); + $oWizardHelper->SetDefaultValue($sAttCode, $defaultValue); + $oObj->Set($sAttCode, $defaultValue); + } + $sFormPrefix = $oWizardHelper->GetFormPrefix(); + $aExpectedAttributes = ($oWizardHelper->GetStimulus() === null) ? array() : $oObj->GetTransitionAttributes($oWizardHelper->GetStimulus(), $oWizardHelper->GetInitialState()); + foreach($oWizardHelper->GetFieldsForAllowedValues() as $sAttCode) + { + $sId = $oWizardHelper->GetIdForField($sAttCode); + if ($sId != '') { - $iFlags = $oObj->GetInitialStateAttributeFlags($sAttCode); - } - else - { - $iFlags = $oObj->GetAttributeFlags($sAttCode); - } - if ($iFlags & OPT_ATT_READONLY) - { - $sHTMLValue = "".$oObj->GetAsHTML($sAttCode); - $oWizardHelper->SetAllowedValuesHtml($sAttCode, $sHTMLValue); - } - else - { - // It may happen that the field we'd like to update does not - // exist in the form. For example, if the field should be hidden/read-only - // in the current state of the object - $value = $oObj->Get($sAttCode); - $displayValue = $oObj->GetEditValue($sAttCode); - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - if (!$oAttDef->IsWritable()) + if (array_key_exists($sAttCode, $aExpectedAttributes)) { - // Even non-writable fields (like AttributeExternal) can be refreshed - $sHTMLValue = $oObj->GetAsHTML($sAttCode); + $iFlags = $aExpectedAttributes[$sAttCode]; + } + elseif ($oObj->IsNew()) + { + $iFlags = $oObj->GetInitialStateAttributeFlags($sAttCode); } else { - $iFlags = MetaModel::GetAttributeFlags($sClass, $oObj->GetState(), $sAttCode); - $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value, $displayValue, $sId, '', $iFlags, array('this' => $oObj, 'formPrefix' => $sFormPrefix), false); - // Make sure that we immediately validate the field when we reload it - $oPage->add_ready_script("$('#$sId').trigger('validate');"); + $iFlags = $oObj->GetAttributeFlags($sAttCode); + } + if ($iFlags & OPT_ATT_READONLY) + { + $sHTMLValue = "".$oObj->GetAsHTML($sAttCode); + $oWizardHelper->SetAllowedValuesHtml($sAttCode, $sHTMLValue); + } + else + { + // It may happen that the field we'd like to update does not + // exist in the form. For example, if the field should be hidden/read-only + // in the current state of the object + $value = $oObj->Get($sAttCode); + $displayValue = $oObj->GetEditValue($sAttCode); + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + if (!$oAttDef->IsWritable()) + { + // Even non-writable fields (like AttributeExternal) can be refreshed + $sHTMLValue = $oObj->GetAsHTML($sAttCode); + } + else + { + $iFlags = MetaModel::GetAttributeFlags($sClass, $oObj->GetState(), $sAttCode); + $sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $value, $displayValue, $sId, '', $iFlags, array('this' => $oObj, 'formPrefix' => $sFormPrefix), false); + // Make sure that we immediately validate the field when we reload it + $oPage->add_ready_script("$('#$sId').trigger('validate');"); + } + $oWizardHelper->SetAllowedValuesHtml($sAttCode, $sHTMLValue); } - $oWizardHelper->SetAllowedValuesHtml($sAttCode, $sHTMLValue); } } - } - $oPage->add_script("oWizardHelper{$sFormPrefix}.m_oData=".$oWizardHelper->ToJSON().";\noWizardHelper{$sFormPrefix}.UpdateFields();\n"); - break; - + $oPage->add_script("oWizardHelper{$sFormPrefix}.m_oData=".$oWizardHelper->ToJSON().";\noWizardHelper{$sFormPrefix}.UpdateFields();\n"); + break; + case 'obj_creation_form': - $oPage->SetContentType('text/html'); - $sJson = utils::ReadParam('json_obj', '', false, 'raw_data'); - $oWizardHelper = WizardHelper::FromJSON($sJson); - $oObj = $oWizardHelper->GetTargetObject(); - $sClass = $oWizardHelper->GetTargetClass(); - $sTargetState = utils::ReadParam('target_state', ''); - $iTransactionId = utils::ReadParam('transaction_id', ''); - $oObj->Set(MetaModel::GetStateAttributeCode($sClass), $sTargetState); - cmdbAbstractObject::DisplayCreationForm($oPage, $sClass, $oObj, array(), array('action' => utils::GetAbsoluteUrlAppRoot().'pages/UI.php', 'transaction_id' => $iTransactionId)); - break; - + $oPage->SetContentType('text/html'); + $sJson = utils::ReadParam('json_obj', '', false, 'raw_data'); + $oWizardHelper = WizardHelper::FromJSON($sJson); + $oObj = $oWizardHelper->GetTargetObject(); + $sClass = $oWizardHelper->GetTargetClass(); + $sTargetState = utils::ReadParam('target_state', ''); + $iTransactionId = utils::ReadParam('transaction_id', ''); + $oObj->Set(MetaModel::GetStateAttributeCode($sClass), $sTargetState); + cmdbAbstractObject::DisplayCreationForm($oPage, $sClass, $oObj, array(), array('action' => utils::GetAbsoluteUrlAppRoot().'pages/UI.php', 'transaction_id' => $iTransactionId)); + break; + // DisplayBlock case 'ajax': - $oPage->SetContentType('text/html'); - if ($sFilter != "") - { - $sExtraParams = stripslashes(utils::ReadParam('extra_params', '', false, 'raw_data')); - $aExtraParams = array(); - if (!empty($sExtraParams)) + $oPage->SetContentType('text/html'); + if ($sFilter != "") { - $aExtraParams = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */); - } - // Restore the app context from the ExtraParams - $oAppContext = new ApplicationContext(false); // false => don't read the context yet ! - $aContext = array(); - foreach($oAppContext->GetNames() as $sName) - { - $sParamName = 'c['.$sName.']'; - if (isset($aExtraParams[$sParamName])) + $sExtraParams = stripslashes(utils::ReadParam('extra_params', '', false, 'raw_data')); + $aExtraParams = array(); + if (!empty($sExtraParams)) { - $aContext[$sName] = $aExtraParams[$sParamName]; + $aExtraParams = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */); } - } - $_REQUEST['c'] = $aContext; - if ($sEncoding == 'oql') - { - $oFilter = DBSearch::FromOQL($sFilter); + // Restore the app context from the ExtraParams + $oAppContext = new ApplicationContext(false); // false => don't read the context yet ! + $aContext = array(); + foreach($oAppContext->GetNames() as $sName) + { + $sParamName = 'c['.$sName.']'; + if (isset($aExtraParams[$sParamName])) + { + $aContext[$sName] = $aExtraParams[$sParamName]; + } + } + $_REQUEST['c'] = $aContext; + if ($sEncoding == 'oql') + { + $oFilter = DBSearch::FromOQL($sFilter); + } + else + { + $oFilter = DBSearch::unserialize($sFilter); + } + $oDisplayBlock = new DisplayBlock($oFilter, $sStyle, false); + $aExtraParams['display_limit'] = true; + $aExtraParams['truncated'] = true; + $oDisplayBlock->RenderContent($oPage, $aExtraParams); } else { - $oFilter = DBSearch::unserialize($sFilter); + $oPage->p("Invalid query (empty filter)."); } - $oDisplayBlock = new DisplayBlock($oFilter, $sStyle, false); - $aExtraParams['display_limit'] = true; - $aExtraParams['truncated'] = true; - $oDisplayBlock->RenderContent($oPage, $aExtraParams); - } - else - { - $oPage->p("Invalid query (empty filter)."); - } - break; - - case 'displayCSVHistory': - $oPage->SetContentType('text/html'); - $bShowAll = (utils::ReadParam('showall', 'false') == 'true'); - BulkChange::DisplayImportHistory($oPage, true, $bShowAll); - break; - - case 'details': - $oPage->SetContentType('text/html'); - $key = utils::ReadParam('id', 0); - $oFilter = new DBObjectSearch($sClass); - $oFilter->AddCondition('id', $key, '='); - $oDisplayBlock = new DisplayBlock($oFilter, 'details', false); - $oDisplayBlock->RenderContent($oPage); - break; - - case 'pie_chart': - $oPage->SetContentType('application/json'); - $sGroupBy = utils::ReadParam('group_by', ''); - if ($sFilter != '') - { - if ($sEncoding == 'oql') - { - $oFilter = DBSearch::FromOQL($sFilter); - } - else - { - $oFilter = DBSearch::unserialize($sFilter); - } - $oDisplayBlock = new DisplayBlock($oFilter, 'pie_chart_ajax', false); - $oDisplayBlock->RenderContent($oPage, array('group_by' => $sGroupBy)); - } - else - { - - $oPage->add("\n3d pie\n."); - } - break; - - case 'chart': - // Workaround for IE8 + IIS + HTTPS - // See TRAC #363, fix described here: http://forums.codecharge.com/posts.php?post_id=97771 - $oPage->add_header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); - $oPage->add_header("Cache-Control: cache, must-revalidate"); - $oPage->add_header("Pragma: public"); + break; + + case 'displayCSVHistory': + $oPage->SetContentType('text/html'); + $bShowAll = (utils::ReadParam('showall', 'false') == 'true'); + BulkChange::DisplayImportHistory($oPage, true, $bShowAll); + break; + + case 'details': + $oPage->SetContentType('text/html'); + $key = utils::ReadParam('id', 0); + $oFilter = new DBObjectSearch($sClass); + $oFilter->AddCondition('id', $key, '='); + $oDisplayBlock = new DisplayBlock($oFilter, 'details', false); + $oDisplayBlock->RenderContent($oPage); + break; + + case 'pie_chart': + $oPage->SetContentType('application/json'); + $sGroupBy = utils::ReadParam('group_by', ''); + if ($sFilter != '') + { + if ($sEncoding == 'oql') + { + $oFilter = DBSearch::FromOQL($sFilter); + } + else + { + $oFilter = DBSearch::unserialize($sFilter); + } + $oDisplayBlock = new DisplayBlock($oFilter, 'pie_chart_ajax', false); + $oDisplayBlock->RenderContent($oPage, array('group_by' => $sGroupBy)); + } + else + { + + $oPage->add("\n3d pie\n."); + } + break; + + case 'chart': + // Workaround for IE8 + IIS + HTTPS + // See TRAC #363, fix described here: http://forums.codecharge.com/posts.php?post_id=97771 + $oPage->add_header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); + $oPage->add_header("Cache-Control: cache, must-revalidate"); + $oPage->add_header("Pragma: public"); + + $aParams = utils::ReadParam('params', array(), false, 'raw_data'); + if ($sFilter != '') + { + $oFilter = DBSearch::unserialize($sFilter); + $oDisplayBlock = new DisplayBlock($oFilter, 'chart_ajax', false); + $oDisplayBlock->RenderContent($oPage, $aParams); + } + else + { + + $oPage->add("\n3d pie\n."); + } + break; - $aParams = utils::ReadParam('params', array(), false, 'raw_data'); - if ($sFilter != '') - { - $oFilter = DBSearch::unserialize($sFilter); - $oDisplayBlock = new DisplayBlock($oFilter, 'chart_ajax', false); - $oDisplayBlock->RenderContent($oPage, $aParams); - } - else - { - - $oPage->add("\n3d pie\n."); - } - break; - case 'modal_details': - $oPage->SetContentType('text/html'); - $key = utils::ReadParam('id', 0); - $oFilter = new DBObjectSearch($sClass); - $oFilter->AddCondition('id', $key, '='); - $oPage->Add("

Object Details

\n"); - $oDisplayBlock = new DisplayBlock($oFilter, 'details', false); - $oDisplayBlock->RenderContent($oPage); - $oPage->Add("\n"); - break; + $oPage->SetContentType('text/html'); + $key = utils::ReadParam('id', 0); + $oFilter = new DBObjectSearch($sClass); + $oFilter->AddCondition('id', $key, '='); + $oPage->Add("

Object Details

\n"); + $oDisplayBlock = new DisplayBlock($oFilter, 'details', false); + $oDisplayBlock->RenderContent($oPage); + $oPage->Add("\n"); + break; case 'link': - $oPage->SetContentType('text/html'); - $sClass = utils::ReadParam('sclass', 'logInfra', false, 'class'); - $sAttCode = utils::ReadParam('attCode', 'name'); - //$sOrg = utils::ReadParam('org_id', ''); - $sName = utils::ReadParam('q', ''); - $iMaxCount = utils::ReadParam('max', 30); - $iCount = 0; - $oFilter = new DBObjectSearch($sClass); - $oFilter->AddCondition($sAttCode, $sName, 'Begins with'); - //$oFilter->AddCondition('org_id', $sOrg, '='); - $oSet = new CMDBObjectSet($oFilter, array($sAttCode => true)); - while( ($iCount < $iMaxCount) && ($oObj = $oSet->fetch()) ) - { - $oPage->add($oObj->GetAsHTML($sAttCode)."|".$oObj->GetKey()."\n"); - $iCount++; - } - break; - + $oPage->SetContentType('text/html'); + $sClass = utils::ReadParam('sclass', 'logInfra', false, 'class'); + $sAttCode = utils::ReadParam('attCode', 'name'); + //$sOrg = utils::ReadParam('org_id', ''); + $sName = utils::ReadParam('q', ''); + $iMaxCount = utils::ReadParam('max', 30); + $iCount = 0; + $oFilter = new DBObjectSearch($sClass); + $oFilter->AddCondition($sAttCode, $sName, 'Begins with'); + //$oFilter->AddCondition('org_id', $sOrg, '='); + $oSet = new CMDBObjectSet($oFilter, array($sAttCode => true)); + while (($iCount < $iMaxCount) && ($oObj = $oSet->fetch())) + { + $oPage->add($oObj->GetAsHTML($sAttCode)."|".$oObj->GetKey()."\n"); + $iCount++; + } + break; + case 'combo_options': - $oPage->SetContentType('text/html'); - $oFilter = DBSearch::FromOQL($sFilter); - $oSet = new CMDBObjectSet($oFilter); - while( $oObj = $oSet->fetch()) - { - $oPage->add(''); - } - break; - + $oPage->SetContentType('text/html'); + $oFilter = DBSearch::FromOQL($sFilter); + $oSet = new CMDBObjectSet($oFilter); + while ($oObj = $oSet->fetch()) + { + $oPage->add(''); + } + break; + case 'display_document': - $id = utils::ReadParam('id', ''); - $sField = utils::ReadParam('field', ''); - if (!empty($sClass) && ($sClass != 'InlineImage') && !empty($id) && !empty($sField)) - { - ormDocument::DownloadDocument($oPage, $sClass, $id, $sField, 'inline'); - } - break; - + $id = utils::ReadParam('id', ''); + $sField = utils::ReadParam('field', ''); + if (!empty($sClass) && ($sClass != 'InlineImage') && !empty($id) && !empty($sField)) + { + ormDocument::DownloadDocument($oPage, $sClass, $id, $sField, 'inline'); + } + break; + case 'search_form': - $oPage->SetContentType('text/html'); - $sClass = utils::ReadParam('className', '', false, 'class'); - $sRootClass = utils::ReadParam('baseClass', '', false, 'class'); - $currentId = utils::ReadParam('currentId', ''); - $sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data'); - $sAction = utils::ReadParam('action', ''); - $oFilter = new DBObjectSearch($sClass); - $oSet = new CMDBObjectSet($oFilter); - $sHtml = cmdbAbstractObject::GetSearchForm($oPage, $oSet, array('currentId' => $currentId, 'baseClass' => $sRootClass, 'action' => $sAction, 'table_id' => $sTableId)); - $oPage->add($sHtml); - break; - + $oPage->SetContentType('text/html'); + $sClass = utils::ReadParam('className', '', false, 'class'); + $sRootClass = utils::ReadParam('baseClass', '', false, 'class'); + $currentId = utils::ReadParam('currentId', ''); + $sTableId = utils::ReadParam('_table_id_', null, false, 'raw_data'); + $sAction = utils::ReadParam('action', ''); + $oFilter = new DBObjectSearch($sClass); + $oSet = new CMDBObjectSet($oFilter); + $sHtml = cmdbAbstractObject::GetSearchForm($oPage, $oSet, array('currentId' => $currentId, 'baseClass' => $sRootClass, 'action' => $sAction, 'table_id' => $sTableId)); + $oPage->add($sHtml); + break; + case 'set_pref': - $sCode = utils::ReadPostedParam('code', ''); - $sValue = utils::ReadPostedParam('value', '', 'raw_data'); - appUserPreferences::SetPref($sCode, $sValue); - break; - + $sCode = utils::ReadPostedParam('code', ''); + $sValue = utils::ReadPostedParam('value', '', 'raw_data'); + appUserPreferences::SetPref($sCode, $sValue); + break; + case 'erase_all_pref': - // Can be useful in case a user got some corrupted prefs... - appUserPreferences::ClearPreferences(); - break; + // Can be useful in case a user got some corrupted prefs... + appUserPreferences::ClearPreferences(); + break; case 'on_form_cancel': - // Called when a creation/modification form is cancelled by the end-user - // Let's take this opportunity to inform the plug-ins so that they can perform some cleanup - $iTransactionId = utils::ReadParam('transaction_id', 0); - $sTempId = session_id().'_'.$iTransactionId; - InlineImage::OnFormCancel($sTempId); - foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) - { - $oExtensionInstance->OnFormCancel($sTempId); - } - $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); - $iObjKey = (int)utils::ReadParam('obj_key', 0, false, 'integer'); - $sToken = utils::ReadParam('token', 0, false, 'raw_data'); - if (($sObjClass != '') && ($iObjKey != 0) && ($sToken != '')) - { - $bReleaseLock = iTopOwnershipLock::ReleaseLock($sObjClass, $iObjKey, $sToken); - } - break; + // Called when a creation/modification form is cancelled by the end-user + // Let's take this opportunity to inform the plug-ins so that they can perform some cleanup + $iTransactionId = utils::ReadParam('transaction_id', 0); + $sTempId = session_id().'_'.$iTransactionId; + InlineImage::OnFormCancel($sTempId); + foreach(MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) + { + $oExtensionInstance->OnFormCancel($sTempId); + } + $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); + $iObjKey = (int)utils::ReadParam('obj_key', 0, false, 'integer'); + $sToken = utils::ReadParam('token', 0, false, 'raw_data'); + if (($sObjClass != '') && ($iObjKey != 0) && ($sToken != '')) + { + $bReleaseLock = iTopOwnershipLock::ReleaseLock($sObjClass, $iObjKey, $sToken); + } + break; case 'reload_dashboard': - $oPage->SetContentType('text/html'); - $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); - $aExtraParams = utils::ReadParam('extra_params', '', false, 'raw_data'); - ApplicationMenu::LoadAdditionalMenus(); - $idx = ApplicationMenu::GetMenuIndexById($sDashboardId); - $oMenu = ApplicationMenu::GetMenuNode($idx); - $oDashboard = $oMenu->GetDashboard(); - $oDashboard->Render($oPage, false, $aExtraParams); - $oPage->add_ready_script("$('.dashboard_contents table.listResults').tableHover(); $('.dashboard_contents table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );"); - break; - + $oPage->SetContentType('text/html'); + $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); + $aExtraParams = utils::ReadParam('extra_params', '', false, 'raw_data'); + ApplicationMenu::LoadAdditionalMenus(); + $idx = ApplicationMenu::GetMenuIndexById($sDashboardId); + $oMenu = ApplicationMenu::GetMenuNode($idx); + $oDashboard = $oMenu->GetDashboard(); + $oDashboard->Render($oPage, false, $aExtraParams); + $oPage->add_ready_script("$('.dashboard_contents table.listResults').tableHover(); $('.dashboard_contents table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );"); + break; + case 'dashboard_editor': - $sId = utils::ReadParam('id', '', false, 'raw_data'); - ApplicationMenu::LoadAdditionalMenus(); - $idx = ApplicationMenu::GetMenuIndexById($sId); - $oMenu = ApplicationMenu::GetMenuNode($idx); - $oMenu->RenderEditor($oPage); - break; - + $sId = utils::ReadParam('id', '', false, 'raw_data'); + ApplicationMenu::LoadAdditionalMenus(); + $idx = ApplicationMenu::GetMenuIndexById($sId); + $oMenu = ApplicationMenu::GetMenuNode($idx); + $oMenu->RenderEditor($oPage); + break; + case 'new_dashlet': - require_once(APPROOT.'application/forms.class.inc.php'); - require_once(APPROOT.'application/dashlet.class.inc.php'); - $sDashletClass = utils::ReadParam('dashlet_class', ''); - $sDashletId = utils::ReadParam('dashlet_id', '', false, 'raw_data'); - if (is_subclass_of($sDashletClass, 'Dashlet')) - { - $oDashlet = new $sDashletClass(new ModelReflectionRuntime(), $sDashletId); - $offset = $oPage->start_capture(); - $oDashlet->DoRender($oPage, true /* bEditMode */, false /* bEnclosingDiv */); - $sHtml = addslashes($oPage->end_capture($offset)); - $sHtml = str_replace("\n", '', $sHtml); - $sHtml = str_replace("\r", '', $sHtml); - $oPage->add_script("$('#dashlet_$sDashletId').html('$sHtml');"); // in ajax web page add_script has the same effect as add_ready_script - // but is executed BEFORE all 'ready_scripts' - $oForm = $oDashlet->GetForm(); // Rebuild the form since the values/content changed - $oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property')); - $sHtml = addslashes($oForm->RenderAsPropertySheet($oPage, true /* bReturnHtml */, '.itop-dashboard')); - $sHtml = str_replace("\n", '', $sHtml); - $sHtml = str_replace("\r", '', $sHtml); - $oPage->add_script("$('#dashlet_properties_$sDashletId').html('$sHtml')"); // in ajax web page add_script has the same effect as add_ready_script // but is executed BEFORE all 'ready_scripts' - } - break; - - case 'update_dashlet_property': - require_once(APPROOT.'application/forms.class.inc.php'); - require_once(APPROOT.'application/dashlet.class.inc.php'); - $aParams = utils::ReadParam('params', '', false, 'raw_data'); - $sDashletClass = $aParams['attr_dashlet_class']; - $sDashletId = $aParams['attr_dashlet_id']; - $aUpdatedProperties = $aParams['updated']; // Code of the changed properties as an array: 'attr_xxx', 'attr_xxy', etc... - $aPreviousValues = $aParams['previous_values']; // hash array: 'attr_xxx' => 'old_value' - if (is_subclass_of($sDashletClass, 'Dashlet')) - { - $oDashlet = new $sDashletClass(new ModelReflectionRuntime(), $sDashletId); - $oForm = $oDashlet->GetForm(); - $aValues = $oForm->ReadParams(); // hash array: 'xxx' => 'new_value' - - $aCurrentValues = $aValues; - $aUpdatedDecoded = array(); - foreach($aUpdatedProperties as $sProp) - { - $sDecodedProp = str_replace('attr_', '', $sProp); // Remove the attr_ prefix - $aCurrentValues[$sDecodedProp] = $aPreviousValues[$sProp]; // Set the previous value - $aUpdatedDecoded[] = $sDecodedProp; - } - - $oDashlet->FromParams($aCurrentValues); - $sPrevClass = get_class($oDashlet); - $oDashlet = $oDashlet->Update($aValues, $aUpdatedDecoded); - $sNewClass = get_class($oDashlet); - if ($sNewClass != $sPrevClass) - { - $oPage->add_ready_script("$('#dashlet_$sDashletId').dashlet('option', {dashlet_class: '$sNewClass'});"); - } - if ($oDashlet->IsRedrawNeeded()) + require_once(APPROOT.'application/forms.class.inc.php'); + require_once(APPROOT.'application/dashlet.class.inc.php'); + $sDashletClass = utils::ReadParam('dashlet_class', ''); + $sDashletId = utils::ReadParam('dashlet_id', '', false, 'raw_data'); + if (is_subclass_of($sDashletClass, 'Dashlet')) { + $oDashlet = new $sDashletClass(new ModelReflectionRuntime(), $sDashletId); $offset = $oPage->start_capture(); $oDashlet->DoRender($oPage, true /* bEditMode */, false /* bEnclosingDiv */); $sHtml = addslashes($oPage->end_capture($offset)); $sHtml = str_replace("\n", '', $sHtml); $sHtml = str_replace("\r", '', $sHtml); - $oPage->add_script("$('#dashlet_$sDashletId').html('$sHtml');"); // in ajax web page add_script has the same effect as add_ready_script - // but is executed BEFORE all 'ready_scripts' - } - if ($oDashlet->IsFormRedrawNeeded()) - { + // but is executed BEFORE all 'ready_scripts' $oForm = $oDashlet->GetForm(); // Rebuild the form since the values/content changed $oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property')); $sHtml = addslashes($oForm->RenderAsPropertySheet($oPage, true /* bReturnHtml */, '.itop-dashboard')); $sHtml = str_replace("\n", '', $sHtml); $sHtml = str_replace("\r", '', $sHtml); $oPage->add_script("$('#dashlet_properties_$sDashletId').html('$sHtml')"); // in ajax web page add_script has the same effect as add_ready_script // but is executed BEFORE all 'ready_scripts' - // but is executed BEFORE all 'ready_scripts' } - } - break; - + break; + + case 'update_dashlet_property': + require_once(APPROOT.'application/forms.class.inc.php'); + require_once(APPROOT.'application/dashlet.class.inc.php'); + $aParams = utils::ReadParam('params', '', false, 'raw_data'); + $sDashletClass = $aParams['attr_dashlet_class']; + $sDashletId = $aParams['attr_dashlet_id']; + $aUpdatedProperties = $aParams['updated']; // Code of the changed properties as an array: 'attr_xxx', 'attr_xxy', etc... + $aPreviousValues = $aParams['previous_values']; // hash array: 'attr_xxx' => 'old_value' + if (is_subclass_of($sDashletClass, 'Dashlet')) + { + $oDashlet = new $sDashletClass(new ModelReflectionRuntime(), $sDashletId); + $oForm = $oDashlet->GetForm(); + $aValues = $oForm->ReadParams(); // hash array: 'xxx' => 'new_value' + + $aCurrentValues = $aValues; + $aUpdatedDecoded = array(); + foreach($aUpdatedProperties as $sProp) + { + $sDecodedProp = str_replace('attr_', '', $sProp); // Remove the attr_ prefix + $aCurrentValues[$sDecodedProp] = $aPreviousValues[$sProp]; // Set the previous value + $aUpdatedDecoded[] = $sDecodedProp; + } + + $oDashlet->FromParams($aCurrentValues); + $sPrevClass = get_class($oDashlet); + $oDashlet = $oDashlet->Update($aValues, $aUpdatedDecoded); + $sNewClass = get_class($oDashlet); + if ($sNewClass != $sPrevClass) + { + $oPage->add_ready_script("$('#dashlet_$sDashletId').dashlet('option', {dashlet_class: '$sNewClass'});"); + } + if ($oDashlet->IsRedrawNeeded()) + { + $offset = $oPage->start_capture(); + $oDashlet->DoRender($oPage, true /* bEditMode */, false /* bEnclosingDiv */); + $sHtml = addslashes($oPage->end_capture($offset)); + $sHtml = str_replace("\n", '', $sHtml); + $sHtml = str_replace("\r", '', $sHtml); + + $oPage->add_script("$('#dashlet_$sDashletId').html('$sHtml');"); // in ajax web page add_script has the same effect as add_ready_script + // but is executed BEFORE all 'ready_scripts' + } + if ($oDashlet->IsFormRedrawNeeded()) + { + $oForm = $oDashlet->GetForm(); // Rebuild the form since the values/content changed + $oForm->SetSubmitParams(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php', array('operation' => 'update_dashlet_property')); + $sHtml = addslashes($oForm->RenderAsPropertySheet($oPage, true /* bReturnHtml */, '.itop-dashboard')); + $sHtml = str_replace("\n", '', $sHtml); + $sHtml = str_replace("\r", '', $sHtml); + $oPage->add_script("$('#dashlet_properties_$sDashletId').html('$sHtml')"); // in ajax web page add_script has the same effect as add_ready_script // but is executed BEFORE all 'ready_scripts' + // but is executed BEFORE all 'ready_scripts' + } + } + break; + case 'save_dashboard': - $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); - $aParams = array(); - $aParams['layout_class'] = utils::ReadParam('layout_class', ''); - $aParams['title'] = utils::ReadParam('title', '', false, 'raw_data'); - $aParams['auto_reload'] = utils::ReadParam('auto_reload', false); - $aParams['auto_reload_sec'] = utils::ReadParam('auto_reload_sec', 300); - $aParams['cells'] = utils::ReadParam('cells', array(), false, 'raw_data'); - $oDashboard = new RuntimeDashboard($sDashboardId); - $oDashboard->FromParams($aParams); - $oDashboard->Save(); - // trigger a reload of the current page since the dashboard just changed - $oPage->add_ready_script( -<<FromParams($aParams); + $oDashboard->Save(); + // trigger a reload of the current page since the dashboard just changed + $oPage->add_ready_script( + <<add_ready_script("sLocation = new String(window.location.href); window.location.href=sLocation.replace('&edit=1', '');"); // reloads the page, doing a GET even if we arrived via a POST - break; + ); + $oPage->add_ready_script("sLocation = new String(window.location.href); window.location.href=sLocation.replace('&edit=1', '');"); // reloads the page, doing a GET even if we arrived via a POST + break; case 'revert_dashboard': - $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); - $oDashboard = new RuntimeDashboard($sDashboardId); - $oDashboard->Revert(); - - // trigger a reload of the current page since the dashboard just changed - $oPage->add_ready_script("window.location.href=window.location.href;"); // reloads the page, doing a GET even if we arrived via a POST - break; - + $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); + $oDashboard = new RuntimeDashboard($sDashboardId); + $oDashboard->Revert(); + + // trigger a reload of the current page since the dashboard just changed + $oPage->add_ready_script("window.location.href=window.location.href;"); // reloads the page, doing a GET even if we arrived via a POST + break; + case 'render_dashboard': - $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); - $aParams = array(); - $aParams['layout_class'] = utils::ReadParam('layout_class', ''); - $aParams['title'] = utils::ReadParam('title', '', false, 'raw_data'); - $aParams['cells'] = utils::ReadParam('cells', array(), false, 'raw_data'); - $aParams['auto_reload'] = utils::ReadParam('auto_reload', false); - $aParams['auto_reload_sec'] = utils::ReadParam('auto_reload_sec', 300); - $oDashboard = new RuntimeDashboard($sDashboardId); - $oDashboard->FromParams($aParams); - $oDashboard->Render($oPage, true /* bEditMode */); - break; - + $sDashboardId = utils::ReadParam('dashboard_id', '', false, 'raw_data'); + $aParams = array(); + $aParams['layout_class'] = utils::ReadParam('layout_class', ''); + $aParams['title'] = utils::ReadParam('title', '', false, 'raw_data'); + $aParams['cells'] = utils::ReadParam('cells', array(), false, 'raw_data'); + $aParams['auto_reload'] = utils::ReadParam('auto_reload', false); + $aParams['auto_reload_sec'] = utils::ReadParam('auto_reload_sec', 300); + $oDashboard = new RuntimeDashboard($sDashboardId); + $oDashboard->FromParams($aParams); + $oDashboard->Render($oPage, true /* bEditMode */); + break; + case 'dashlet_creation_dlg': - $sOQL = utils::ReadParam('oql', '', false, 'raw_data'); - RuntimeDashboard::GetDashletCreationDlgFromOQL($oPage, $sOQL); - break; + $sOQL = utils::ReadParam('oql', '', false, 'raw_data'); + RuntimeDashboard::GetDashletCreationDlgFromOQL($oPage, $sOQL); + break; case 'add_dashlet': - $oForm = RuntimeDashboard::GetDashletCreationForm(); - $aValues = $oForm->ReadParams(); - - $sDashletClass = $aValues['dashlet_class']; - $sMenuId = $aValues['menu_id']; - - if (is_subclass_of($sDashletClass, 'Dashlet')) - { - $oDashlet = new $sDashletClass(new ModelReflectionRuntime(), 0); - $oDashlet->FromParams($aValues); + $oForm = RuntimeDashboard::GetDashletCreationForm(); + $aValues = $oForm->ReadParams(); + $sDashletClass = $aValues['dashlet_class']; + $sMenuId = $aValues['menu_id']; + + if (is_subclass_of($sDashletClass, 'Dashlet')) + { + $oDashlet = new $sDashletClass(new ModelReflectionRuntime(), 0); + $oDashlet->FromParams($aValues); + + ApplicationMenu::LoadAdditionalMenus(); + $index = ApplicationMenu::GetMenuIndexById($sMenuId); + $oMenu = ApplicationMenu::GetMenuNode($index); + $oMenu->AddDashlet($oDashlet); + // navigate to the dashboard page + if ($aValues['open_editor']) + { + $oPage->add_ready_script("window.location.href='".addslashes(utils::GetAbsoluteUrlAppRoot().'pages/UI.php?c[menu]='.urlencode($sMenuId))."&edit=1';"); // reloads the page, doing a GET even if we arrived via a POST + } + } + break; + + case 'shortcut_list_dlg': + $sOQL = utils::ReadParam('oql', '', false, 'raw_data'); + $sTableSettings = utils::ReadParam('table_settings', '', false, 'raw_data'); + ShortcutOQL::GetCreationDlgFromOQL($oPage, $sOQL, $sTableSettings); + break; + + case 'shortcut_list_create': + $oForm = ShortcutOQL::GetCreationForm(); + $aValues = $oForm->ReadParams(); + + $oAppContext = new ApplicationContext(); + $aContext = $oAppContext->GetAsHash(); + $sContext = serialize($aContext); + + $oShortcut = MetaModel::NewObject("ShortcutOQL"); + $oShortcut->Set('user_id', UserRights::GetUserId()); + $oShortcut->Set("context", $sContext); + $oShortcut->Set("name", $aValues['name']); + $oShortcut->Set("oql", $aValues['oql']); + $iAutoReload = (int)$aValues['auto_reload_sec']; + if (($aValues['auto_reload']) && ($iAutoReload > 0)) + { + $oShortcut->Set("auto_reload_sec", max(MetaModel::GetConfig()->Get('min_reload_interval'), $iAutoReload)); + $oShortcut->Set("auto_reload", 'custom'); + } + utils::PushArchiveMode(false); + $iId = $oShortcut->DBInsertNoReload(); + utils::PopArchiveMode(); + + $oShortcut->CloneTableSettings($aValues['table_settings']); + + // Add the menu node in the right place + // + // Mmmm... already done because the newly created menu is read from the DB + // as soon as we invoke DisplayMenu + + // Refresh the menu pane + $aExtraParams = array(); + ApplicationMenu::DisplayMenu($oPage, $aExtraParams); + break; + + case 'shortcut_rename_dlg': + $oSearch = new DBObjectSearch('Shortcut'); + $aShortcuts = utils::ReadMultipleSelection($oSearch); + $iShortcut = $aShortcuts[0]; + $oShortcut = MetaModel::GetObject('Shortcut', $iShortcut); + $oShortcut->StartRenameDialog($oPage); + break; + + case 'shortcut_rename_go': + $iShortcut = utils::ReadParam('id', 0); + $oShortcut = MetaModel::GetObject('Shortcut', $iShortcut); + + $sName = utils::ReadParam('attr_name', '', false, 'raw_data'); + if (strlen($sName) > 0) + { + $oShortcut->Set('name', $sName); + utils::PushArchiveMode(false); + $oShortcut->DBUpdate(); + utils::PopArchiveMode(); + $oPage->add_ready_script('window.location.reload();'); + } + + break; + + case 'shortcut_delete_go': + $oSearch = new DBObjectSearch('Shortcut'); + $oSearch->AddCondition('user_id', UserRights::GetUserId(), '='); + $aShortcuts = utils::ReadMultipleSelection($oSearch); + foreach($aShortcuts as $iShortcut) + { + $oShortcut = MetaModel::GetObject('Shortcut', $iShortcut); + utils::PushArchiveMode(false); + $oShortcut->DBDelete(); + utils::PopArchiveMode(); + $oPage->add_ready_script('window.location.reload();'); + } + break; + + case 'export_dashboard': + $sMenuId = utils::ReadParam('id', '', false, 'raw_data'); ApplicationMenu::LoadAdditionalMenus(); $index = ApplicationMenu::GetMenuIndexById($sMenuId); $oMenu = ApplicationMenu::GetMenuNode($index); - $oMenu->AddDashlet($oDashlet); - // navigate to the dashboard page - if ($aValues['open_editor']) - { - $oPage->add_ready_script("window.location.href='".addslashes(utils::GetAbsoluteUrlAppRoot().'pages/UI.php?c[menu]='.urlencode($sMenuId))."&edit=1';"); // reloads the page, doing a GET even if we arrived via a POST - } - } - break; - - case 'shortcut_list_dlg': - $sOQL = utils::ReadParam('oql', '', false, 'raw_data'); - $sTableSettings = utils::ReadParam('table_settings', '', false, 'raw_data'); - ShortcutOQL::GetCreationDlgFromOQL($oPage, $sOQL, $sTableSettings); - break; - - case 'shortcut_list_create': - $oForm = ShortcutOQL::GetCreationForm(); - $aValues = $oForm->ReadParams(); - - $oAppContext = new ApplicationContext(); - $aContext = $oAppContext->GetAsHash(); - $sContext = serialize($aContext); - - $oShortcut = MetaModel::NewObject("ShortcutOQL"); - $oShortcut->Set('user_id', UserRights::GetUserId()); - $oShortcut->Set("context", $sContext); - $oShortcut->Set("name", $aValues['name']); - $oShortcut->Set("oql", $aValues['oql']); - $iAutoReload = (int)$aValues['auto_reload_sec']; - if (($aValues['auto_reload']) && ($iAutoReload > 0)) - { - $oShortcut->Set("auto_reload_sec", max(MetaModel::GetConfig()->Get('min_reload_interval'), $iAutoReload)); - $oShortcut->Set("auto_reload", 'custom'); - } - utils::PushArchiveMode(false); - $iId = $oShortcut->DBInsertNoReload(); - utils::PopArchiveMode(); - - $oShortcut->CloneTableSettings($aValues['table_settings']); - - // Add the menu node in the right place - // - // Mmmm... already done because the newly created menu is read from the DB - // as soon as we invoke DisplayMenu - - // Refresh the menu pane - $aExtraParams = array(); - ApplicationMenu::DisplayMenu($oPage, $aExtraParams); - break; - - case 'shortcut_rename_dlg': - $oSearch = new DBObjectSearch('Shortcut'); - $aShortcuts = utils::ReadMultipleSelection($oSearch); - $iShortcut = $aShortcuts[0]; - $oShortcut = MetaModel::GetObject('Shortcut', $iShortcut); - $oShortcut->StartRenameDialog($oPage); - break; - - case 'shortcut_rename_go': - $iShortcut = utils::ReadParam('id', 0); - $oShortcut = MetaModel::GetObject('Shortcut', $iShortcut); - - $sName = utils::ReadParam('attr_name', '', false, 'raw_data'); - if (strlen($sName) > 0) - { - $oShortcut->Set('name', $sName); - utils::PushArchiveMode(false); - $oShortcut->DBUpdate(); - utils::PopArchiveMode(); - $oPage->add_ready_script('window.location.reload();'); - } - - break; - - case 'shortcut_delete_go': - $oSearch = new DBObjectSearch('Shortcut'); - $oSearch->AddCondition('user_id', UserRights::GetUserId(), '='); - $aShortcuts = utils::ReadMultipleSelection($oSearch); - foreach ($aShortcuts as $iShortcut) - { - $oShortcut = MetaModel::GetObject('Shortcut', $iShortcut); - utils::PushArchiveMode(false); - $oShortcut->DBDelete(); - utils::PopArchiveMode(); - $oPage->add_ready_script('window.location.reload();'); - } - break; - - case 'export_dashboard': - $sMenuId = utils::ReadParam('id', '', false, 'raw_data'); - ApplicationMenu::LoadAdditionalMenus(); - $index = ApplicationMenu::GetMenuIndexById($sMenuId); - $oMenu = ApplicationMenu::GetMenuNode($index); - if ($oMenu instanceof DashboardMenuNode) - { - $oDashboard = $oMenu->GetDashboard(); - - $oPage->TrashUnexpectedOutput(); - $oPage->SetContentType('text/xml'); - $oPage->SetContentDisposition('attachment', $oMenu->GetLabel().'.xml'); - $oPage->add($oDashboard->ToXml()); - } - break; - - case 'import_dashboard': - $sMenuId = utils::ReadParam('id', '', false, 'raw_data'); - ApplicationMenu::LoadAdditionalMenus(); - $index = ApplicationMenu::GetMenuIndexById($sMenuId); - $oMenu = ApplicationMenu::GetMenuNode($index); - $aResult = array('error' => ''); - try - { if ($oMenu instanceof DashboardMenuNode) { - $oDoc = utils::ReadPostedDocument('dashboard_upload_file'); $oDashboard = $oMenu->GetDashboard(); - $oDashboard->FromXml($oDoc->GetData()); - $oDashboard->Save(); - } - else - { - $aResult['error'] = 'Dashboard id="'.$sMenuId.'" not found.'; - } - } - catch(DOMException $e) - { - $aResult = array('error' => Dict::S('UI:Error:InvalidDashboardFile')); - } - catch(Exception $e) - { - $aResult = array('error' => $e->getMessage()); - } - $oPage->add(json_encode($aResult)); - break; - - case 'about_box': - $oPage->SetContentType('text/html'); - $sDialogTitle = addslashes(Dict::S('UI:About:Title')); - $oPage->add_ready_script( -<<TrashUnexpectedOutput(); + $oPage->SetContentType('text/xml'); + $oPage->SetContentDisposition('attachment', $oMenu->GetLabel().'.xml'); + $oPage->add($oDashboard->ToXml()); + } + break; + + case 'import_dashboard': + $sMenuId = utils::ReadParam('id', '', false, 'raw_data'); + ApplicationMenu::LoadAdditionalMenus(); + $index = ApplicationMenu::GetMenuIndexById($sMenuId); + $oMenu = ApplicationMenu::GetMenuNode($index); + $aResult = array('error' => ''); + try + { + if ($oMenu instanceof DashboardMenuNode) + { + $oDoc = utils::ReadPostedDocument('dashboard_upload_file'); + $oDashboard = $oMenu->GetDashboard(); + $oDashboard->FromXml($oDoc->GetData()); + $oDashboard->Save(); + } + else + { + $aResult['error'] = 'Dashboard id="'.$sMenuId.'" not found.'; + } + } catch (DOMException $e) + { + $aResult = array('error' => Dict::S('UI:Error:InvalidDashboardFile')); + } catch (Exception $e) + { + $aResult = array('error' => $e->getMessage()); + } + $oPage->add(json_encode($aResult)); + break; + + case 'about_box': + $oPage->SetContentType('text/html'); + + $sDialogTitle = addslashes(Dict::S('UI:About:Title')); + $oPage->add_ready_script( + << false)); // Most recent first - $oLastInstall = $oSet->Fetch(); - $sLastInstallDate = $oLastInstall->Get('installed'); - $sDataModelVersion = $oLastInstall->Get('version'); - $aDataModelInfo = json_decode($oLastInstall->Get('comment'), true); - $sDataModelSourceDir = $aDataModelInfo['source_dir']; + // Get the datamodel directory + $oFilter = DBObjectSearch::FromOQL('SELECT ModuleInstallation WHERE name="datamodel"'); + $oSet = new DBObjectSet($oFilter, array('installed' => false)); // Most recent first + $oLastInstall = $oSet->Fetch(); + $sLastInstallDate = $oLastInstall->Get('installed'); + $sDataModelVersion = $oLastInstall->Get('version'); + $aDataModelInfo = json_decode($oLastInstall->Get('comment'), true); + $sDataModelSourceDir = $aDataModelInfo['source_dir']; - require_once(APPROOT.'setup/runtimeenv.class.inc.php'); - $sCurrEnv = utils::GetCurrentEnvironment(); - $oRuntimeEnv = new RunTimeEnvironment($sCurrEnv); - $aSearchDirs = array(APPROOT.$sDataModelSourceDir); - if (file_exists(APPROOT.'extensions')) - { - $aSearchDirs[] = APPROOT.'extensions'; - } - $sExtraDir = APPROOT.'data/'.$sCurrEnv.'-modules/'; - if (file_exists($sExtraDir)) - { - $aSearchDirs[] = $sExtraDir; - } - $aAvailableModules = $oRuntimeEnv->AnalyzeInstallation(MetaModel::GetConfig(), $aSearchDirs); - - require_once(APPROOT.'setup/setuputils.class.inc.php'); - $aLicenses = SetupUtils::GetLicenses($sCurrEnv); - - $aItopSettings = array('cron_max_execution_time', 'timezone'); - $aPHPSettings = array('memory_limit', 'max_execution_time', 'upload_max_filesize', 'post_max_size'); - $aMySQLSettings = array('max_allowed_packet', 'key_buffer_size', 'query_cache_size'); - $aMySQLStatuses = array('Key_read_requests', 'Key_reads'); - - if (extension_loaded('suhosin')) - { - $aPHPSettings[] = 'suhosin.post.max_vars'; - $aPHPSettings[] = 'suhosin.get.max_value_length'; - } - - $aMySQLVars = array(); - foreach (CMDBSource::QueryToArray('SHOW VARIABLES') as $aRow) - { - $aMySQLVars[$aRow['Variable_name']] = $aRow['Value']; - } - - $aMySQLStats = array(); - foreach (CMDBSource::QueryToArray('SHOW GLOBAL STATUS') as $aRow) - { - $aMySQLStats[$aRow['Variable_name']] = $aRow['Value']; - } - - // Display - // - $oPage->add("
"); - $oPage->add('
'); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add(''); - $oPage->add('
'); - $oPage->add($sVersionString.'
'); - $oPage->add(Dict::S('UI:About:DataModel').': '.$sDataModelVersion.'
'); - $oPage->add('MySQL: '.$sMySQLVersion.'
'); - $oPage->add('PHP: '.$sPHPVersion.'
'); - $oPage->add('
'); - $oPage->add("
"); - - $oPage->add("
"); - $oPage->add('
'); - $oPage->add(''.Dict::S('UI:About:Licenses').''); - $oPage->add('
    '); - $index = 0; - foreach($aLicenses as $oLicense) - { - $oPage->add('
  • '.$oLicense->product.', © '.$oLicense->author.' is licensed under the '.$oLicense->license_type.' license. (Details)'); - $oPage->add(''); - $oPage->add_ready_script('$("#toggle_'.$index.'").click( function() { $("#license_'.$index.'").slideToggle("normal"); } );'); - $index++; - } - $oPage->add('
'); - $oPage->add('
'); - $oPage->add("
"); - - $oPage->add('
'); - $oPage->add(''.Dict::S('UI:About:InstallationOptions').''); - $oPage->add("
"); - $oPage->add('
    '); - - require_once(APPROOT.'setup/extensionsmap.class.inc.php'); - $oExtensionsMap = new iTopExtensionsMap(); - $oExtensionsMap->LoadChoicesFromDatabase(MetaModel::GetConfig()); - $aChoices = $oExtensionsMap->GetChoices(); - foreach ($aChoices as $oExtension) - { - switch($oExtension->sSource) + require_once(APPROOT.'setup/runtimeenv.class.inc.php'); + $sCurrEnv = utils::GetCurrentEnvironment(); + $oRuntimeEnv = new RunTimeEnvironment($sCurrEnv); + $aSearchDirs = array(APPROOT.$sDataModelSourceDir); + if (file_exists(APPROOT.'extensions')) { - case iTopExtension::SOURCE_REMOTE: - $sSource = ' '.Dict::S('UI:About:RemoteExtensionSource').''; - break; - - case iTopExtension::SOURCE_MANUAL: - $sSource = ' '.Dict::S('UI:About:ManualExtensionSource').''; - break; - - default: - $sSource = ''; + $aSearchDirs[] = APPROOT.'extensions'; } - $oPage->add('
  • '.$oExtension->sLabel.$sSource.'
  • '); - } - $oPage->add('
'); - $oPage->add("
"); - $oPage->add('
'); - - - // MUST NOT be localized, as the information given here will be sent to the support - $oPage->add("".Dict::S('UI:About:Support')."
\n"); - $oPage->add("
"); - $oPage->add(''); - $oPage->add("
"); + require_once(APPROOT.'setup/setuputils.class.inc.php'); + $aLicenses = SetupUtils::GetLicenses($sCurrEnv); + + $aItopSettings = array('cron_max_execution_time', 'timezone'); + $aPHPSettings = array('memory_limit', 'max_execution_time', 'upload_max_filesize', 'post_max_size'); + $aMySQLSettings = array('max_allowed_packet', 'key_buffer_size', 'query_cache_size'); + $aMySQLStatuses = array('Key_read_requests', 'Key_reads'); + + if (extension_loaded('suhosin')) + { + $aPHPSettings[] = 'suhosin.post.max_vars'; + $aPHPSettings[] = 'suhosin.get.max_value_length'; + } + + $aMySQLVars = array(); + foreach(CMDBSource::QueryToArray('SHOW VARIABLES') as $aRow) + { + $aMySQLVars[$aRow['Variable_name']] = $aRow['Value']; + } + + $aMySQLStats = array(); + foreach(CMDBSource::QueryToArray('SHOW GLOBAL STATUS') as $aRow) + { + $aMySQLStats[$aRow['Variable_name']] = $aRow['Value']; + } + + // Display + // + $oPage->add("
"); + $oPage->add('
'); + $oPage->add(''); + $oPage->add(''); + $oPage->add(''); + $oPage->add(''); + $oPage->add(''); + $oPage->add('
'); + $oPage->add($sVersionString.'
'); + $oPage->add(Dict::S('UI:About:DataModel').': '.$sDataModelVersion.'
'); + $oPage->add('MySQL: '.$sMySQLVersion.'
'); + $oPage->add('PHP: '.$sPHPVersion.'
'); + $oPage->add('
'); + $oPage->add("
"); + + $oPage->add("
"); + $oPage->add('
'); + $oPage->add(''.Dict::S('UI:About:Licenses').''); + $oPage->add('
    '); + $index = 0; + foreach($aLicenses as $oLicense) + { + $oPage->add('
  • '.$oLicense->product.', © '.$oLicense->author.' is licensed under the '.$oLicense->license_type.' license. (Details)'); + $oPage->add(''); + $oPage->add_ready_script('$("#toggle_'.$index.'").click( function() { $("#license_'.$index.'").slideToggle("normal"); } );'); + $index++; + } + $oPage->add('
'); + $oPage->add('
'); + $oPage->add("
"); + + $oPage->add('
'); + $oPage->add(''.Dict::S('UI:About:InstallationOptions').''); + $oPage->add("
"); + $oPage->add('
    '); + + require_once(APPROOT.'setup/extensionsmap.class.inc.php'); + $oExtensionsMap = new iTopExtensionsMap(); + $oExtensionsMap->LoadChoicesFromDatabase(MetaModel::GetConfig()); + $aChoices = $oExtensionsMap->GetChoices(); + foreach($aChoices as $oExtension) + { + switch ($oExtension->sSource) + { + case iTopExtension::SOURCE_REMOTE: + $sSource = ' '.Dict::S('UI:About:RemoteExtensionSource').''; + break; + + case iTopExtension::SOURCE_MANUAL: + $sSource = ' '.Dict::S('UI:About:ManualExtensionSource').''; + break; + + default: + $sSource = ''; + } + $oPage->add('
  • '.$oExtension->sLabel.$sSource.'
  • '); + } + $oPage->add('
'); + $oPage->add("
"); + $oPage->add('
'); + + + // MUST NOT be localized, as the information given here will be sent to the support + $oPage->add("".Dict::S('UI:About:Support')."
\n"); + $oPage->add("
"); + $oPage->add(''); + $oPage->add("
"); + + $oPage->add("
"); + break; - $oPage->add("
"); - break; - case 'history': - $oPage->SetContentType('text/html'); - $id = (int)utils::ReadParam('id', 0); - $iStart = (int)utils::ReadParam('start', 0); - $iCount = (int)utils::ReadParam('count', MetaModel::GetConfig()->Get('max_history_length', '50')); - $oObj = MetaModel::GetObject($sClass, $id); - $oObj->DisplayBareHistory($oPage, false, $iCount, $iStart); - $oPage->add_ready_script("$('#history table.listResults').tableHover(); $('#history table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );"); - break; + $oPage->SetContentType('text/html'); + $id = (int)utils::ReadParam('id', 0); + $iStart = (int)utils::ReadParam('start', 0); + $iCount = (int)utils::ReadParam('count', MetaModel::GetConfig()->Get('max_history_length', '50')); + $oObj = MetaModel::GetObject($sClass, $id); + $oObj->DisplayBareHistory($oPage, false, $iCount, $iStart); + $oPage->add_ready_script("$('#history table.listResults').tableHover(); $('#history table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );"); + break; case 'history_from_filter': - $oPage->SetContentType('text/html'); - $oHistoryFilter = DBSearch::unserialize($sFilter); - $iStart = (int)utils::ReadParam('start', 0); - $iCount = (int)utils::ReadParam('count', MetaModel::GetConfig()->Get('max_history_length', '50')); - $oBlock = new HistoryBlock($oHistoryFilter, 'table', false); - $oBlock->SetLimit($iCount, $iStart); - $oBlock->Display($oPage, 'history'); - $oPage->add_ready_script("$('#history table.listResults').tableHover(); $('#history table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );"); - break; + $oPage->SetContentType('text/html'); + $oHistoryFilter = DBSearch::unserialize($sFilter); + $iStart = (int)utils::ReadParam('start', 0); + $iCount = (int)utils::ReadParam('count', MetaModel::GetConfig()->Get('max_history_length', '50')); + $oBlock = new HistoryBlock($oHistoryFilter, 'table', false); + $oBlock->SetLimit($iCount, $iStart); + $oBlock->Display($oPage, 'history'); + $oPage->add_ready_script("$('#history table.listResults').tableHover(); $('#history table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );"); + break; case 'full_text_search': - $aFullTextNeedles = utils::ReadParam('needles', array(), false, 'raw_data'); - $sFullText = trim(implode(' ', $aFullTextNeedles)); - $sClassName = utils::ReadParam('class', ''); - $iCount = utils::ReadParam('count', 0); - $iCurrentPos = utils::ReadParam('position', 0); - $iTune = utils::ReadParam('tune', 0); - if (empty($sFullText)) - { - $oPage->p(Dict::S('UI:Search:NoSearch')); - break; - } - - // Search in full text mode in all the classes - $aMatches = array(); - - // Build the ordered list of classes to search into - // - if (empty($sClassName)) - { - $aSearchClasses = MetaModel::GetClasses('searchable'); - } - else - { - // Search is limited to a given class and its subclasses - $aSearchClasses = MetaModel::EnumChildClasses($sClassName, ENUM_CHILD_CLASSES_ALL); - } - // Skip abstract classes, since we search in all the child classes anyway - foreach($aSearchClasses as $idx => $sClass) - { - if (MetaModel::IsAbstract($sClass)) + $aFullTextNeedles = utils::ReadParam('needles', array(), false, 'raw_data'); + $sFullText = trim(implode(' ', $aFullTextNeedles)); + $sClassName = utils::ReadParam('class', ''); + $iCount = utils::ReadParam('count', 0); + $iCurrentPos = utils::ReadParam('position', 0); + $iTune = utils::ReadParam('tune', 0); + if (empty($sFullText)) { - unset($aSearchClasses[$idx]); + $oPage->p(Dict::S('UI:Search:NoSearch')); + break; } - } - $sMaxChunkDuration = MetaModel::GetConfig()->Get('full_text_chunk_duration'); - $aAccelerators = MetaModel::GetConfig()->Get('full_text_accelerators'); + // Search in full text mode in all the classes + $aMatches = array(); - foreach (array_reverse($aAccelerators) as $sClass => $aRestriction) - { - $bSkip = false; - $iPos = array_search($sClass, $aSearchClasses); - if ($iPos !== false) + // Build the ordered list of classes to search into + // + if (empty($sClassName)) { - unset($aSearchClasses[$iPos]); + $aSearchClasses = MetaModel::GetClasses('searchable'); } else { - $bSkip = true; + // Search is limited to a given class and its subclasses + $aSearchClasses = MetaModel::EnumChildClasses($sClassName, ENUM_CHILD_CLASSES_ALL); } - $bSkip |= array_key_exists('skip', $aRestriction) ? $aRestriction['skip'] : false ; - if (!in_array($sClass, $aSearchClasses)) - if ($sClass == $sClassName) + // Skip abstract classes, since we search in all the child classes anyway + foreach($aSearchClasses as $idx => $sClass) { - // Class explicitely requested, do NOT skip it - // beware: there may not be a 'query' defined for a skipped class ! - $bSkip = false; - } - if (!$bSkip) - { - // NOT skipped, add the class to the list of classes to search into - if (array_key_exists('query', $aRestriction)) + if (MetaModel::IsAbstract($sClass)) { - array_unshift($aSearchClasses, $aRestriction['query']); + unset($aSearchClasses[$idx]); + } + } + + $sMaxChunkDuration = MetaModel::GetConfig()->Get('full_text_chunk_duration'); + $aAccelerators = MetaModel::GetConfig()->Get('full_text_accelerators'); + + foreach(array_reverse($aAccelerators) as $sClass => $aRestriction) + { + $bSkip = false; + $iPos = array_search($sClass, $aSearchClasses); + if ($iPos !== false) + { + unset($aSearchClasses[$iPos]); } else { - // No accelerator query - array_unshift($aSearchClasses, $sClassName); + $bSkip = true; } - } - } - - $aSearchClasses = array_values($aSearchClasses); // renumbers the array starting from zero, removing the missing indexes - $fStarted = microtime(true); - $iFoundInThisRound = 0; - for($iPos = $iCurrentPos; $iPos < count($aSearchClasses) ; $iPos++) - { - if ($iFoundInThisRound && (microtime(true) - $fStarted >= $sMaxChunkDuration)) - { - break; - } - - $sClassSpec = $aSearchClasses[$iPos]; - if (substr($sClassSpec, 0, 7) == 'SELECT ') - { - $oFilter = DBObjectSearch::FromOQL($sClassSpec); - $sClassName = $oFilter->GetClass(); - $sNeedleFormat = isset($aAccelerators[$sClassName]['needle']) ? $aAccelerators[$sClassName]['needle'] : '%$needle$%'; - $sNeedle = str_replace('$needle$', $sFullText, $sNeedleFormat); - $aParams = array('needle' => $sNeedle); - } - else - { - $sClassName = $sClassSpec; - $oFilter = new DBObjectSearch($sClassName); - $aParams = array(); - - foreach($aFullTextNeedles as $sSearchText) + $bSkip |= array_key_exists('skip', $aRestriction) ? $aRestriction['skip'] : false; + if (!in_array($sClass, $aSearchClasses)) { - $oFilter->AddCondition_FullText($sSearchText); + if ($sClass == $sClassName) + { + // Class explicitely requested, do NOT skip it + // beware: there may not be a 'query' defined for a skipped class ! + $bSkip = false; + } + } + if (!$bSkip) + { + // NOT skipped, add the class to the list of classes to search into + if (array_key_exists('query', $aRestriction)) + { + array_unshift($aSearchClasses, $aRestriction['query']); + } + else + { + // No accelerator query + array_unshift($aSearchClasses, $sClassName); + } } } - $oFilter->SetShowObsoleteData(utils::ShowObsoleteData()); - // Skip abstract classes - if (MetaModel::IsAbstract($sClassName)) continue; - if ($iTune > 0) + $aSearchClasses = array_values($aSearchClasses); // renumbers the array starting from zero, removing the missing indexes + $fStarted = microtime(true); + $iFoundInThisRound = 0; + for($iPos = $iCurrentPos; $iPos < count($aSearchClasses); $iPos++) { - $fStartedClass = microtime(true); - } - $oSet = new DBObjectSet($oFilter, array(), $aParams); - if (array_key_exists($sClassName, $aAccelerators) && array_key_exists('attributes', $aAccelerators[$sClassName])) - { - $oSet->OptimizeColumnLoad(array($oFilter->GetClassAlias() => $aAccelerators[$sClassName]['attributes'])); - } + if ($iFoundInThisRound && (microtime(true) - $fStarted >= $sMaxChunkDuration)) + { + break; + } - $sFullTextJS = addslashes($sFullText); - $bEnableEnlarge = array_key_exists($sClassName, $aAccelerators) && array_key_exists('query', $aAccelerators[$sClassName]); - if (array_key_exists($sClassName, $aAccelerators) && array_key_exists('enable_enlarge', $aAccelerators[$sClassName])) - { - $bEnableEnlarge &= $aAccelerators[$sClassName]['enable_enlarge']; - } - $sEnlargeTheSearch = -<<GetClass(); + $sNeedleFormat = isset($aAccelerators[$sClassName]['needle']) ? $aAccelerators[$sClassName]['needle'] : '%$needle$%'; + $sNeedle = str_replace('$needle$', $sFullText, $sNeedleFormat); + $aParams = array('needle' => $sNeedle); + } + else + { + $sClassName = $sClassSpec; + $oFilter = new DBObjectSearch($sClassName); + $aParams = array(); + + foreach($aFullTextNeedles as $sSearchText) + { + $oFilter->AddCondition_FullText($sSearchText); + } + } + $oFilter->SetShowObsoleteData(utils::ShowObsoleteData()); + // Skip abstract classes + if (MetaModel::IsAbstract($sClassName)) continue; + + if ($iTune > 0) + { + $fStartedClass = microtime(true); + } + $oSet = new DBObjectSet($oFilter, array(), $aParams); + if (array_key_exists($sClassName, $aAccelerators) && array_key_exists('attributes', $aAccelerators[$sClassName])) + { + $oSet->OptimizeColumnLoad(array($oFilter->GetClassAlias() => $aAccelerators[$sClassName]['attributes'])); + } + + $sFullTextJS = addslashes($sFullText); + $bEnableEnlarge = array_key_exists($sClassName, $aAccelerators) && array_key_exists('query', $aAccelerators[$sClassName]); + if (array_key_exists($sClassName, $aAccelerators) && array_key_exists('enable_enlarge', $aAccelerators[$sClassName])) + { + $bEnableEnlarge &= $aAccelerators[$sClassName]['enable_enlarge']; + } + $sEnlargeTheSearch = + <<'); @@ -1501,92 +1502,94 @@ EOF $.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', oParams, function(data) { $('.search-class-$sClassName').html(data); }); -EOF - ; +EOF; - - $sEnlargeButton = ''; - if ($bEnableEnlarge) - { - $sEnlargeButton = " "; - } - if ($oSet->Count() > 0) - { - $aLeafs = array(); - while($oObj = $oSet->Fetch()) + + $sEnlargeButton = ''; + if ($bEnableEnlarge) { - if (get_class($oObj) == $sClassName) + $sEnlargeButton = " "; + } + if ($oSet->Count() > 0) + { + $aLeafs = array(); + while ($oObj = $oSet->Fetch()) { - $aLeafs[] = $oObj->GetKey(); - $iFoundInThisRound ++; + if (get_class($oObj) == $sClassName) + { + $aLeafs[] = $oObj->GetKey(); + $iFoundInThisRound++; + } + } + $oLeafsFilter = new DBObjectSearch($sClassName); + if (count($aLeafs) > 0) + { + $iCount += count($aLeafs); + $oPage->add("
\n"); + $oPage->add("
\n"); + if (array_key_exists($sClassName, $aAccelerators)) + { + $oPage->add("

".MetaModel::GetClassIcon($sClassName)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aLeafs), Metamodel::GetName($sClassName)).$sEnlargeButton."

\n"); + } + else + { + $oPage->add("

".MetaModel::GetClassIcon($sClassName)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aLeafs), Metamodel::GetName($sClassName))."

\n"); + } + $oPage->add("
\n"); + $oLeafsFilter->AddCondition('id', $aLeafs, 'IN'); + $oBlock = new DisplayBlock($oLeafsFilter, 'list', false); + $sBlockId = 'global_search_'.$sClassName; + $oPage->add('
'); + $oBlock->RenderContent($oPage, array('table_id' => $sBlockId, 'currentId' => $sBlockId)); + $oPage->add("
\n"); + $oPage->add("
\n"); + $oPage->p(' '); // Some space ? } } - $oLeafsFilter = new DBObjectSearch($sClassName); - if (count($aLeafs) > 0) + else { - $iCount += count($aLeafs); - $oPage->add("
\n"); - $oPage->add("
\n"); if (array_key_exists($sClassName, $aAccelerators)) { - $oPage->add("

".MetaModel::GetClassIcon($sClassName)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aLeafs), Metamodel::GetName($sClassName)).$sEnlargeButton."

\n"); + $oPage->add("
\n"); + $oPage->add("
\n"); + $oPage->add("

".MetaModel::GetClassIcon($sClassName)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', 0, Metamodel::GetName($sClassName)).$sEnlargeButton."

\n"); + $oPage->add("
\n"); + $oPage->add("
\n"); + $oPage->p(' '); // Some space ? } - else - { - $oPage->add("

".MetaModel::GetClassIcon($sClassName)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aLeafs), Metamodel::GetName($sClassName))."

\n"); - } - $oPage->add("
\n"); - $oLeafsFilter->AddCondition('id', $aLeafs, 'IN'); - $oBlock = new DisplayBlock($oLeafsFilter, 'list', false); - $sBlockId = 'global_search_'.$sClassName; - $oPage->add('
'); - $oBlock->RenderContent($oPage, array('table_id' => $sBlockId, 'currentId' => $sBlockId)); - $oPage->add("
\n"); - $oPage->add("
\n"); - $oPage->p(' '); // Some space ? + } + if ($iTune > 0) + { + $fDurationClass = microtime(true) - $fStartedClass; + $oPage->add_script("oTimeStatistics.$sClassName = $fDurationClass;"); } } - else if (array_key_exists($sClassName, $aAccelerators)) + if ($iPos < count($aSearchClasses)) { - $oPage->add("
\n"); - $oPage->add("
\n"); - $oPage->add("

".MetaModel::GetClassIcon($sClassName)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', 0, Metamodel::GetName($sClassName)).$sEnlargeButton."

\n"); - $oPage->add("
\n"); - $oPage->add("
\n"); - $oPage->p(' '); // Some space ? - } - if ($iTune > 0) - { - $fDurationClass = microtime(true) - $fStartedClass; - $oPage->add_script("oTimeStatistics.$sClassName = $fDurationClass;"); - } - } - if ($iPos < count($aSearchClasses)) - { - $sJSNeedle = json_encode($aFullTextNeedles); - $oPage->add_ready_script( -<<add_ready_script( + <<add_ready_script( -<<add_ready_script( + << 0) - { - $oPage->add_ready_script( -<< 0) + { + $oPage->add_ready_script( + <<add_ready_script("$('#full_text_results').append('
$sFullTextSummary
');"); - } - } - break; - - case 'full_text_search_enlarge': - $sFullText = trim(utils::ReadParam('text', '', false, 'raw_data')); - $sClass = trim(utils::ReadParam('class', '')); - $iTune = utils::ReadParam('tune', 0); - - if (preg_match('/^"(.*)"$/', $sFullText, $aMatches)) - { - // The text is surrounded by double-quotes, remove the quotes and treat it as one single expression - $aFullTextNeedles = array($aMatches[1]); - } - else - { - // Split the text on the blanks and treat this as a search for AND AND - $aFullTextNeedles = explode(' ', $sFullText); - } - - $oFilter = new DBObjectSearch($sClass); - foreach($aFullTextNeedles as $sSearchText) - { - $oFilter->AddCondition_FullText($sSearchText); - } - $oFilter->SetShowObsoleteData(utils::ShowObsoleteData()); - $oSet = new DBObjectSet($oFilter); - $oPage->add("
\n"); - $oPage->add("

".MetaModel::GetClassIcon($sClass)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(), Metamodel::GetName($sClass))."

\n"); - $oPage->add("
\n"); - if ($oSet->Count() > 0) - { - $aLeafs = array(); - while($oObj = $oSet->Fetch()) - { - if (get_class($oObj) == $sClass) + if ($iCount == 0) { - $aLeafs[] = $oObj->GetKey(); + $sFullTextSummary = addslashes(Dict::S('UI:Search:NoObjectFound')); + $oPage->add_ready_script("$('#full_text_results').append('
$sFullTextSummary
');"); } } - $oLeafsFilter = new DBObjectSearch($sClass); - if (count($aLeafs) > 0) + break; + + case 'full_text_search_enlarge': + $sFullText = trim(utils::ReadParam('text', '', false, 'raw_data')); + $sClass = trim(utils::ReadParam('class', '')); + $iTune = utils::ReadParam('tune', 0); + + if (preg_match('/^"(.*)"$/', $sFullText, $aMatches)) { - $oLeafsFilter->AddCondition('id', $aLeafs, 'IN'); - $oBlock = new DisplayBlock($oLeafsFilter, 'list', false); - $sBlockId = 'global_search_'.$sClass; - $oPage->add('
'); - $oBlock->RenderContent($oPage, array('table_id' => $sBlockId, 'currentId' => $sBlockId)); - $oPage->add('
'); - $oPage->P(' '); // Some space ? - // Hide "no object found" - $oPage->add_ready_script('$("#no_object_found").hide();'); + // The text is surrounded by double-quotes, remove the quotes and treat it as one single expression + $aFullTextNeedles = array($aMatches[1]); } - } - $oPage->add_ready_script( -<< AND AND + $aFullTextNeedles = explode(' ', $sFullText); + } + + $oFilter = new DBObjectSearch($sClass); + foreach($aFullTextNeedles as $sSearchText) + { + $oFilter->AddCondition_FullText($sSearchText); + } + $oFilter->SetShowObsoleteData(utils::ShowObsoleteData()); + $oSet = new DBObjectSet($oFilter); + $oPage->add("
\n"); + $oPage->add("

".MetaModel::GetClassIcon($sClass)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(), Metamodel::GetName($sClass))."

\n"); + $oPage->add("
\n"); + if ($oSet->Count() > 0) + { + $aLeafs = array(); + while ($oObj = $oSet->Fetch()) + { + if (get_class($oObj) == $sClass) + { + $aLeafs[] = $oObj->GetKey(); + } + } + $oLeafsFilter = new DBObjectSearch($sClass); + if (count($aLeafs) > 0) + { + $oLeafsFilter->AddCondition('id', $aLeafs, 'IN'); + $oBlock = new DisplayBlock($oLeafsFilter, 'list', false); + $sBlockId = 'global_search_'.$sClass; + $oPage->add('
'); + $oBlock->RenderContent($oPage, array('table_id' => $sBlockId, 'currentId' => $sBlockId)); + $oPage->add('
'); + $oPage->P(' '); // Some space ? + // Hide "no object found" + $oPage->add_ready_script('$("#no_object_found").hide();'); + } + } + $oPage->add_ready_script( + <<SetContentType('text/html'); - $oPage->add( -<<SetContentType('text/html'); + $oPage->add( + << .ui-progressbar { position: relative; @@ -1719,595 +1722,596 @@ EOF } EOF - ); - $oPage->add('
'); - $oPage->add('
'); - $oPage->add('

 

'); - $oPage->add('

'.Dict::S('UI:CSVImport:AdvancedMode+').'

'); - $oPage->add('

 

'); - $oPage->add('
'); - $oPage->add('

'.Dict::S('ExcelExport:PreparingExport').'

'); - $oPage->add('
'.Dict::S('ExcelExport:Statistics').'
'); - $oPage->add('
'); - $aLabels = array( - 'dialog_title' => Dict::S('ExcelExporter:ExportDialogTitle'), - 'cancel_button' => Dict::S('UI:Button:Cancel'), - 'export_button' => Dict::S('ExcelExporter:ExportButton'), - 'download_button' => Dict::Format('ExcelExporter:DownloadButton', 'export.xlsx'), //TODO: better name for the file (based on the class of the filter??) - ); - $sJSLabels = json_encode($aLabels); - $sFilter = addslashes($sFilter); - $sJSPageUrl = addslashes(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php'); - $oPage->add_ready_script("$('#XlsxExportDlg').xlsxexporter({filter: '$sFilter', labels: $sJSLabels, ajax_page_url: '$sJSPageUrl'});"); - break; - + ); + $oPage->add('
'); + $oPage->add('
'); + $oPage->add('

 

'); + $oPage->add('

'.Dict::S('UI:CSVImport:AdvancedMode+').'

'); + $oPage->add('

 

'); + $oPage->add('
'); + $oPage->add('

'.Dict::S('ExcelExport:PreparingExport').'

'); + $oPage->add('
'.Dict::S('ExcelExport:Statistics').'
'); + $oPage->add('
'); + $aLabels = array( + 'dialog_title' => Dict::S('ExcelExporter:ExportDialogTitle'), + 'cancel_button' => Dict::S('UI:Button:Cancel'), + 'export_button' => Dict::S('ExcelExporter:ExportButton'), + 'download_button' => Dict::Format('ExcelExporter:DownloadButton', 'export.xlsx'), //TODO: better name for the file (based on the class of the filter??) + ); + $sJSLabels = json_encode($aLabels); + $sFilter = addslashes($sFilter); + $sJSPageUrl = addslashes(utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php'); + $oPage->add_ready_script("$('#XlsxExportDlg').xlsxexporter({filter: '$sFilter', labels: $sJSLabels, ajax_page_url: '$sJSPageUrl'});"); + break; + case 'xlsx_start': - $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); - $bAdvanced = (utils::ReadParam('advanced', 'false') == 'true'); - $oSearch = DBObjectSearch::unserialize($sFilter); - - $oExcelExporter = new ExcelExporter(); - $oExcelExporter->SetObjectList($oSearch); - //$oExcelExporter->SetChunkSize(10); //Only for testing - $oExcelExporter->SetAdvancedMode($bAdvanced); - $sToken = $oExcelExporter->SaveState(); - $oPage->add(json_encode(array('status' => 'ok', 'token' => $sToken))); - break; - + $sFilter = utils::ReadParam('filter', '', false, 'raw_data'); + $bAdvanced = (utils::ReadParam('advanced', 'false') == 'true'); + $oSearch = DBObjectSearch::unserialize($sFilter); + + $oExcelExporter = new ExcelExporter(); + $oExcelExporter->SetObjectList($oSearch); + //$oExcelExporter->SetChunkSize(10); //Only for testing + $oExcelExporter->SetAdvancedMode($bAdvanced); + $sToken = $oExcelExporter->SaveState(); + $oPage->add(json_encode(array('status' => 'ok', 'token' => $sToken))); + break; + case 'xlsx_run': - $sMemoryLimit = MetaModel::GetConfig()->Get('xlsx_exporter_memory_limit'); - ini_set('memory_limit', $sMemoryLimit); - ini_set('max_execution_time', max(300, ini_get('max_execution_time'))); // At least 5 minutes - - $sToken = utils::ReadParam('token', '', false, 'raw_data'); - $oExcelExporter = new ExcelExporter($sToken); - $aStatus = $oExcelExporter->Run(); - $aResults = array('status' => $aStatus['code'], 'percentage' => $aStatus['percentage'], 'message' => $aStatus['message']); - if ($aStatus['code'] == 'done') - { - $aResults['statistics'] = $oExcelExporter->GetStatistics('html'); - } - $oPage->add(json_encode($aResults)); - break; - + $sMemoryLimit = MetaModel::GetConfig()->Get('xlsx_exporter_memory_limit'); + ini_set('memory_limit', $sMemoryLimit); + ini_set('max_execution_time', max(300, ini_get('max_execution_time'))); // At least 5 minutes + + $sToken = utils::ReadParam('token', '', false, 'raw_data'); + $oExcelExporter = new ExcelExporter($sToken); + $aStatus = $oExcelExporter->Run(); + $aResults = array('status' => $aStatus['code'], 'percentage' => $aStatus['percentage'], 'message' => $aStatus['message']); + if ($aStatus['code'] == 'done') + { + $aResults['statistics'] = $oExcelExporter->GetStatistics('html'); + } + $oPage->add(json_encode($aResults)); + break; + case 'xlsx_download': - $sToken = utils::ReadParam('token', '', false, 'raw_data'); - $oPage->SetContentType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); - $oPage->SetContentDisposition('attachment', 'export.xlsx'); - $sFileContent = ExcelExporter::GetExcelFileFromToken($sToken); - $oPage->add($sFileContent); - ExcelExporter::CleanupFromToken($sToken); - break; - + $sToken = utils::ReadParam('token', '', false, 'raw_data'); + $oPage->SetContentType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + $oPage->SetContentDisposition('attachment', 'export.xlsx'); + $sFileContent = ExcelExporter::GetExcelFileFromToken($sToken); + $oPage->add($sFileContent); + ExcelExporter::CleanupFromToken($sToken); + break; + case 'xlsx_abort': - // Stop & cleanup an export... - $sToken = utils::ReadParam('token', '', false, 'raw_data'); - ExcelExporter::CleanupFromToken($sToken); - break; + // Stop & cleanup an export... + $sToken = utils::ReadParam('token', '', false, 'raw_data'); + ExcelExporter::CleanupFromToken($sToken); + break; case 'relation_pdf': case 'relation_attachment': - require_once(APPROOT.'core/simplegraph.class.inc.php'); - require_once(APPROOT.'core/relationgraph.class.inc.php'); - require_once(APPROOT.'core/displayablegraph.class.inc.php'); - $sRelation = utils::ReadParam('relation', 'impacts'); - $sDirection = utils::ReadParam('direction', 'down'); - - $iGroupingThreshold = utils::ReadParam('g', 5, false, 'integer'); - $sPageFormat = utils::ReadParam('p', 'A4'); - $sPageOrientation = utils::ReadParam('o', 'L'); - $sTitle = utils::ReadParam('title', '', false, 'raw_data'); - $sPositions = utils::ReadParam('positions', null, false, 'raw_data'); - $aExcludedClasses = utils::ReadParam('excluded_classes', array(), false, 'raw_data'); - $bIncludeList = (bool)utils::ReadParam('include_list', false); - $sComments = utils::ReadParam('comments', '', false, 'raw_data'); - $aContexts = utils::ReadParam('contexts', array(), false, 'raw_data'); - $sContextKey = utils::ReadParam('context_key', '', false, 'raw_data'); - $aPositions = null; - if ($sPositions != null) - { - $aPositions = json_decode($sPositions, true); - } - - // Get the list of source objects - $aSources = utils::ReadParam('sources', array(), false, 'raw_data'); - $aSourceObjects = array(); - foreach($aSources as $sClass => $aIDs) - { - $oSearch = new DBObjectSearch($sClass); - $oSearch->AddCondition('id', $aIDs, 'IN'); - $oSet = new DBObjectSet($oSearch); - while($oObj = $oSet->Fetch()) - { - $aSourceObjects[] = $oObj; - } - } - $sSourceClass = '*'; - if (count($aSourceObjects) == 1) - { - $sSourceClass = get_class($aSourceObjects[0]); - } - - // Get the list of excluded objects - $aExcluded = utils::ReadParam('excluded', array(), false, 'raw_data'); - $aExcludedObjects = array(); - foreach($aExcluded as $sClass => $aIDs) - { - $oSearch = new DBObjectSearch($sClass); - $oSearch->AddCondition('id', $aIDs, 'IN'); - $oSet = new DBObjectSet($oSearch); - while($oObj = $oSet->Fetch()) - { - $aExcludedObjects[] = $oObj; - } - } - - $iMaxRecursionDepth = MetaModel::GetConfig()->Get('relations_max_depth', 20); - if ($sDirection == 'up') - { - $oRelGraph = MetaModel::GetRelatedObjectsUp($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aContexts); - } - else - { - $oRelGraph = MetaModel::GetRelatedObjectsDown($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aExcludedObjects, $aContexts); - } - - // Remove excluded classes from the graph - if (count($aExcludedClasses) > 0) - { - $oIterator = new RelationTypeIterator($oRelGraph, 'Node'); - foreach($oIterator as $oNode) - { - $oObj = $oNode->GetProperty('object'); - if ($oObj && in_array(get_class($oObj), $aExcludedClasses)) - { - $oRelGraph->FilterNode($oNode); - } - } - } - - $oPage = new PDFPage($sTitle, $sPageFormat, $sPageOrientation); - $oPage->SetContentDisposition('attachment', $sTitle.'.pdf'); - - $oGraph = DisplayableGraph::FromRelationGraph($oRelGraph, $iGroupingThreshold, ($sDirection == 'down')); - $oGraph->InitFromGraphviz(); - if ($aPositions != null) - { - $oGraph->UpdatePositions($aPositions); - } + require_once(APPROOT.'core/simplegraph.class.inc.php'); + require_once(APPROOT.'core/relationgraph.class.inc.php'); + require_once(APPROOT.'core/displayablegraph.class.inc.php'); + $sRelation = utils::ReadParam('relation', 'impacts'); + $sDirection = utils::ReadParam('direction', 'down'); - $aGroups = array(); - $oIterator = new RelationTypeIterator($oGraph, 'Node'); - foreach($oIterator as $oNode) - { - if ($oNode instanceof DisplayableGroupNode) + $iGroupingThreshold = utils::ReadParam('g', 5, false, 'integer'); + $sPageFormat = utils::ReadParam('p', 'A4'); + $sPageOrientation = utils::ReadParam('o', 'L'); + $sTitle = utils::ReadParam('title', '', false, 'raw_data'); + $sPositions = utils::ReadParam('positions', null, false, 'raw_data'); + $aExcludedClasses = utils::ReadParam('excluded_classes', array(), false, 'raw_data'); + $bIncludeList = (bool)utils::ReadParam('include_list', false); + $sComments = utils::ReadParam('comments', '', false, 'raw_data'); + $aContexts = utils::ReadParam('contexts', array(), false, 'raw_data'); + $sContextKey = utils::ReadParam('context_key', '', false, 'raw_data'); + $aPositions = null; + if ($sPositions != null) { - $aGroups[$oNode->GetProperty('group_index')] = $oNode->GetObjects(); + $aPositions = json_decode($sPositions, true); } - } - // First page is the graph - $oGraph->RenderAsPDF($oPage, $sComments, $sContextKey); - if ($bIncludeList) - { - // Then the lists of objects (one table per finalclass) - $aResults = array(); - $oIterator = new RelationTypeIterator($oRelGraph, 'Node'); - foreach($oIterator as $oNode) - { - $oObj = $oNode->GetProperty('object'); // Some nodes (Redundancy Nodes and Group) do not contain an object - if ($oObj) - { - $sObjClass = get_class($oObj); - if (!array_key_exists($sObjClass, $aResults)) - { - $aResults[$sObjClass] = array(); - } - $aResults[$sObjClass][] = $oObj; - } - } - - $oPage->get_tcpdf()->AddPage(); - $oPage->get_tcpdf()->SetFont('dejavusans', '', 10, '', true); // Reset the font size to its default - $oPage->add(''); - $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); - foreach($aResults as $sListClass => $aObjects) - { - set_time_limit($iLoopTimeLimit*count($aObjects)); - $oSet = CMDBObjectSet::FromArray($sListClass, $aObjects); - $oSet->SetShowObsoleteData(utils::ShowObsoleteData()); - $sHtml = "
\n"; - $sHtml .= "
".MetaModel::GetClassIcon($sListClass, true, 'width: 24px; height: 24px;')." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(), Metamodel::GetName($sListClass))."
\n"; - $sHtml .= "
\n"; - $oPage->add($sHtml); - cmdbAbstractObject::DisplaySet($oPage, $oSet, array('table_id' => $sSourceClass.'_'.$sRelation.'_'.$sDirection.'_'.$sListClass)); - $oPage->p(''); // Some space - } - - // Then the content of the groups (one table per group) - if (count($aGroups) > 0) - { - $oPage->get_tcpdf()->AddPage(); - $oPage->add(''); - foreach($aGroups as $idx => $aObjects) - { - set_time_limit($iLoopTimeLimit*count($aObjects)); - $sListClass = get_class(current($aObjects)); - $oSet = CMDBObjectSet::FromArray($sListClass, $aObjects); - $sHtml = "
\n"; - $sHtml .= "
".MetaModel::GetClassIcon($sListClass, true, 'width: 24px; height: 24px;')." ".Dict::Format('UI:RelationGroupNumber_N', (1+$idx))."
\n"; - $sHtml .= "
\n"; - $oPage->add($sHtml); - cmdbAbstractObject::DisplaySet($oPage, $oSet); - $oPage->p(''); // Some space - } - } - } - if ($operation == 'relation_attachment') - { - $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); - $iObjKey = (int)utils::ReadParam('obj_key', 0, false, 'integer'); - - // Save the generated PDF as an attachment - $sPDF = $oPage->get_pdf(); - $oPage = new ajax_page(''); - $oAttachment = new Attachment(); - $oAttachment->Set('item_class', $sObjClass); - $oAttachment->Set('item_id', $iObjKey); - $oDoc = new ormDocument($sPDF, 'application/pdf', $sTitle.'.pdf'); - $oAttachment->Set('contents', $oDoc); - $iAttachmentId = $oAttachment->DBInsert(); - $aRet = array( - 'status' => 'ok', - 'att_id' => $iAttachmentId, - ); - $oPage->add(json_encode($aRet)); - } - break; - - case 'relation_json': - require_once(APPROOT.'core/simplegraph.class.inc.php'); - require_once(APPROOT.'core/relationgraph.class.inc.php'); - require_once(APPROOT.'core/displayablegraph.class.inc.php'); - $sRelation = utils::ReadParam('relation', 'impacts'); - $sDirection = utils::ReadParam('direction', 'down'); - $iGroupingThreshold = utils::ReadParam('g', 5); - $sPositions = utils::ReadParam('positions', null, false, 'raw_data'); - $aExcludedClasses = utils::ReadParam('excluded_classes', array(), false, 'raw_data'); - $aContexts = utils::ReadParam('contexts', array(), false, 'raw_data'); - $sContextKey = utils::ReadParam('context_key', array(), false, 'raw_data'); - $aPositions = null; - if ($sPositions != null) - { - $aPositions = json_decode($sPositions, true); - } - // Get the list of source objects - $aSources = utils::ReadParam('sources', array(), false, 'raw_data'); - $aSourceObjects = array(); - foreach($aSources as $sClass => $aIDs) - { - $oSearch = new DBObjectSearch($sClass); - $oSearch->AddCondition('id', $aIDs, 'IN'); - $oSet = new DBObjectSet($oSearch); - while($oObj = $oSet->Fetch()) + $aSources = utils::ReadParam('sources', array(), false, 'raw_data'); + $aSourceObjects = array(); + foreach($aSources as $sClass => $aIDs) { - $aSourceObjects[] = $oObj; - } - } - - // Get the list of excluded objects - $aExcluded = utils::ReadParam('excluded', array(), false, 'raw_data'); - $aExcludedObjects = array(); - foreach($aExcluded as $sClass => $aIDs) - { - $oSearch = new DBObjectSearch($sClass); - $oSearch->AddCondition('id', $aIDs, 'IN'); - $oSet = new DBObjectSet($oSearch); - while($oObj = $oSet->Fetch()) - { - $aExcludedObjects[] = $oObj; - } - } - - // Compute the graph - $iMaxRecursionDepth = MetaModel::GetConfig()->Get('relations_max_depth', 20); - if ($sDirection == 'up') - { - $oRelGraph = MetaModel::GetRelatedObjectsUp($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aContexts); - } - else - { - $oRelGraph = MetaModel::GetRelatedObjectsDown($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aExcludedObjects, $aContexts); - } - - // Remove excluded classes from the graph - if (count($aExcludedClasses) > 0) - { - $oIterator = new RelationTypeIterator($oRelGraph, 'Node'); - foreach($oIterator as $oNode) - { - $oObj = $oNode->GetProperty('object'); - if ($oObj && in_array(get_class($oObj), $aExcludedClasses)) + $oSearch = new DBObjectSearch($sClass); + $oSearch->AddCondition('id', $aIDs, 'IN'); + $oSet = new DBObjectSet($oSearch); + while ($oObj = $oSet->Fetch()) { - $oRelGraph->FilterNode($oNode); + $aSourceObjects[] = $oObj; } } - } - - $oGraph = DisplayableGraph::FromRelationGraph($oRelGraph, $iGroupingThreshold, ($sDirection == 'down')); - $oGraph->InitFromGraphviz(); - if ($aPositions != null) - { - $oGraph->UpdatePositions($aPositions); - } - $oPage->add($oGraph->GetAsJSON($sContextKey)); - $oPage->SetContentType('application/json'); - break; - - case 'relation_groups': - $aGroups = utils::ReadParam('groups'); - $iBlock = 1; // Zero is not a valid blockid - foreach($aGroups as $idx => $aDefinition) - { - $sListClass = $aDefinition['class']; - $oSearch = new DBObjectSearch($sListClass); - $oSearch->AddCondition('id', $aDefinition['keys'], 'IN'); - $oSearch->SetShowObsoleteData(utils::ShowObsoleteData()); - $oPage->add("

".Dict::Format('UI:RelationGroupNumber_N', (1+$idx))."

\n"); - $oPage->add("
\n"); - $oPage->add("

".MetaModel::GetClassIcon($sListClass)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aDefinition['keys']), Metamodel::GetName($sListClass))."

\n"); - $oPage->add("
\n"); - $oBlock = new DisplayBlock($oSearch, 'list'); - $oBlock->Display($oPage, 'group_'.$iBlock++); - $oPage->p(' '); // Some space ? - } - break; + $sSourceClass = '*'; + if (count($aSourceObjects) == 1) + { + $sSourceClass = get_class($aSourceObjects[0]); + } - case 'relation_lists': - $aLists = utils::ReadParam('lists'); - $iBlock = 1; // Zero is not a valid blockid - foreach($aLists as $sListClass => $aKeys) - { - $oSearch = new DBObjectSearch($sListClass); - $oSearch->AddCondition('id', $aKeys, 'IN'); - $oSearch->SetShowObsoleteData(utils::ShowObsoleteData()); - $oPage->add("
\n"); - $oPage->add("

".MetaModel::GetClassIcon($sListClass)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aKeys), Metamodel::GetName($sListClass))."

\n"); - $oPage->add("
\n"); - $oBlock = new DisplayBlock($oSearch, 'list'); - $oBlock->Display($oPage, 'list_'.$iBlock++, array('table_id' => 'ImpactAnalysis_'.$sListClass)); - $oPage->p(' '); // Some space ? - } - break; - - case 'ticket_impact': - require_once(APPROOT.'core/simplegraph.class.inc.php'); - require_once(APPROOT.'core/relationgraph.class.inc.php'); - require_once(APPROOT.'core/displayablegraph.class.inc.php'); - $sRelation = utils::ReadParam('relation', 'impacts'); - $sDirection = utils::ReadParam('direction', 'down'); - $iGroupingThreshold = utils::ReadParam('g', 5); - $sClass = utils::ReadParam('class', '', false, 'class'); - $sAttCode = utils::ReadParam('attcode', 'functionalcis_list'); - $sImpactAttCode = utils::ReadParam('impact_attcode', 'impact_code'); - $sImpactAttCodeValue = utils::ReadParam('impact_attcode_value', 'manual'); - $iId = (int)utils::ReadParam('id', 0, false, 'integer'); - - // Get the list of source objects - $oTicket = MetaModel::GetObject($sClass, $iId); - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - $sExtKeyToRemote = $oAttDef->GetExtKeyToRemote(); - $oExtKeyToRemote = MetaModel::GetAttributeDef($oAttDef->GetLinkedClass(), $sExtKeyToRemote); - $sRemoteClass = $oExtKeyToRemote->GetTargetClass(); - $oSet = $oTicket->Get($sAttCode); - $aSourceObjects = array(); - $aExcludedObjects = array(); - while($oLnk = $oSet->Fetch()) - { - if ($oLnk->Get($sImpactAttCode) == 'manual') + // Get the list of excluded objects + $aExcluded = utils::ReadParam('excluded', array(), false, 'raw_data'); + $aExcludedObjects = array(); + foreach($aExcluded as $sClass => $aIDs) { - $aSourceObjects[] = MetaModel::GetObject($sRemoteClass, $oLnk->Get($sExtKeyToRemote)); - } - if ($oLnk->Get($sImpactAttCode) == 'not_impacted') - { - $aExcludedObjects[] = MetaModel::GetObject($sRemoteClass, $oLnk->Get($sExtKeyToRemote)); - } - } - - // Compute the graph - $iMaxRecursionDepth = MetaModel::GetConfig()->Get('relations_max_depth', 20); - if ($sDirection == 'up') - { - $oRelGraph = MetaModel::GetRelatedObjectsUp($sRelation, $aSourceObjects, $iMaxRecursionDepth); - } - else - { - $oRelGraph = MetaModel::GetRelatedObjectsDown($sRelation, $aSourceObjects, $iMaxRecursionDepth, $aExcludedObjects); - } - - $aResults = $oRelGraph->GetObjectsByClass(); - $oGraph = DisplayableGraph::FromRelationGraph($oRelGraph, $iGroupingThreshold, ($sDirection == 'down')); - - $sContextKey = 'itop-tickets/relation_context/'.$sClass.'/'.$sRelation.'/'.$sDirection; - $oAppContext = new ApplicationContext(); - $oGraph->Display($oPage, $aResults, $sRelation, $oAppContext, $aExcludedObjects, $sClass, $iId, $sContextKey, array('this' => $oTicket)); - break; - - case 'export_build': - register_shutdown_function(function() - { - $aErr = error_get_last(); - if (($aErr !== null) && ($aErr['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR))) - { - ob_end_clean(); - echo json_encode(array('code' => 'error', 'percentage' => 100, 'message' => Dict::Format('UI:Error_Details', $aErr['message']))); - } - }); - try - { - $token = utils::ReadParam('token', null); - $aResult = array('code' => 'error', 'percentage' => 100, 'message' => "Export not found for token: '$token'"); // Fallback error, just in case - $data = ''; - if ($token === null) - { - $sFormat = utils::ReadParam('format', ''); - $sExpression = utils::ReadParam('expression', null, false, 'raw_data'); - $iQueryId = utils::ReadParam('query', null); - if ($sExpression === null) + $oSearch = new DBObjectSearch($sClass); + $oSearch->AddCondition('id', $aIDs, 'IN'); + $oSet = new DBObjectSet($oSearch); + while ($oObj = $oSet->Fetch()) { - $oQuerySearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $iQueryId)); - $oQuerySearch->UpdateContextFromUser(); - $oQueries = new DBObjectSet($oQuerySearch); - if ($oQueries->Count() > 0) - { - $oQuery = $oQueries->Fetch(); - $sExpression = $oQuery->Get('oql'); - } - else - { - $aResult = array('code' => 'error', 'percentage' => 100, 'message' => "Invalid query phrasebook identifier: '$iQueryId'"); - } + $aExcludedObjects[] = $oObj; } - if($sExpression !== null) - { - $oSearch = DBObjectSearch::FromOQL($sExpression); - $oSearch->UpdateContextFromUser(); - $oExporter = BulkExport::FindExporter($sFormat, $oSearch); - $oExporter->SetObjectList($oSearch); - $oExporter->SetFormat($sFormat); - $oExporter->SetChunkSize(EXPORTER_DEFAULT_CHUNK_SIZE); - $oExporter->ReadParameters(); - } - - // First pass, generate the headers - $data .= $oExporter->GetHeader(); + } + + $iMaxRecursionDepth = MetaModel::GetConfig()->Get('relations_max_depth', 20); + if ($sDirection == 'up') + { + $oRelGraph = MetaModel::GetRelatedObjectsUp($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aContexts); } else { - $oExporter = BulkExport::FindExporterFromToken($token); + $oRelGraph = MetaModel::GetRelatedObjectsDown($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aExcludedObjects, $aContexts); } - - if ($oExporter) + + // Remove excluded classes from the graph + if (count($aExcludedClasses) > 0) { - $data .= $oExporter->GetNextChunk($aResult); - if ($aResult['code'] != 'done') + $oIterator = new RelationTypeIterator($oRelGraph, 'Node'); + foreach($oIterator as $oNode) { - $oExporter->AppendToTmpFile($data); - $aResult['token'] = $oExporter->SaveState(); - } - else - { - // Last pass - $data .= $oExporter->GetFooter(); - $oExporter->AppendToTmpFile($data); - $aResult['token'] = $oExporter->SaveState(); - if (substr($oExporter->GetMimeType(), 0, 5) == 'text/') + $oObj = $oNode->GetProperty('object'); + if ($oObj && in_array(get_class($oObj), $aExcludedClasses)) { - // Result must be encoded in UTF-8 to be passed as part of a JSON structure - $sCharset = $oExporter->GetCharacterSet(); - if (strtoupper($sCharset) != 'UTF-8') + $oRelGraph->FilterNode($oNode); + } + } + } + + $oPage = new PDFPage($sTitle, $sPageFormat, $sPageOrientation); + $oPage->SetContentDisposition('attachment', $sTitle.'.pdf'); + + $oGraph = DisplayableGraph::FromRelationGraph($oRelGraph, $iGroupingThreshold, ($sDirection == 'down')); + $oGraph->InitFromGraphviz(); + if ($aPositions != null) + { + $oGraph->UpdatePositions($aPositions); + } + + $aGroups = array(); + $oIterator = new RelationTypeIterator($oGraph, 'Node'); + foreach($oIterator as $oNode) + { + if ($oNode instanceof DisplayableGroupNode) + { + $aGroups[$oNode->GetProperty('group_index')] = $oNode->GetObjects(); + } + } + // First page is the graph + $oGraph->RenderAsPDF($oPage, $sComments, $sContextKey); + + if ($bIncludeList) + { + // Then the lists of objects (one table per finalclass) + $aResults = array(); + $oIterator = new RelationTypeIterator($oRelGraph, 'Node'); + foreach($oIterator as $oNode) + { + $oObj = $oNode->GetProperty('object'); // Some nodes (Redundancy Nodes and Group) do not contain an object + if ($oObj) + { + $sObjClass = get_class($oObj); + if (!array_key_exists($sObjClass, $aResults)) { - $aResult['text_result'] = iconv($sCharset, 'UTF-8', file_get_contents($oExporter->GetTmpFilePath())); + $aResults[$sObjClass] = array(); + } + $aResults[$sObjClass][] = $oObj; + } + } + + $oPage->get_tcpdf()->AddPage(); + $oPage->get_tcpdf()->SetFont('dejavusans', '', 10, '', true); // Reset the font size to its default + $oPage->add(''); + $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); + foreach($aResults as $sListClass => $aObjects) + { + set_time_limit($iLoopTimeLimit * count($aObjects)); + $oSet = CMDBObjectSet::FromArray($sListClass, $aObjects); + $oSet->SetShowObsoleteData(utils::ShowObsoleteData()); + $sHtml = "
\n"; + $sHtml .= "
".MetaModel::GetClassIcon($sListClass, true, 'width: 24px; height: 24px;')." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', $oSet->Count(), + Metamodel::GetName($sListClass))."
\n"; + $sHtml .= "
\n"; + $oPage->add($sHtml); + cmdbAbstractObject::DisplaySet($oPage, $oSet, array('table_id' => $sSourceClass.'_'.$sRelation.'_'.$sDirection.'_'.$sListClass)); + $oPage->p(''); // Some space + } + + // Then the content of the groups (one table per group) + if (count($aGroups) > 0) + { + $oPage->get_tcpdf()->AddPage(); + $oPage->add(''); + foreach($aGroups as $idx => $aObjects) + { + set_time_limit($iLoopTimeLimit * count($aObjects)); + $sListClass = get_class(current($aObjects)); + $oSet = CMDBObjectSet::FromArray($sListClass, $aObjects); + $sHtml = "
\n"; + $sHtml .= "
".MetaModel::GetClassIcon($sListClass, true, 'width: 24px; height: 24px;')." ".Dict::Format('UI:RelationGroupNumber_N', (1 + $idx))."
\n"; + $sHtml .= "
\n"; + $oPage->add($sHtml); + cmdbAbstractObject::DisplaySet($oPage, $oSet); + $oPage->p(''); // Some space + } + } + } + if ($operation == 'relation_attachment') + { + $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); + $iObjKey = (int)utils::ReadParam('obj_key', 0, false, 'integer'); + + // Save the generated PDF as an attachment + $sPDF = $oPage->get_pdf(); + $oPage = new ajax_page(''); + $oAttachment = new Attachment(); + $oAttachment->Set('item_class', $sObjClass); + $oAttachment->Set('item_id', $iObjKey); + $oDoc = new ormDocument($sPDF, 'application/pdf', $sTitle.'.pdf'); + $oAttachment->Set('contents', $oDoc); + $iAttachmentId = $oAttachment->DBInsert(); + $aRet = array( + 'status' => 'ok', + 'att_id' => $iAttachmentId, + ); + $oPage->add(json_encode($aRet)); + } + break; + + case 'relation_json': + require_once(APPROOT.'core/simplegraph.class.inc.php'); + require_once(APPROOT.'core/relationgraph.class.inc.php'); + require_once(APPROOT.'core/displayablegraph.class.inc.php'); + $sRelation = utils::ReadParam('relation', 'impacts'); + $sDirection = utils::ReadParam('direction', 'down'); + $iGroupingThreshold = utils::ReadParam('g', 5); + $sPositions = utils::ReadParam('positions', null, false, 'raw_data'); + $aExcludedClasses = utils::ReadParam('excluded_classes', array(), false, 'raw_data'); + $aContexts = utils::ReadParam('contexts', array(), false, 'raw_data'); + $sContextKey = utils::ReadParam('context_key', array(), false, 'raw_data'); + $aPositions = null; + if ($sPositions != null) + { + $aPositions = json_decode($sPositions, true); + } + + // Get the list of source objects + $aSources = utils::ReadParam('sources', array(), false, 'raw_data'); + $aSourceObjects = array(); + foreach($aSources as $sClass => $aIDs) + { + $oSearch = new DBObjectSearch($sClass); + $oSearch->AddCondition('id', $aIDs, 'IN'); + $oSet = new DBObjectSet($oSearch); + while ($oObj = $oSet->Fetch()) + { + $aSourceObjects[] = $oObj; + } + } + + // Get the list of excluded objects + $aExcluded = utils::ReadParam('excluded', array(), false, 'raw_data'); + $aExcludedObjects = array(); + foreach($aExcluded as $sClass => $aIDs) + { + $oSearch = new DBObjectSearch($sClass); + $oSearch->AddCondition('id', $aIDs, 'IN'); + $oSet = new DBObjectSet($oSearch); + while ($oObj = $oSet->Fetch()) + { + $aExcludedObjects[] = $oObj; + } + } + + // Compute the graph + $iMaxRecursionDepth = MetaModel::GetConfig()->Get('relations_max_depth', 20); + if ($sDirection == 'up') + { + $oRelGraph = MetaModel::GetRelatedObjectsUp($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aContexts); + } + else + { + $oRelGraph = MetaModel::GetRelatedObjectsDown($sRelation, $aSourceObjects, $iMaxRecursionDepth, true, $aExcludedObjects, $aContexts); + } + + // Remove excluded classes from the graph + if (count($aExcludedClasses) > 0) + { + $oIterator = new RelationTypeIterator($oRelGraph, 'Node'); + foreach($oIterator as $oNode) + { + $oObj = $oNode->GetProperty('object'); + if ($oObj && in_array(get_class($oObj), $aExcludedClasses)) + { + $oRelGraph->FilterNode($oNode); + } + } + } + + $oGraph = DisplayableGraph::FromRelationGraph($oRelGraph, $iGroupingThreshold, ($sDirection == 'down')); + $oGraph->InitFromGraphviz(); + if ($aPositions != null) + { + $oGraph->UpdatePositions($aPositions); + } + $oPage->add($oGraph->GetAsJSON($sContextKey)); + $oPage->SetContentType('application/json'); + break; + + case 'relation_groups': + $aGroups = utils::ReadParam('groups'); + $iBlock = 1; // Zero is not a valid blockid + foreach($aGroups as $idx => $aDefinition) + { + $sListClass = $aDefinition['class']; + $oSearch = new DBObjectSearch($sListClass); + $oSearch->AddCondition('id', $aDefinition['keys'], 'IN'); + $oSearch->SetShowObsoleteData(utils::ShowObsoleteData()); + $oPage->add("

".Dict::Format('UI:RelationGroupNumber_N', (1 + $idx))."

\n"); + $oPage->add("
\n"); + $oPage->add("

".MetaModel::GetClassIcon($sListClass)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aDefinition['keys']), Metamodel::GetName($sListClass))."

\n"); + $oPage->add("
\n"); + $oBlock = new DisplayBlock($oSearch, 'list'); + $oBlock->Display($oPage, 'group_'.$iBlock++); + $oPage->p(' '); // Some space ? + } + break; + + case 'relation_lists': + $aLists = utils::ReadParam('lists'); + $iBlock = 1; // Zero is not a valid blockid + foreach($aLists as $sListClass => $aKeys) + { + $oSearch = new DBObjectSearch($sListClass); + $oSearch->AddCondition('id', $aKeys, 'IN'); + $oSearch->SetShowObsoleteData(utils::ShowObsoleteData()); + $oPage->add("
\n"); + $oPage->add("

".MetaModel::GetClassIcon($sListClass)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aKeys), Metamodel::GetName($sListClass))."

\n"); + $oPage->add("
\n"); + $oBlock = new DisplayBlock($oSearch, 'list'); + $oBlock->Display($oPage, 'list_'.$iBlock++, array('table_id' => 'ImpactAnalysis_'.$sListClass)); + $oPage->p(' '); // Some space ? + } + break; + + case 'ticket_impact': + require_once(APPROOT.'core/simplegraph.class.inc.php'); + require_once(APPROOT.'core/relationgraph.class.inc.php'); + require_once(APPROOT.'core/displayablegraph.class.inc.php'); + $sRelation = utils::ReadParam('relation', 'impacts'); + $sDirection = utils::ReadParam('direction', 'down'); + $iGroupingThreshold = utils::ReadParam('g', 5); + $sClass = utils::ReadParam('class', '', false, 'class'); + $sAttCode = utils::ReadParam('attcode', 'functionalcis_list'); + $sImpactAttCode = utils::ReadParam('impact_attcode', 'impact_code'); + $sImpactAttCodeValue = utils::ReadParam('impact_attcode_value', 'manual'); + $iId = (int)utils::ReadParam('id', 0, false, 'integer'); + + // Get the list of source objects + $oTicket = MetaModel::GetObject($sClass, $iId); + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + $sExtKeyToRemote = $oAttDef->GetExtKeyToRemote(); + $oExtKeyToRemote = MetaModel::GetAttributeDef($oAttDef->GetLinkedClass(), $sExtKeyToRemote); + $sRemoteClass = $oExtKeyToRemote->GetTargetClass(); + $oSet = $oTicket->Get($sAttCode); + $aSourceObjects = array(); + $aExcludedObjects = array(); + while ($oLnk = $oSet->Fetch()) + { + if ($oLnk->Get($sImpactAttCode) == 'manual') + { + $aSourceObjects[] = MetaModel::GetObject($sRemoteClass, $oLnk->Get($sExtKeyToRemote)); + } + if ($oLnk->Get($sImpactAttCode) == 'not_impacted') + { + $aExcludedObjects[] = MetaModel::GetObject($sRemoteClass, $oLnk->Get($sExtKeyToRemote)); + } + } + + // Compute the graph + $iMaxRecursionDepth = MetaModel::GetConfig()->Get('relations_max_depth', 20); + if ($sDirection == 'up') + { + $oRelGraph = MetaModel::GetRelatedObjectsUp($sRelation, $aSourceObjects, $iMaxRecursionDepth); + } + else + { + $oRelGraph = MetaModel::GetRelatedObjectsDown($sRelation, $aSourceObjects, $iMaxRecursionDepth, $aExcludedObjects); + } + + $aResults = $oRelGraph->GetObjectsByClass(); + $oGraph = DisplayableGraph::FromRelationGraph($oRelGraph, $iGroupingThreshold, ($sDirection == 'down')); + + $sContextKey = 'itop-tickets/relation_context/'.$sClass.'/'.$sRelation.'/'.$sDirection; + $oAppContext = new ApplicationContext(); + $oGraph->Display($oPage, $aResults, $sRelation, $oAppContext, $aExcludedObjects, $sClass, $iId, $sContextKey, array('this' => $oTicket)); + break; + + case 'export_build': + register_shutdown_function(function () { + $aErr = error_get_last(); + if (($aErr !== null) && ($aErr['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR))) + { + ob_end_clean(); + echo json_encode(array('code' => 'error', 'percentage' => 100, 'message' => Dict::Format('UI:Error_Details', $aErr['message']))); + } + }); + try + { + $token = utils::ReadParam('token', null); + $aResult = array('code' => 'error', 'percentage' => 100, 'message' => "Export not found for token: '$token'"); // Fallback error, just in case + $data = ''; + if ($token === null) + { + $sFormat = utils::ReadParam('format', ''); + $sExpression = utils::ReadParam('expression', null, false, 'raw_data'); + $iQueryId = utils::ReadParam('query', null); + if ($sExpression === null) + { + $oQuerySearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $iQueryId)); + $oQuerySearch->UpdateContextFromUser(); + $oQueries = new DBObjectSet($oQuerySearch); + if ($oQueries->Count() > 0) + { + $oQuery = $oQueries->Fetch(); + $sExpression = $oQuery->Get('oql'); } else { - $aResult['text_result'] = file_get_contents($oExporter->GetTmpFilePath()); + $aResult = array('code' => 'error', 'percentage' => 100, 'message' => "Invalid query phrasebook identifier: '$iQueryId'"); } - $aResult['mime_type'] = $oExporter->GetMimeType(); } - $aResult['message'] = Dict::Format('Core:BulkExport:ClickHereToDownload_FileName', $oExporter->GetDownloadFileName()); + if ($sExpression !== null) + { + $oSearch = DBObjectSearch::FromOQL($sExpression); + $oSearch->UpdateContextFromUser(); + $oExporter = BulkExport::FindExporter($sFormat, $oSearch); + $oExporter->SetObjectList($oSearch); + $oExporter->SetFormat($sFormat); + $oExporter->SetChunkSize(EXPORTER_DEFAULT_CHUNK_SIZE); + $oExporter->ReadParameters(); + } + + // First pass, generate the headers + $data .= $oExporter->GetHeader(); } + else + { + $oExporter = BulkExport::FindExporterFromToken($token); + } + + if ($oExporter) + { + $data .= $oExporter->GetNextChunk($aResult); + if ($aResult['code'] != 'done') + { + $oExporter->AppendToTmpFile($data); + $aResult['token'] = $oExporter->SaveState(); + } + else + { + // Last pass + $data .= $oExporter->GetFooter(); + $oExporter->AppendToTmpFile($data); + $aResult['token'] = $oExporter->SaveState(); + if (substr($oExporter->GetMimeType(), 0, 5) == 'text/') + { + // Result must be encoded in UTF-8 to be passed as part of a JSON structure + $sCharset = $oExporter->GetCharacterSet(); + if (strtoupper($sCharset) != 'UTF-8') + { + $aResult['text_result'] = iconv($sCharset, 'UTF-8', file_get_contents($oExporter->GetTmpFilePath())); + } + else + { + $aResult['text_result'] = file_get_contents($oExporter->GetTmpFilePath()); + } + $aResult['mime_type'] = $oExporter->GetMimeType(); + } + $aResult['message'] = Dict::Format('Core:BulkExport:ClickHereToDownload_FileName', $oExporter->GetDownloadFileName()); + } + } + $oPage->add(json_encode($aResult)); + } catch (BulkExportException $e) + { + $aResult = array('code' => 'error', 'percentage' => 100, 'message' => $e->GetLocalizedMessage()); + $oPage->add(json_encode($aResult)); + } catch (Exception $e) + { + $aResult = array('code' => 'error', 'percentage' => 100, 'message' => $e->getMessage()); + $oPage->add(json_encode($aResult)); } - $oPage->add(json_encode($aResult)); - } - catch(BulkExportException $e) - { - $aResult = array('code' => 'error', 'percentage' => 100, 'message' => $e->GetLocalizedMessage()); - $oPage->add(json_encode($aResult)); - } - catch(Exception $e) - { - $aResult = array('code' => 'error', 'percentage' => 100, 'message' => $e->getMessage()); - $oPage->add(json_encode($aResult)); - } - break; - + break; + case 'export_download': - $token = utils::ReadParam('token', null); - if ($token !== null) - { - $oExporter = BulkExport::FindExporterFromToken($token); - if ($oExporter) + $token = utils::ReadParam('token', null); + if ($token !== null) { - $sMimeType = $oExporter->GetMimeType(); - if (substr($sMimeType, 0, 5) == 'text/') + $oExporter = BulkExport::FindExporterFromToken($token); + if ($oExporter) { - $sMimeType .= ';charset='.strtolower($oExporter->GetCharacterSet()); + $sMimeType = $oExporter->GetMimeType(); + if (substr($sMimeType, 0, 5) == 'text/') + { + $sMimeType .= ';charset='.strtolower($oExporter->GetCharacterSet()); + } + $oPage->SetContentType($sMimeType); + $oPage->SetContentDisposition('attachment', $oExporter->GetDownloadFileName()); + $oPage->add(file_get_contents($oExporter->GetTmpFilePath())); } - $oPage->SetContentType($sMimeType); - $oPage->SetContentDisposition('attachment', $oExporter->GetDownloadFileName()); - $oPage->add(file_get_contents($oExporter->GetTmpFilePath())); } - } - break; - + break; + case 'export_cancel': - $token = utils::ReadParam('token', null); - if ($token !== null) - { - $oExporter = BulkExport::FindExporterFromToken($token); - if ($oExporter) + $token = utils::ReadParam('token', null); + if ($token !== null) { - $oExporter->Cleanup(); - } - } - $aResult = array('code' => 'error', 'percentage' => 100, 'message' => Dict::S('Core:BulkExport:ExportCancelledByUser')); - $oPage->add(json_encode($aResult)); - break; - - case 'extend_lock': - $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); - $iObjKey = (int)utils::ReadParam('obj_key', 0, false, 'integer'); - $sToken = utils::ReadParam('token', 0, false, 'raw_data'); - $aResult = iTopOwnershipLock::ExtendLock($sObjClass, $iObjKey, $sToken); - if (!$aResult['status']) - { - if ($aResult['operation'] == 'lost') - { - $sName = $aResult['owner']->GetName(); - if ($aResult['owner']->Get('contactid') != 0) + $oExporter = BulkExport::FindExporterFromToken($token); + if ($oExporter) { - $sName .= ' ('.$aResult['owner']->Get('contactid_friendlyname').')'; + $oExporter->Cleanup(); } - $aResult['message'] = Dict::Format('UI:CurrentObjectIsLockedBy_User', $sName); - $aResult['popup_message'] = Dict::Format('UI:CurrentObjectIsLockedBy_User_Explanation', $sName); } - else if ($aResult['operation'] == 'expired') + $aResult = array('code' => 'error', 'percentage' => 100, 'message' => Dict::S('Core:BulkExport:ExportCancelledByUser')); + $oPage->add(json_encode($aResult)); + break; + + case 'extend_lock': + $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); + $iObjKey = (int)utils::ReadParam('obj_key', 0, false, 'integer'); + $sToken = utils::ReadParam('token', 0, false, 'raw_data'); + $aResult = iTopOwnershipLock::ExtendLock($sObjClass, $iObjKey, $sToken); + if (!$aResult['status']) { - $aResult['message'] = Dict::S('UI:CurrentObjectLockExpired'); - $aResult['popup_message'] = Dict::S('UI:CurrentObjectLockExpired_Explanation'); + if ($aResult['operation'] == 'lost') + { + $sName = $aResult['owner']->GetName(); + if ($aResult['owner']->Get('contactid') != 0) + { + $sName .= ' ('.$aResult['owner']->Get('contactid_friendlyname').')'; + } + $aResult['message'] = Dict::Format('UI:CurrentObjectIsLockedBy_User', $sName); + $aResult['popup_message'] = Dict::Format('UI:CurrentObjectIsLockedBy_User_Explanation', $sName); + } + else + { + if ($aResult['operation'] == 'expired') + { + $aResult['message'] = Dict::S('UI:CurrentObjectLockExpired'); + $aResult['popup_message'] = Dict::S('UI:CurrentObjectLockExpired_Explanation'); + } + } } - } - $oPage->add(json_encode($aResult)); - break; - + $oPage->add(json_encode($aResult)); + break; + case 'watchdog': - $oPage->add('ok'); // Better for debugging... - break; - + $oPage->add('ok'); // Better for debugging... + break; + case 'cke_img_upload': // Image uploaded via CKEditor $aResult = array( - 'uploaded' => 0, - 'fileName' => '', - 'url' => '', - 'icon' => '', - 'msg' => '', - 'att_id' => 0, - 'preview' => 'false', + 'uploaded' => 0, + 'fileName' => '', + 'url' => '', + 'icon' => '', + 'msg' => '', + 'att_id' => 0, + 'preview' => 'false', ); - + $sObjClass = stripslashes(utils::ReadParam('obj_class', '', false, 'class')); $sTempId = utils::ReadParam('temp_id', ''); if (empty($sObjClass)) @@ -2333,9 +2337,9 @@ EOF $oAttachment->Set('item_class', $sObjClass); $oAttachment->SetDefaultOrgId(); $oAttachment->Set('contents', $oDoc); - $oAttachment->Set('secret', sprintf ('%06x', mt_rand(0, 0xFFFFFF))); // something not easy to guess + $oAttachment->Set('secret', sprintf('%06x', mt_rand(0, 0xFFFFFF))); // something not easy to guess $iAttId = $oAttachment->DBInsert(); - + $aResult['uploaded'] = 1; $aResult['msg'] = htmlentities($oDoc->GetFileName(), ENT_QUOTES, 'UTF-8'); $aResult['fileName'] = $oDoc->GetFileName(); @@ -2350,15 +2354,14 @@ EOF { $aResult['error'] = $oDoc->GetFileName().' is not a valid image format.'; } - } - catch (FileUploadException $e) + } catch (FileUploadException $e) { $aResult['error'] = $e->GetMessage(); } } $oPage->add(json_encode($aResult)); break; - + case 'cke_upload_and_browse': $sTempId = utils::ReadParam('temp_id'); $sObjClass = utils::ReadParam('obj_class', '', false, 'class'); @@ -2375,32 +2378,31 @@ EOF $oAttachment->Set('item_class', $sObjClass); $oAttachment->SetDefaultOrgId(); $oAttachment->Set('contents', $oDoc); - $oAttachment->Set('secret', sprintf ('%06x', mt_rand(0, 0xFFFFFF))); // something not easy to guess + $oAttachment->Set('secret', sprintf('%06x', mt_rand(0, 0xFFFFFF))); // something not easy to guess $iAttId = $oAttachment->DBInsert(); - + } - } - catch (FileUploadException $e) + } catch (FileUploadException $e) { // fail silently ?? - } + } // Fall though !! => browse - + case 'cke_browse': $oPage = new NiceWebPage(Dict::S('UI:BrowseInlineImages')); $oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/magnific-popup.css'); $oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.magnific-popup.min.js'); $sImgUrl = utils::GetAbsoluteUrlAppRoot().INLINEIMAGE_DOWNLOAD_URL; - + $sTempId = utils::ReadParam('temp_id'); $sClass = utils::ReadParam('obj_class', '', false, 'class'); $iObjectId = utils::ReadParam('obj_key', 0, false, 'integer'); $sCKEditorFuncNum = utils::ReadParam('CKEditorFuncNum', ''); - + $sPostUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?CKEditorFuncNum='.$sCKEditorFuncNum; - + $oPage->add_style( -<<add( -<<
$sUploadLegend @@ -2428,9 +2430,9 @@ EOF EOF ); - + $oPage->add_script( -<<add_ready_script( -<<'); $('#upload_form').submit(); @@ -2475,14 +2477,14 @@ EOF $sOQL = "SELECT InlineImage WHERE ((temp_id = :temp_id) OR (item_class = :obj_class AND item_id = :obj_id))"; $oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL), array(), array('temp_id' => $sTempId, 'obj_class' => $sClass, 'obj_id' => $iObjectId)); $oPage->add("
$sAvailableImagesLegend"); - + if ($oSet->Count() == 0) { $oPage->add("

$sNoInlineImage

"); } else { - while($oAttachment = $oSet->Fetch()) + while ($oAttachment = $oSet->Fetch()) { $oDoc = $oAttachment->Get('contents'); if ($oDoc->GetMainMimeType() == 'image') @@ -2495,8 +2497,8 @@ EOF } } $oPage->add("
"); - break; - + break; + case 'custom_fields_update': $oPage->SetContentType('application/json'); $sAttCode = utils::ReadParam('attcode', ''); @@ -2518,8 +2520,7 @@ EOF $aRenderRes = $oRenderer->Render($aRequestedFields); $aResult['form']['updated_fields'] = $aRenderRes; - } - catch (Exception $e) + } catch (Exception $e) { $aResult['error'] = $e->getMessage(); } @@ -2527,12 +2528,11 @@ EOF break; default: - $oPage->p("Invalid query."); + $oPage->p("Invalid query."); } $oPage->output(); -} -catch (Exception $e) +} catch (Exception $e) { // note: transform to cope with XSS attacks echo htmlentities($e->GetMessage(), ENT_QUOTES, 'utf-8'); diff --git a/pages/ajax.searchform.php b/pages/ajax.searchform.php index 712e8b1c8..92ea6071f 100644 --- a/pages/ajax.searchform.php +++ b/pages/ajax.searchform.php @@ -57,19 +57,9 @@ try $sListParams = stripslashes(utils::ReadParam('list_params', '{}', false, 'raw_data')); $aListParams = (array) json_decode($sListParams, true); - - $aPassFromExtraParamsToListParams = array( - 'currentId', - 'selection_mode', - 'selection_type',// In case of single selection, the root of the HTML identifiers used is suffixed with "_results" (at least in the external keys) - 'cssCount', - ); - foreach ($aPassFromExtraParamsToListParams as $passThroughKey) + foreach($aListParams as $key => $value) { - if (array_key_exists($passThroughKey, $aListParams)) - { - $aExtraParams[$passThroughKey] = $aListParams[$passThroughKey]; - } + $aExtraParams[$key] = $value; } if (array_key_exists('table_inner_id', $aListParams)) diff --git a/sources/application/search/searchform.class.inc.php b/sources/application/search/searchform.class.inc.php index 4c38f86ad..c4380e2a9 100644 --- a/sources/application/search/searchform.class.inc.php +++ b/sources/application/search/searchform.class.inc.php @@ -61,11 +61,15 @@ class SearchForm $sClassName = $oSet->GetFilter()->GetClass(); $aListParams = array(); + foreach($aExtraParams as $key => $value) + { + $aListParams[$key] = $value; + } + // Simple search form if (isset($aExtraParams['currentId'])) { $sSearchFormId = $aExtraParams['currentId']; - $aListParams['currentId'] = $aExtraParams['currentId']; } else { @@ -83,23 +87,13 @@ class SearchForm { $sRootClass = $sClassName; } - if (array_key_exists('selection_mode', $aExtraParams)) - { - $aListParams['selection_mode'] = $aExtraParams['selection_mode']; - } - if (array_key_exists('selection_type', $aExtraParams)) - { - $aListParams['selection_type'] = $aExtraParams['selection_type']; - } + $sJson = stripslashes(utils::ReadParam('json', '', false, 'raw_data')); if (!empty($sJson)) { $aListParams['json'] = json_decode($sJson, true); } - if (array_key_exists('cssCount', $aExtraParams)) - { - $aListParams['cssCount'] = $aExtraParams['cssCount']; - } + $aSubClasses = MetaModel::GetSubclasses($sRootClass); if (count($aSubClasses) > 0) @@ -139,15 +133,14 @@ class SearchForm { $aExtraParams['table_id'] = "search_form_result_{$sSearchFormId}"; } - $aListParams['table_id'] = $aExtraParams['table_id']; - if (array_key_exists('table_inner_id', $aExtraParams)) - { - $aListParams['table_inner_id'] = $aExtraParams['table_inner_id']; - } - else + if (!array_key_exists('table_inner_id', $aExtraParams)) { $aListParams['table_inner_id'] = uniqid('table_inner_id_'); } + if (array_key_exists('table_id2', $aExtraParams)) + { + $aListParams['table_id'] = $aExtraParams['table_id2']; + } $aSearchParams = array( 'criterion_outer_selector' => "#fs_{$sSearchFormId}_criterion_outer", 'result_list_outer_selector' => "#{$aExtraParams['table_id']}", @@ -162,13 +155,13 @@ class SearchForm ), ); - if (isset($aSearchParams['list_params']['table_inner_id'])) - { - $aSearchParams['data_config_list_selector'] = '#'.$aSearchParams['list_params']['table_inner_id']; - } - elseif (isset($aSearchParams['list_params']['table_id'])) - { - $aSearchParams['data_config_list_selector'] = '#'.$aSearchParams['list_params']['table_id']; + if (isset($aSearchParams['list_params']['table_id'])) + { + $aSearchParams['data_config_list_selector'] = '#'.$aSearchParams['list_params']['table_id']; + } + elseif (isset($aSearchParams['list_params']['table_inner_id'])) + { + $aSearchParams['data_config_list_selector'] = '#'.$aSearchParams['list_params']['table_inner_id']; } else {