From c149ec8e2c1d7e1cac629b175df83ff2e90d351d Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Wed, 14 Dec 2011 17:44:06 +0000 Subject: [PATCH] #485 Improved the end-user experience with Excel and the web queries (added a phrasebook) + link to test the OQL attributes (query phrasebook or email actions, etc.) including the handlink of query arguments) + fixed wrong prototypes for a few implementations of GetBareProperties() SVN:1.2[1719] --- application/application.inc.php | 1 + application/cmdbabstract.class.inc.php | 17 ++- application/query.class.inc.php | 105 ++++++++++++++++++ core/attributedef.class.inc.php | 1 + core/config.class.inc.php | 1 + core/dbobjectsearch.class.php | 13 +++ core/event.class.inc.php | 2 +- core/expression.class.inc.php | 13 +-- dictionaries/dictionary.itop.ui.php | 26 ++++- dictionaries/fr.dictionary.itop.ui.php | 14 +++ .../model.itop-config-mgmt.php | 2 +- .../model.itop-welcome-itil.php | 1 + pages/run_query.php | 65 ++++++++--- synchro/synchrodatasource.class.inc.php | 4 +- webservices/export.php | 34 +++++- 15 files changed, 262 insertions(+), 37 deletions(-) create mode 100644 application/query.class.inc.php diff --git a/application/application.inc.php b/application/application.inc.php index 6a5ddaabd..890d71794 100644 --- a/application/application.inc.php +++ b/application/application.inc.php @@ -29,6 +29,7 @@ require_once(APPROOT.'/application/displayblock.class.inc.php'); require_once(APPROOT.'/application/sqlblock.class.inc.php'); require_once(APPROOT.'/application/audit.category.class.inc.php'); require_once(APPROOT.'/application/audit.rule.class.inc.php'); +require_once(APPROOT.'/application/query.class.inc.php'); //require_once(APPROOT.'/application/menunode.class.inc.php'); require_once(APPROOT.'/application/utils.inc.php'); diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 5dd49eaec..5d2c85381 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -1649,6 +1649,7 @@ EOF $sHTMLValue = " {$sValidationField}"; break; + case 'OQLExpression': case 'Text': $aEventsList[] ='validate'; $aEventsList[] ='keyup'; @@ -1670,7 +1671,21 @@ EOF { $sStyle = 'style="'.implode('; ', $aStyles).'"'; } - $sHTMLValue = "
{$sValidationField}
"; + if ($oAttDef->GetEditClass() == 'OQLExpression') + { + $sTestResId = 'query_res_'.$sFieldPrefix.$sAttCode.$sNameSuffix; //$oPage->GetUniqueId(); + $sBaseUrl = utils::GetAbsoluteUrlAppRoot().'pages/run_query.php?expression='; + $sInitialUrl = $sBaseUrl.urlencode($sEditValue); + $sAdditionalStuff = "".Dict::S('UI:Edit:TestQuery').""; + $oPage->add_ready_script("$('#$iId').bind('change keyup', function(evt, sFormId) { $('#$sTestResId').attr('href', '$sBaseUrl'+encodeURIComponent($(this).val())); } );"); + } + else + { + $sAdditionalStuff = ""; + } + // Ok, the text area is drawn here + $sHTMLValue = "
$sAdditionalStuff{$sValidationField}
"; + break; case 'CaseLog': diff --git a/application/query.class.inc.php b/application/query.class.inc.php new file mode 100644 index 000000000..cf7bc1af3 --- /dev/null +++ b/application/query.class.inc.php @@ -0,0 +1,105 @@ + + * @author Romain Quetiez + * @author Denis Flaven + * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL + */ + +abstract class Query extends cmdbAbstractObject +{ + public static function Init() + { + $aParams = array + ( + "category" => "core/cmdb,view_in_gui", + "key_type" => "autoincrement", + "name_attcode" => "name", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_query", + "db_key_field" => "id", + "db_finalclass_field" => "realclass", + "display_template" => "", + ); + MetaModel::Init_Params($aParams); + //MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeString("name", array("allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeText("description", array("allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + + // Display lists + MetaModel::Init_SetZListItems('details', array('name', 'description')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list + // Search criteria +// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form +// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form + } +} + +class QueryOQL extends Query +{ + public static function Init() + { + $aParams = array + ( + "category" => "core/cmdb,view_in_gui", + "key_type" => "autoincrement", + "name_attcode" => "name", + "state_attcode" => "", + "reconc_keys" => array(), + "db_table" => "priv_query_oql", + "db_key_field" => "id", + "db_finalclass_field" => "", + "display_template" => "", + ); + MetaModel::Init_Params($aParams); + MetaModel::Init_InheritAttributes(); + MetaModel::Init_AddAttribute(new AttributeOQL("oql", array("allowed_values"=>null, "sql"=>"oql", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array()))); + + // Display lists + MetaModel::Init_SetZListItems('details', array('name', 'description', 'oql')); // Attributes to be displayed for the complete details + MetaModel::Init_SetZListItems('list', array('description')); // Attributes to be displayed for a list + // Search criteria +// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form +// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form + } + + function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array()) + { + parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams); + + if (!$bEditMode) + { + $sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?format=spreadsheet&login_mode=basic&query='.$this->GetKey(); + $sOql = $this->Get('oql'); + $oSearch = DBObjectSearch::FromOQL($sOql); + $aParameters = $oSearch->GetQueryParams(); + foreach($aParameters as $sParam => $val) + { + $sUrl .= '&arg_'.$sParam.'=["'.$sParam.'"]'; + } + $oPage->p(Dict::S('UI:Query:UrlForExcel').':
'); + } + } +} + +?> diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index acb9dffcb..ea73477b3 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -1880,6 +1880,7 @@ class AttributeIPAddress extends AttributeString */ class AttributeOQL extends AttributeText { + public function GetEditClass() {return "OQLExpression";} } /** diff --git a/core/config.class.inc.php b/core/config.class.inc.php index d9cd5c824..c3731ab71 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -562,6 +562,7 @@ class Config 'application/menunode.class.inc.php', 'application/user.preferences.class.inc.php', 'application/audit.rule.class.inc.php', + 'application/query.class.inc.php', // Romain - That's dirty, because those classes are in fact part of the core // but I needed those classes to be derived from cmdbAbstractObject // (to be managed via the GUI) and this class in not really known from diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php index 5981de40d..35a19c00d 100644 --- a/core/dbobjectsearch.class.php +++ b/core/dbobjectsearch.class.php @@ -737,11 +737,24 @@ class DBObjectSearch { return $this->m_aRelatedTo; } + + public function SetInternalParams($aParams) + { + return $this->m_aParams = $aParams; + } + public function GetInternalParams() { return $this->m_aParams; } + public function GetQueryParams() + { + $aParams = array(); + $this->m_oSearchCondition->Render($aParams, true); + return $aParams; + } + public function ListConstantFields() { return $this->m_oSearchCondition->ListConstantFields(); diff --git a/core/event.class.inc.php b/core/event.class.inc.php index 52a51bbcd..173e635d6 100644 --- a/core/event.class.inc.php +++ b/core/event.class.inc.php @@ -103,7 +103,7 @@ class Event extends DBObject implements iDisplay $this->DisplayBareProperties($oPage, $bEditMode); } - function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $aExtraParams = array()) + function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array()) { if ($bEditMode) return; // Not editable diff --git a/core/expression.class.inc.php b/core/expression.class.inc.php index e7df0c033..ee07e2565 100644 --- a/core/expression.class.inc.php +++ b/core/expression.class.inc.php @@ -282,16 +282,7 @@ class UnaryExpression extends Expression // recursive rendering public function Render(&$aArgs = null, $bRetrofitParams = false) { - if ($bRetrofitParams) - { - $iParamIndex = count($aArgs) + 1; // 1-based indexation - $aArgs['param'.$iParamIndex] = $this->m_value; - return ':param'.$iParamIndex; - } - else - { - return CMDBSource::Quote($this->m_value); - } + return CMDBSource::Quote($this->m_value); } public function GetUnresolvedFields($sAlias, &$aUnresolved) @@ -483,7 +474,7 @@ class VariableExpression extends UnaryExpression } elseif ($bRetrofitParams) { - //$aArgs[$this->m_sName] = null; + $aArgs[$this->m_sName] = null; return ':'.$this->m_sName; } else diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php index d22890747..2411d7049 100644 --- a/dictionaries/dictionary.itop.ui.php +++ b/dictionaries/dictionary.itop.ui.php @@ -76,6 +76,24 @@ Dict::Add('EN US', 'English', 'English', array( 'Class:AuditRule/Attribute:category_name+' => 'Name of the category for this rule', )); +// +// Class: QueryOQL +// + +Dict::Add('EN US', 'English', 'English', array( + 'Class:Query' => 'Query', + 'Class:Query+' => 'A query is a data set defined in a dynamic way', + 'Class:Query/Attribute:name' => 'Name', + 'Class:Query/Attribute:name+' => 'Identifies the query', + 'Class:Query/Attribute:description' => 'Description', + 'Class:Query/Attribute:description+' => 'Long description for the query (purpose, usage, etc.)', + + 'Class:QueryOQL' => 'OQL Query', + 'Class:QueryOQL+' => 'A query based on the Object Query Language', + 'Class:QueryOQL/Attribute:oql' => 'Expression', + 'Class:QueryOQL/Attribute:oql+' => 'OQL Expression', +)); + ////////////////////////////////////////////////////////////////////// // Classes in 'addon/userrights' ////////////////////////////////////////////////////////////////////// @@ -548,7 +566,7 @@ Dict::Add('EN US', 'English', 'English', array( 'UI:RunQuery:DevelopedQuery' => 'Redevelopped query expression: ', 'UI:RunQuery:SerializedFilter' => 'Serialized filter: ', 'UI:RunQuery:Error' => 'An error occured while running the query: %1$s', - + 'UI:Query:UrlForExcel' => 'URL to use for MS-Excel web queries', 'UI:Schema:Title' => 'iTop objects schema', 'UI:Schema:CategoryMenuItem' => 'Category %1$s', 'UI:Schema:Relationships' => 'Relationships', @@ -608,8 +626,8 @@ Dict::Add('EN US', 'English', 'English', array( 'UI:Schema:LifeCycleAttributeMustChange' => 'Must change', 'UI:Schema:LifeCycleAttributeMustPrompt' => 'User will be prompted to change the value', 'UI:Schema:LifeCycleEmptyList' => 'empty list', - 'UI:LinksWidget:Autocomplete+' => 'Type the first 3 characters...', + 'UI:Edit:TestQuery' => 'Test query', 'UI:Combo:SelectValue' => '--- select a value ---', 'UI:Label:SelectedObjects' => 'Selected objects: ', 'UI:Label:AvailableObjects' => 'Available objects: ', @@ -622,7 +640,6 @@ Dict::Add('EN US', 'English', 'English', array( 'UI:RemoveLinkedObjectsOf_Class' => 'Remove selected objects', 'UI:Message:EmptyList:UseAdd' => 'The list is empty, use the "Add..." button to add elements.', 'UI:Message:EmptyList:UseSearchForm' => 'Use the search form above to search for objects to be added.', - 'UI:Wizard:FinalStepTitle' => 'Final step: confirmation', 'UI:Title:DeletionOf_Object' => 'Deletion of %1$s', 'UI:Title:BulkDeletionOf_Count_ObjectsOf_Class' => 'Bulk deletion of %1$d objects of class %2$s', @@ -825,6 +842,9 @@ When associated with a trigger, each action is given an "order" number, specifyi 'Menu:RunQueriesMenu' => 'Run Queries', 'Menu:RunQueriesMenu+' => 'Run any query', + 'Menu:QueryMenu' => 'Query phrasebook', + 'Menu:QueryMenu+' => 'Query phrasebook', + 'Menu:DataAdministration' => 'Data administration', 'Menu:DataAdministration+' => 'Data administration', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 1a9edff89..33ed6caff 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -50,6 +50,16 @@ Dict::Add('FR FR', 'French', 'Français', array( 'Class:AuditCategory/Attribute:definition_set+' => 'Expression OQL qui défini le périmètre d\'application de l\'audit', 'Class:AuditCategory/Attribute:rules_list' => 'Règles d\'audit', 'Class:AuditCategory/Attribute:rules_list+' => 'Règles d\'audit pour cette catégorie', + 'Class:Query' => 'Requête', + 'Class:Query+' => 'Une requête définit un ensemble d\'information de manière dynamique', + 'Class:Query/Attribute:name' => 'Nom', + 'Class:Query/Attribute:name+' => 'Identification de la requête', + 'Class:Query/Attribute:description' => 'Description', + 'Class:Query/Attribute:description+' => 'Description complète (finalité, utilisations, public)', + 'Class:QueryOQL' => 'Requête OQL', + 'Class:QueryOQL+' => 'Une requête écrite dans le langage "Object Query Language"', + 'Class:QueryOQL/Attribute:oql' => 'Expression', + 'Class:QueryOQL/Attribute:oql+' => 'Expression OQL', 'Class:URP_Profiles' => 'Profil', 'Class:URP_Profiles+' => 'Profil utilisateur', 'Class:URP_Profiles/Attribute:name' => 'Nom', @@ -431,6 +441,7 @@ Dict::Add('FR FR', 'French', 'Français', array( 'UI:RunQuery:DevelopedQuery' => 'Requête OQL décompilée : ', 'UI:RunQuery:SerializedFilter' => 'Version sérialisée : ', 'UI:RunQuery:Error' => 'Une erreur s\'est produite durant l\'exécution de la requête : %1$s', + 'UI:Query:UrlForExcel' => 'Lien à copier-coller dans Excel, pour déclarer une source de données à partir du web', 'UI:Schema:Title' => 'Modèle de données iTop', 'UI:Schema:CategoryMenuItem' => 'Catégorie %1$s', 'UI:Schema:Relationships' => 'Relations', @@ -490,6 +501,7 @@ Dict::Add('FR FR', 'French', 'Français', array( 'UI:Schema:LifeCycleAttributeMustPrompt' => 'L\'utilisateur se verra proposer de changer la valeur', 'UI:Schema:LifeCycleEmptyList' => 'liste vide', 'UI:LinksWidget:Autocomplete+' => 'Tapez les 3 premiers caractères...', + 'UI:Edit:TestQuery' => 'Tester le requête', 'UI:Combo:SelectValue' => '--- choisissez une valeur ---', 'UI:Label:SelectedObjects' => 'Objets sélectionnés: ', 'UI:Label:AvailableObjects' => 'Objets disponibles: ', @@ -684,6 +696,8 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé 'Menu:Notifications:Title' => 'Catégories d\'audit', 'Menu:RunQueriesMenu' => 'Requêtes OQL', 'Menu:RunQueriesMenu+' => 'Executer une requête OQL', + 'Menu:QueryMenu' => 'Livre des requêtes', + 'Menu:QueryMenu+' => 'Livre des requêtes', 'Menu:DataAdministration' => 'Administration des données', 'Menu:DataAdministration+' => 'Administration des données', 'Menu:UniversalSearchMenu' => 'Recherche Universelle', diff --git a/modules/itop-config-mgmt-1.0.0/model.itop-config-mgmt.php b/modules/itop-config-mgmt-1.0.0/model.itop-config-mgmt.php index 9931d94c3..376bf6e92 100644 --- a/modules/itop-config-mgmt-1.0.0/model.itop-config-mgmt.php +++ b/modules/itop-config-mgmt-1.0.0/model.itop-config-mgmt.php @@ -365,7 +365,7 @@ class FileDoc extends Document $oPage->add($this->DisplayDocumentInline($oPage, 'contents')); $oPage->SetCurrentTab(Dict::S('UI:PropertiesTab')); } - parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix); + parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams); } } diff --git a/modules/itop-welcome-itil/model.itop-welcome-itil.php b/modules/itop-welcome-itil/model.itop-welcome-itil.php index 3e177e5e9..f15cf6896 100644 --- a/modules/itop-welcome-itil/model.itop-welcome-itil.php +++ b/modules/itop-welcome-itil/model.itop-welcome-itil.php @@ -56,6 +56,7 @@ class ItopWelcome extends ModuleHandlerAPI new TemplateMenuNode('NotificationsMenu', APPROOT.'application/templates/notifications_menu.html', $oAdminMenu->GetIndex(), 3 /* fRank */); new OQLMenuNode('AuditCategories', 'SELECT AuditCategory', $oAdminMenu->GetIndex(), 4 /* fRank */); new WebPageMenuNode('RunQueriesMenu', utils::GetAbsoluteUrlAppRoot().'pages/run_query.php', $oAdminMenu->GetIndex(), 8 /* fRank */); + new OQLMenuNode('QueryMenu', 'SELECT Query', $oAdminMenu->GetIndex(), 8.5 /* fRank */); new WebPageMenuNode('ExportMenu', utils::GetAbsoluteUrlAppRoot().'webservices/export.php', $oAdminMenu->GetIndex(), 9 /* fRank */); new WebPageMenuNode('DataModelMenu', utils::GetAbsoluteUrlAppRoot().'pages/schema.php', $oAdminMenu->GetIndex(), 10 /* fRank */); new WebPageMenuNode('UniversalSearchMenu', utils::GetAbsoluteUrlAppRoot().'pages/UniversalSearch.php', $oAdminMenu->GetIndex(), 11 /* fRank */); diff --git a/pages/run_query.php b/pages/run_query.php index 6909eaed2..a256cd39a 100644 --- a/pages/run_query.php +++ b/pages/run_query.php @@ -120,30 +120,63 @@ try // leave $sExpression as is } - $oP->add("
\n"); - $oP->add(Dict::S('UI:RunQuery:ExpressionToEvaluate')."
\n"); - $oP->add("\n"); - $oP->add("\n"); - $oP->add($oAppContext->GetForForm()); - $oP->add("
\n"); + $oFilter = null; + $aArgs = array(); if (!empty($sExpression)) { $oFilter = DBObjectSearch::FromOQL($sExpression); if ($oFilter) { - $oP->add("

Query results

\n"); - - $oResultBlock = new DisplayBlock($oFilter, 'list', false); - $oResultBlock->Display($oP, 'runquery'); - - $oP->p(''); - $oP->StartCollapsibleSection(Dict::S('UI:RunQuery:MoreInfo'), false); - $oP->p(Dict::S('UI:RunQuery:DevelopedQuery').$oFilter->ToOQL()); - $oP->p(Dict::S('UI:RunQuery:SerializedFilter').$oFilter->serialize()); - $oP->EndCollapsibleSection(); + $aArgs = array(); + foreach($oFilter->GetQueryParams() as $sParam => $foo) + { + $value = utils::ReadParam('arg_'.$sParam, null, true, 'raw_data'); + if (!is_null($value)) + { + $aArgs[$sParam] = $value; + } + else + { + $aArgs[$sParam] = ''; + } + } + $oFilter->SetInternalParams($aArgs); } } + + $oP->add("
\n"); + $oP->add(Dict::S('UI:RunQuery:ExpressionToEvaluate')."
\n"); + $oP->add("\n"); + + if (count($aArgs) > 0) + { + $oP->add("
\n"); + $oP->add("

Query arguments

\n"); + foreach($aArgs as $sParam => $sValue) + { + $oP->p("$sParam: \n"); + } + $oP->add("
\n"); + } + + $oP->add("\n"); + $oP->add($oAppContext->GetForForm()); + $oP->add("
\n"); + + if ($oFilter) + { + $oP->add("

Query results

\n"); + + $oResultBlock = new DisplayBlock($oFilter, 'list', false); + $oResultBlock->Display($oP, 'runquery'); + + $oP->p(''); + $oP->StartCollapsibleSection(Dict::S('UI:RunQuery:MoreInfo'), false); + $oP->p(Dict::S('UI:RunQuery:DevelopedQuery').$oFilter->ToOQL()); + $oP->p(Dict::S('UI:RunQuery:SerializedFilter').$oFilter->serialize()); + $oP->EndCollapsibleSection(); + } } catch(CoreException $e) { diff --git a/synchro/synchrodatasource.class.inc.php b/synchro/synchrodatasource.class.inc.php index f83a6f6b2..5ba253b08 100644 --- a/synchro/synchrodatasource.class.inc.php +++ b/synchro/synchrodatasource.class.inc.php @@ -2264,7 +2264,7 @@ class SynchroReplica extends DBObject implements iDisplay $this->DisplayBareProperties($oPage, $bEditMode); } - function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $aExtraParams = array()) + function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array()) { if ($bEditMode) return; // Not editable @@ -2286,7 +2286,7 @@ class SynchroReplica extends DBObject implements iDisplay { $oPage->add('
'); $oPage->add(''.Dict::Format('Core:SynchroReplica:TargetObject', $oDestObj->GetHyperlink()).''); - $oDestObj->DisplayBareProperties($oPage, false, $aExtraParams); + $oDestObj->DisplayBareProperties($oPage, false, $sPrefix, $aExtraParams); $oPage->add('
'); } $oPage->add(''); diff --git a/webservices/export.php b/webservices/export.php index b9c59e6b6..bc09cf760 100644 --- a/webservices/export.php +++ b/webservices/export.php @@ -55,6 +55,22 @@ $currentOrganization = utils::ReadParam('org_id', ''); // Main program $sExpression = utils::ReadParam('expression', '', true /* Allow CLI */, 'raw_data'); +if (strlen($sExpression) == 0) +{ + $sQueryId = trim(utils::ReadParam('query', '', true /* Allow CLI */, 'raw_data')); + if (strlen($sQueryId) > 0) + { + $oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId)); + $oQueries = new DBObjectSet($oSearch); + if ($oQueries->Count() > 0) + { + $oQuery = $oQueries->Fetch(); + $sExpression = $oQuery->Get('oql'); + } + } +} + + $sFormat = strtolower(utils::ReadParam('format', 'html')); $sFields = utils::ReadParam('fields', '', true, 'raw_data'); // CSV field list (allows to specify link set attributes, still not taken into account for XML export) @@ -76,9 +92,21 @@ if (!empty($sExpression)) try { $oFilter = DBObjectSearch::FromOQL($sExpression); + + $aArgs = array(); + foreach($oFilter->GetQueryParams() as $sParam => $foo) + { + $value = utils::ReadParam('arg_'.$sParam, null, true, 'raw_data'); + if (!is_null($value)) + { + $aArgs[$sParam] = $value; + } + } + $oFilter->SetInternalParams($aArgs); + if ($oFilter) { - $oSet = new CMDBObjectSet($oFilter); + $oSet = new CMDBObjectSet($oFilter, array(), $aArgs); switch($sFormat) { case 'html': @@ -164,7 +192,9 @@ if (!$oP) $oP->p("General purpose export page."); $oP->p("Parameters:"); $oP->p("
  • expression: an OQL expression (URL encoded if needed)
  • -
  • format: (optional, default is html) the desired output format. Can be one of 'html', 'csv' or 'xml'
  • +
  • query: (alternative to 'expression') the id of an entry from the query phrasebook
  • +
  • arg_xxx: (needed if the query has parameters) the value of the parameter 'xxx'
  • +
  • format: (optional, default is html) the desired output format. Can be one of 'html', 'spreadsheet', 'csv' or 'xml'
  • fields: (optional, no effect on XML format) list of fields (attribute codes) separated by a coma
"); }