diff --git a/datamodels/1.x/itop-request-mgmt-1.0.0/main.itop-request-mgmt.php b/datamodels/1.x/itop-request-mgmt-1.0.0/main.itop-request-mgmt.php index f1ac92b4b..5b72fe1f9 100644 --- a/datamodels/1.x/itop-request-mgmt-1.0.0/main.itop-request-mgmt.php +++ b/datamodels/1.x/itop-request-mgmt-1.0.0/main.itop-request-mgmt.php @@ -14,4 +14,19 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +define('PORTAL_SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN SLA AS sla ON sla.service_id=s.id JOIN lnkContractToSLA AS ln ON ln.sla_id=sla.id JOIN CustomerContract AS cc ON ln.contract_id=cc.id WHERE cc.org_id = :org_id'); +define('PORTAL_SERVICE_SUBCATEGORY_QUERY', 'SELECT ServiceSubcategory WHERE service_id = :svc_id'); + +define('PORTAL_VALIDATE_SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN SLA AS sla ON sla.service_id=s.id JOIN lnkContractToSLA AS ln ON ln.sla_id=sla.id JOIN CustomerContract AS cc ON ln.contract_id=cc.id WHERE cc.org_id = :org_id AND s.id = :id'); +define('PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY', 'SELECT ServiceSubcategory AS Sub JOIN Service AS Svc ON Sub.service_id = Svc.id WHERE Sub.id=:id'); + +define('PORTAL_ALL_PARAMS', 'from_service_id,org_id,caller_id,service_id,servicesubcategory_id,title,description,impact,urgency,workgroup_id,moreinfo,caller_id,start_date,end_date,duration,impact_duration'); + +define('PORTAL_ATTCODE_LOG', 'ticket_log'); +define('PORTAL_ATTCODE_COMMENT', 'user_commment'); +define('PORTAL_REQUEST_FORM_ATTRIBUTES', 'title,description,impact,urgency,workgroup_id'); + +define('PORTAL_ATTCODE_TYPE', ''); // optional if the type has to be set +define('PORTAL_SET_TYPE_FROM', ''); // The attribute to get the type from (Subcategory) + ?> diff --git a/datamodels/2.x/itop-request-mgmt-itil/main.itop-request-mgmt-itil.php b/datamodels/2.x/itop-request-mgmt-itil/main.itop-request-mgmt-itil.php index 19b95387b..74b877e65 100755 --- a/datamodels/2.x/itop-request-mgmt-itil/main.itop-request-mgmt-itil.php +++ b/datamodels/2.x/itop-request-mgmt-itil/main.itop-request-mgmt-itil.php @@ -14,7 +14,19 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +define('PORTAL_SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id'); +define('PORTAL_SERVICE_SUBCATEGORY_QUERY', 'SELECT ServiceSubcategory WHERE service_id = :svc_id'); +define('PORTAL_VALIDATE_SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.id = :id'); +define('PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY', 'SELECT ServiceSubcategory AS Sub JOIN Service AS Svc ON Sub.service_id = Svc.id WHERE Sub.id=:id'); +define('PORTAL_ALL_PARAMS', 'from_service_id,org_id,caller_id,service_id,servicesubcategory_id,title,description,impact,emergency,moreinfo,caller_id,start_date,end_date,duration,impact_duration'); + +define('PORTAL_ATTCODE_LOG', 'public_log'); +define('PORTAL_ATTCODE_COMMENT', 'user_comment'); +define('PORTAL_REQUEST_FORM_ATTRIBUTES', 'title,description,impact,emergency'); + +define('PORTAL_ATTCODE_TYPE', ''); // optional if the type has to be set +define('PORTAL_SET_TYPE_FROM', ''); // The attribute to get the type from (Subcategory) ?> diff --git a/datamodels/2.x/itop-request-mgmt-itil/module.itop-request-mgmt-itil.php b/datamodels/2.x/itop-request-mgmt-itil/module.itop-request-mgmt-itil.php index 421400752..3dec1d6dd 100755 --- a/datamodels/2.x/itop-request-mgmt-itil/module.itop-request-mgmt-itil.php +++ b/datamodels/2.x/itop-request-mgmt-itil/module.itop-request-mgmt-itil.php @@ -23,6 +23,7 @@ SetupWebPage::AddModule( // 'datamodel' => array( 'model.itop-request-mgmt-itil.php', + 'main.itop-request-mgmt-itil.php', ), 'data.struct' => array( diff --git a/datamodels/2.x/itop-request-mgmt/main.itop-request-mgmt.php b/datamodels/2.x/itop-request-mgmt/main.itop-request-mgmt.php index 5eeb75d3f..d4661878f 100755 --- a/datamodels/2.x/itop-request-mgmt/main.itop-request-mgmt.php +++ b/datamodels/2.x/itop-request-mgmt/main.itop-request-mgmt.php @@ -14,6 +14,19 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +define('PORTAL_SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id'); +define('PORTAL_SERVICE_SUBCATEGORY_QUERY', 'SELECT ServiceSubcategory WHERE service_id = :svc_id'); +define('PORTAL_VALIDATE_SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.id = :id'); +define('PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY', 'SELECT ServiceSubcategory AS Sub JOIN Service AS Svc ON Sub.service_id = Svc.id WHERE Sub.id=:id'); + +define('PORTAL_ALL_PARAMS', 'from_service_id,org_id,caller_id,service_id,servicesubcategory_id,title,description,impact,emergency,moreinfo,caller_id,start_date,end_date,duration,impact_duration'); + +define('PORTAL_ATTCODE_LOG', 'public_log'); +define('PORTAL_ATTCODE_COMMENT', 'user_comment'); +define('PORTAL_REQUEST_FORM_ATTRIBUTES', 'title,description,impact,emergency'); + +define('PORTAL_ATTCODE_TYPE', 'request_type'); // optional if the type has to be set +define('PORTAL_SET_TYPE_FROM', 'request_type'); // The attribute to get the type from (Subcategory) ?> diff --git a/datamodels/2.x/itop-request-mgmt/module.itop-request-mgmt.php b/datamodels/2.x/itop-request-mgmt/module.itop-request-mgmt.php index 0b3ac7822..9c1a8ce26 100755 --- a/datamodels/2.x/itop-request-mgmt/module.itop-request-mgmt.php +++ b/datamodels/2.x/itop-request-mgmt/module.itop-request-mgmt.php @@ -23,6 +23,7 @@ SetupWebPage::AddModule( // 'datamodel' => array( 'model.itop-request-mgmt.php', + 'main.itop-request-mgmt.php', ), 'data.struct' => array( diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php index 2201e0b5b..36818b593 100644 --- a/dictionaries/dictionary.itop.ui.php +++ b/dictionaries/dictionary.itop.ui.php @@ -933,6 +933,7 @@ When associated with a trigger, each action is given an "order" number, specifyi 'UI:ElementsDisplayed' => 'Filtering', 'Portal:Title' => 'iTop user portal', + 'Portal:NoRequestMgmt' => 'Dear %1$s, you have been redirected to this page because your account is configured with the profile \'Portal user\'. Unfortunately, iTop has not been installed with the feature \'Request Management\'. Please contact your administrator.', 'Portal:Refresh' => 'Refresh', 'Portal:Back' => 'Back', 'Portal:WelcomeUserOrg' => 'Welcome %1$s, from %2$s', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index ecfbed56b..0e60616bd 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -778,6 +778,7 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé 'UI:ElementsDisplayed' => 'Filtrage', 'UI:OperationCancelled' => 'Opération Annulée', 'Portal:Title' => 'Portail utilisateur iTop', + 'Portal:NoRequestMgmt' => 'Chèr(e) %1$s, vous avez été redirigé(e) vers cette page car votre compte utilisateur est configuré avec le profil \'Utilisateur du Portail\'. Malheureusement, iTop n\'a pas été installé avec le module de \'Gestion des Demandes\'. Merci de contacter votre administrateur iTop.', 'Portal:Refresh' => 'Rafraîchir', 'Portal:Back' => 'Retour', 'Portal:WelcomeUserOrg' => 'Bienvenue %1$s (%2$s)', diff --git a/portal/index.php b/portal/index.php index efcaf7eb0..62ab4d48c 100644 --- a/portal/index.php +++ b/portal/index.php @@ -1,881 +1,880 @@ - - * @author Romain Quetiez - * @author Denis Flaven - * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL - */ -require_once('../approot.inc.php'); -require_once(APPROOT.'/application/application.inc.php'); -require_once(APPROOT.'/application/nicewebpage.class.inc.php'); -require_once(APPROOT.'/application/wizardhelper.class.inc.php'); - - - -define('SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN SLA AS sla ON sla.service_id=s.id JOIN lnkContractToSLA AS ln ON ln.sla_id=sla.id JOIN CustomerContract AS cc ON ln.contract_id=cc.id WHERE cc.org_id = :org_id'); -define('SERVICE_SUBCATEGORY_QUERY', 'SELECT ServiceSubcategory WHERE service_id = :svc_id'); - -define('VALIDATE_SERVICECATEGORY_QUERY', 'SELECT Service AS s JOIN SLA AS sla ON sla.service_id=s.id JOIN lnkContractToSLA AS ln ON ln.sla_id=sla.id JOIN CustomerContract AS cc ON ln.contract_id=cc.id WHERE cc.org_id = :org_id AND s.id = :id'); -define('VALIDATE_SERVICESUBCATEGORY_QUERY', 'SELECT ServiceSubcategory AS Sub JOIN Service AS Svc ON Sub.service_id = Svc.id WHERE Sub.id=:id'); - -define('ALL_PARAMS', 'from_service_id,org_id,caller_id,service_id,servicesubcategory_id,title,description,impact,urgency,workgroup_id,moreinfo,caller_id,start_date,end_date,duration,impact_duration'); - - - -/** - * Displays the portal main menu - * @param WebPage $oP The current web page - * @return void - */ -function DisplayMainMenu(WebPage $oP) -{ - $oP->AddMenuButton('showongoing', 'Portal:ShowOngoing', '../portal/index.php?operation=show_ongoing'); - $oP->AddMenuButton('newrequest', 'Portal:CreateNewRequest', '../portal/index.php?operation=create_request'); - $oP->AddMenuButton('showclosed', 'Portal:ShowClosed', '../portal/index.php?operation=show_closed'); - if (UserRights::CanChangePassword()) - { - $oP->AddMenuButton('change_pwd', 'Portal:ChangeMyPassword', '../portal/index.php?loginop=change_pwd'); - } -} - -/** - * Displays the current tickets - * @param WebPage $oP The current web page - * @return void - */ -function ShowOngoingTickets(WebPage $oP) -{ - $oP->add("
\n"); - $oP->add("

".Dict::S('Portal:OpenRequests')."

\n"); - ListOpenRequests($oP); - $oP->add("
\n"); - - $oP->add("
\n"); - $oP->add("

".Dict::S('Portal:ResolvedRequests')."

\n"); - ListResolvedRequests($oP); - $oP->add("
\n"); -} - -/** - * Displays the closed tickets - * @param WebPage $oP The current web page - * @return void - */ -function ShowClosedTickets(WebPage $oP) -{ - $oP->add("
\n"); - //$oP->add("

".Dict::S('Portal:ListClosedTickets')."

\n"); - ListClosedTickets($oP); - $oP->add("
\n"); -} - -/** - * Displays the form to select a Service Category Id (among the valid ones for the specified user Organization) - * @param WebPage $oP Web page for the form output - * @param Organization $oUserOrg The organization of the current user - * @return void - */ -function SelectServiceCategory($oP, $oUserOrg) -{ - $aParameters = $oP->ReadAllParams(ALL_PARAMS); - - $oP->add("
\n"); - $oP->WizardFormStart('request_wizard', 1); - - $oP->add("

".Dict::S('Portal:SelectService')."

\n"); - $oP->add("\n"); - $oSearch = DBObjectSearch::FromOQL(SERVICECATEGORY_QUERY); - $oSet = new CMDBObjectSet($oSearch, array(), array('org_id' => $oUserOrg->GetKey())); - while($oService = $oSet->Fetch()) - { - $id = $oService->GetKey(); - $sChecked = ""; - if (isset($aParameters['service_id']) && ($id == $aParameters['service_id'])) - { - $sChecked = "checked"; - } - $oP->p(""); - } - $oP->add("

"); - $oP->p("

".$oService->GetAsHTML('description')."

\n"); - - $oP->DumpHiddenParams($aParameters, array('service_id')); - $oP->add(""); - $oP->WizardFormButtons(BUTTON_BACK | BUTTON_NEXT | BUTTON_CANCEL); - $oP->WizardFormEnd(); - $oP->WizardCheckSelectionOnSubmit(Dict::S('Portal:PleaseSelectOneService')); - $oP->add("
\n"); -} - -/** - * Displays the form to select a Service Subcategory Id (among the valid ones for the specified user Organization) - * and based on the page's parameter 'service_id' - * @param WebPage $oP Web page for the form output - * @param Organization $oUserOrg The organization of the current user - * @return void - */ - -function SelectServiceSubCategory($oP, $oUserOrg) -{ - $aParameters = $oP->ReadAllParams(ALL_PARAMS); - - $iSvcId = $aParameters['service_id']; - $iDefaultSubSvcId = isset($aParameters['servicesubcategory_id']) ? $aParameters['servicesubcategory_id'] : 0; - - $iDefaultWizNext = 2; - - $oSearch = DBObjectSearch::FromOQL(SERVICE_SUBCATEGORY_QUERY); - $oSet = new CMDBObjectSet($oSearch, array(), array('svc_id' => $iSvcId, 'org_id' => $oUserOrg->GetKey())); - $oServiceCategory = MetaModel::GetObject('Service', $iSvcId, false); - if (is_object($oServiceCategory)) - { - $oP->add("
\n"); - $oP->add("

".Dict::Format('Portal:SelectSubcategoryFrom_Service', $oServiceCategory->GetName())."

\n"); - $oP->WizardFormStart('request_wizard', $iDefaultWizNext); - $oP->add("\n"); - while($oSubService = $oSet->Fetch()) - { - $id = $oSubService->GetKey(); - $sChecked = ""; - if ($id == $iDefaultSubSvcId) - { - $sChecked = "checked"; - } - - $oP->add(""); - - $oP->add(""); - - $oP->add(""); - $oP->add(""); - } - $oP->add("
"); - $oP->add("

"); - $oP->add("
"); - $oP->add("

"); - $oP->add("

".$oSubService->GetAsHTML('description')."

"); - $oP->add("
\n"); - $oP->DumpHiddenParams($aParameters, array('servicesubcategory_id')); - $oP->add(""); - $oP->WizardFormButtons(BUTTON_BACK | BUTTON_NEXT | BUTTON_CANCEL); - $oP->WizardFormEnd(); - $oP->WizardCheckSelectionOnSubmit(Dict::S('Portal:PleaseSelectAServiceSubCategory')); - $oP->add("
\n"); - } - else - { - $oP->p("Error: Invalid Service: id = $iSvcId"); - } -} - -/** - * Displays the form for the final step of the UserRequest creation - * @param WebPage $oP The current web page for the form output - * @param Organization $oUserOrg The organization of the current user - * @return void - */ -function RequestCreationForm($oP, $oUserOrg) -{ - $oP->add_script( -<<ReadAllParams(ALL_PARAMS); - - $aList = array('title', 'description', 'impact', 'urgency', 'workgroup_id'); - - $sDescription = ''; - if (isset($aParameters['template_id'])) - { - $oTemplate = MetaModel::GetObject('Template', $aParameters['template_id'], false); - if (is_object($oTemplate)) - { - $sDescription = htmlentities($oTemplate->Get('template'), ENT_QUOTES, 'UTF-8'); - } - } - - $oServiceCategory = MetaModel::GetObject('Service', $aParameters['service_id'], false); - $oServiceSubCategory = MetaModel::GetObject('ServiceSubcategory', $aParameters['servicesubcategory_id'], false); - if (is_object($oServiceCategory) && is_object($oServiceSubCategory)) - { - $oRequest = new UserRequest(); - $oRequest->Set('org_id', $oUserOrg->GetKey()); - $oRequest->Set('caller_id', UserRights::GetContactId()); - $oRequest->Set('service_id', $aParameters['service_id']); - $oRequest->Set('servicesubcategory_id', $aParameters['servicesubcategory_id']); - - $oAttDef = MetaModel::GetAttributeDef('UserRequest', 'service_id'); - $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $oServiceCategory->GetName()); - $oAttDef = MetaModel::GetAttributeDef('UserRequest', 'servicesubcategory_id'); - $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $oServiceSubCategory->GetName()); - - $iFlags = 0; - foreach($aList as $sAttCode) - { - $value = ''; - if (isset($aParameters[$sAttCode])) - { - $value = $aParameters[$sAttCode]; - $oRequest->Set($sAttCode, $value); - } - } - $aFieldsMap = array(); - foreach($aList as $sAttCode) - { - $value = ''; - $oAttDef = MetaModel::GetAttributeDef(get_class($oRequest), $sAttCode); - $iFlags = $oRequest->GetAttributeFlags($sAttCode); - if (isset($aParameters[$sAttCode])) - { - $value = $aParameters[$sAttCode]; - } - $aArgs = array('this' => $oRequest); - - $sInputId = 'attr_'.$sAttCode; - $aFieldsMap[$sAttCode] = $sInputId; - $sValue = "".$oRequest->GetFormElementForField($oP, get_class($oRequest), $sAttCode, $oAttDef, $value, '', 'attr_'.$sAttCode, '', $iFlags, $aArgs).''; - $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sValue); - } - $aDetails[] = array('label' => Dict::S('Class:Ticket/Attribute:ticket_log'), 'value' => ''); - - $oP->add_linked_script("../js/json.js"); - $oP->add_linked_script("../js/forms-json-utils.js"); - $oP->add_linked_script("../js/wizardhelper.js"); - $oP->add_linked_script("../js/wizard.utils.js"); - $oP->add_linked_script("../js/linkswidget.js"); - $oP->add_linked_script("../js/extkeywidget.js"); - $oP->add_linked_script("../js/jquery.blockUI.js"); - $oP->add("
\n"); - $oP->add("

".Dict::S('Portal:DescriptionOfTheRequest')."

\n"); - $oP->WizardFormStart('request_form', 3); - //$oP->add("\n"); - $oP->details($aDetails); - - $oAttPlugin = new AttachmentPlugIn(); - $oAttPlugin->OnDisplayRelations($oRequest, $oP, true /* edit */); - - $oP->DumpHiddenParams($aParameters, $aList); - $oP->add(""); - $oP->WizardFormButtons(BUTTON_BACK | BUTTON_FINISH | BUTTON_CANCEL); - $oP->WizardFormEnd(); - $oP->add("\n"); - $iFieldsCount = count($aFieldsMap); - $sJsonFieldsMap = json_encode($aFieldsMap); - - $oP->add_ready_script( -<<ReadAllParams(ALL_PARAMS); - $sTransactionId = utils::ReadPostedParam('transaction_id', ''); - if (!utils::IsTransactionValid($sTransactionId)) - { - $oP->add("

".Dict::S('UI:Error:ObjectAlreadyCreated')."

\n"); - //ShowOngoingTickets($oP); - return; - } - - // Validate the parameters - // 1) ServiceCategory - $oSearch = DBObjectSearch::FromOQL(VALIDATE_SERVICECATEGORY_QUERY); - $oSet = new CMDBObjectSet($oSearch, array(), array('id' => $aParameters['service_id'], 'org_id' => $oUserOrg->GetKey())); - if ($oSet->Count() != 1) - { - // Invalid service for the current user ! - throw new Exception("Invalid Service Category: id={$aParameters['service_id']} - count: ".$oSet->Count()); - } - $oServiceCategory = $oSet->Fetch(); - - // 2) Service Subcategory - $oSearch = DBObjectSearch::FromOQL(VALIDATE_SERVICESUBCATEGORY_QUERY); - $oSet = new CMDBObjectSet($oSearch, array(), array('service_id' => $aParameters['service_id'], 'id' =>$aParameters['servicesubcategory_id'],'org_id' => $oUserOrg->GetKey() )); - if ($oSet->Count() != 1) - { - // Invalid subcategory - throw new Exception("Invalid ServiceSubcategory: id={$aParameters['servicesubcategory_id']} for service category ".$oServiceCategory->GetName()."({$aParameters['service_id']}) - count: ".$oSet->Count()); - } - $oServiceSubCategory = $oSet->Fetch(); - - $oRequest = new UserRequest(); - $oRequest->Set('org_id', $oUserOrg->GetKey()); - $oRequest->Set('caller_id', UserRights::GetContactId()); - $aList = array('service_id', 'servicesubcategory_id', 'title', 'description', 'impact'); - $oRequest->UpdateObjectFromPostedForm(); - if (isset($aParameters['moreinfo'])) - { - // There is a template, insert it into the description - $oRequest->Set('ticket_log', $aParameters['moreinfo']); - } - - /////$oP->DoUpdateObjectFromPostedForm($oObj); - $oAttPlugin = new AttachmentPlugIn(); - $oAttPlugin->OnFormSubmit($oRequest); - - list($bRes, $aIssues) = $oRequest->CheckToWrite(); - if ($bRes) - { - $oRequest->DBInsert(); - $oP->add("

".Dict::Format('UI:Title:Object_Of_Class_Created', $oRequest->GetName(), MetaModel::GetName(get_class($oRequest)))."

\n"); - - //DisplayObject($oP, $oRequest, $oUserOrg); - ShowOngoingTickets($oP); - } - else - { - RequestCreationForm($oP, $oUserOrg); - $sIssueDesc = Dict::Format('UI:ObjectCouldNotBeWritten', implode(', ', $aIssues)); - $oP->add_ready_script("alert('".addslashes($sIssueDesc)."');"); - } -} - -/** - * Prompts the user for creating a new request - * @param WebPage $oP The current web page - * @return void - */ -function CreateRequest(WebPage $oP, Organization $oUserOrg) -{ - switch($oP->GetWizardStep()) - { - case 0: - default: - SelectServiceCategory($oP, $oUserOrg); - break; - - case 1: - SelectServiceSubCategory($oP, $oUserOrg); - break; - - case 2: - RequestCreationForm($oP, $oUserOrg); - break; - - case 3: - DoCreateRequest($oP, $oUserOrg); - break; - } -} - -/** - * Lists all the currently opened User Requests for the current user - * @param WebPage $oP The current web page - * @return void - */ -function ListOpenRequests(WebPage $oP) -{ - $oUserOrg = GetUserOrg(); - - $sOQL = 'SELECT UserRequest WHERE org_id = :org_id AND status NOT IN ("closed")'; - $oSearch = DBObjectSearch::FromOQL($sOQL); - $iUser = UserRights::GetContactId(); - if ($iUser > 0) - { - $oSearch->AddCondition('caller_id', $iUser); - } - $oSet = new CMDBObjectSet($oSearch, array(), array('org_id' => $oUserOrg->GetKey())); - $aZList = array('finalclass', 'title', 'start_date', 'status', 'servicesubcategory_id', 'priority', 'caller_id'); - $oP->DisplaySet($oSet, $aZList, Dict::S('Portal:NoOpenRequest')); -} - -/** - * Lists all the currently resolved (not yet closed) User Requests for the current user - * @param WebPage $oP The current web page - * @return void - */ -function ListResolvedRequests(WebPage $oP) -{ - $oUserOrg = GetUserOrg(); - - $sOQL = 'SELECT UserRequest WHERE org_id = :org_id AND status = "resolved"'; - $oSearch = DBObjectSearch::FromOQL($sOQL); - $iUser = UserRights::GetContactId(); - if ($iUser > 0) - { - $oSearch->AddCondition('caller_id', $iUser); - } - $oSet = new CMDBObjectSet($oSearch, array(), array('org_id' => $oUserOrg->GetKey())); - $aZList = array('finalclass', 'title', 'start_date', 'status', 'servicesubcategory_id', 'priority', 'caller_id'); - $oP->DisplaySet($oSet, $aZList, Dict::S('Portal:NoOpenRequest')); -} - -/** - * Lists all the currently closed tickets - * @param WebPage $oP The current web page - * @return void - */ -function ListClosedTickets(WebPage $oP) -{ - $aAttSpecs = array('ref', 'start_date', 'close_date', 'service_id', 'caller_id'); - $aZList = array('title', 'start_date', 'close_date', 'servicesubcategory_id'); - - $oP->DisplaySearchForm('UserRequest', $aAttSpecs, array('operation' => 'show_closed'), 'search_', false /* => not closed */); - - $oUserOrg = GetUserOrg(); - - // UserRequest - $oSearch = $oP->PostedParamsToFilter('UserRequest', $aAttSpecs, 'search_'); - if(is_null($oSearch)) - { - $oSearch = new DBObjectSearch('UserRequest'); - } - $oSearch->AddCondition('org_id', $oUserOrg->GetKey()); - $oSearch->AddCondition('status', 'closed'); - $iUser = UserRights::GetContactId(); - if ($iUser > 0) - { - $oSearch->AddCondition('caller_id', $iUser); - } - $oSet1 = new CMDBObjectSet($oSearch); - $oP->add("

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

".Dict::S('Portal:ClosedRequests')."

\n"); - $oP->DisplaySet($oSet1, $aZList, Dict::S('Portal:NoClosedRequest')); - $oP->add("

\n"); -} - - -/** - * Display an object - to be customized - * @param WebPage $oP The current web page - * @param Object $oObj Any kind of object - * @param Object $oUserOrg The organization of the logged in user - * @return void - */ -function DisplayObject($oP, $oObj, $oUserOrg) -{ - switch(get_class($oObj)) - { - case 'UserRequest': - ShowDetailsRequest($oP, $oObj); - break; - - default: - throw new Exception("The class ".get_class($oObj)." is not handled through the portal"); - } -} - -/** - * Displays the details of a request - * @param WebPage $oP The current web page - * @param Object $oObj The target object - * @return void - */ -function ShowDetailsRequest(WebPage $oP, $oObj) -{ - $sClass = get_class($oObj); - - $bIsEscalateButton = false; - $bIsCloseButton = false; - $bEditAttachments = false; - switch($oObj->GetState()) - { - case 'new': - case 'assigned': - case 'frozen': - $aEditAtt = array( - 'ticket_log' => '????' - ); - $bEditAttachments = true; - // disabled - $bIsEscalateButton = true; - break; - - case 'escalated_tto': - case 'escalated_ttr': - $aEditAtt = array( - 'ticket_log' => '????' - ); - $bEditAttachments = true; - break; - - case 'resolved': - $aEditAtt = array( - // non, read-only dans cet etat - 'ticket_log' => '????', - 'user_satisfaction' => '????', - 'user_commment' => '????', - ); - $bIsCloseButton = true; - break; - - case 'closed': - case 'closure_requested': - default: - $aEditAtt = array(); - break; - } - -// REFACTORISER LA MISE EN FORME - $oP->add("

".$oObj->GetIcon()." ".Dict::Format('Portal:TitleRequestDetailsFor_Request', $oObj->GetName())."

\n"); - - switch($sClass) - { - case 'UserIssue': - //$aAttList = array('ref', 'status', 'title', 'description', 'start_date', 'caller_id', 'servicesubcategory_id', 'impact', 'priority', 'agent_id', 'close_date', 'last_update', 'assignment_date', 'resolution_code', 'solution', 'origin', 'time_spent', 'respected_gtr', 'gtr_overdue', 'user_satisfaction', 'user_commment', 'freeze_reason', 'ticket_log'); - $aAttList = array('col:0'=> array('ref','caller_id','impact','perimeter','servicesubcategory_id','title'),'col:1'=> array('status','priority','start_date','resolution_date','last_update','agent_id')); - break; - - case 'UserRequest': - //$aAttList = array('ref', 'status', 'title', 'description', 'requesttype', 'start_date', 'caller_id', 'servicesubcategory_id', 'priority', 'agent_id', 'close_date', 'last_update', 'assignment_date', 'user_satisfaction', 'user_commment', 'freeze_reason', 'ticket_log'); - $aAttList = array('col:0'=> array('ref','caller_id','servicesubcategory_id','title'),'col:1'=> array('status','priority','start_date','resolution_date','last_update','agent_id')); - break; - - default: - //$aAttList = array('ref'); - array('col:0'=> array('ref','service_id','servicesubcategory_id','title'),'col:1'=> array('status','start_date')); - break; - } - - // Remove the edited attribute from the shown attributes - // - foreach($aEditAtt as $sAttCode => $foo) - { - foreach($aAttList as $col => $aColumn) - { - if (in_array($sAttCode, $aColumn)) - { - if(($index = array_search($sAttCode, $aColumn)) !== false) - { - unset($aAttList[$col][$index]); - } - } - } - } - - $oP->add("
\n"); - $oP->WizardFormStart('request_form', null); - - $oP->add('
'); - $oP->add('
'); - - $oP->add(''); - $oP->add(''); - $oP->add(''); - $oP->add(''); - -// REFACTORISER - $oP->add(''); - $oP->add(''); - $oP->add(''); - - if (count($aEditAtt) > 0) - { - $oP->add(''); - $oP->add('
'); - $oP->DisplayObjectDetails($oObj, $aAttList['col:0']); - $oP->add(''); - $oP->DisplayObjectDetails($oObj, $aAttList['col:1']); - $oP->add('
'); - $oAttPlugin = new AttachmentPlugIn(); - if ($bEditAttachments) - { - $oAttPlugin->EnableDelete(false); - $oAttPlugin->OnDisplayRelations($oObj, $oP, true /* edit */); - } - else - { - $oAttPlugin->OnDisplayRelations($oObj, $oP, false /* read */); - } - $oP->add('
'); - - //$oP->add("
\n"); - //$oP->add(''); - $oP->add(''); - } - - $oP->add(''); - $oP->add(''); - $oP->add(''); - - $oP->add('
'); - //$oP->add("

".Dict::Format('Portal:CommentsFor_Request', $oObj->GetName())."

\n"); - $oP->add(""); - $oP->add("GetKey()."\">"); - $oP->add(""); - $oP->add("\n"); - $oP->add_script( -<< $foo) - { - $sValue = $oObj->Get($sAttCode); - $sDisplayValue = $oObj->GetEditValue($sAttCode); - $aArgs = array('this' => $oObj, 'formPrefix' => ''); - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - $sInputId = 'input_'.$sAttCode; - $sHTMLValue = "".cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', 0 /*$iFlags*/, $aArgs).''; - - $aEditFields[$sAttCode] = array( - 'label' => MetaModel::GetLabel($sClass, $sAttCode), - 'value' => $sHTMLValue - ); - } - foreach($aEditFields as $sAttCode => $aFieldSpec) - { - if ($sAttCode == 'ticket_log') - { - // Skip, the public log will be displayed below the buttons - continue; - } - $oP->add("
"); - $oP->add('

'.$aFieldSpec['label'].'

'); - $oP->add($aFieldSpec['value']); - $oP->add('
'); - } - // $oP->p(''); - if($bIsCloseButton) - { - $sStimulusCode = 'ev_close'; - $oP->p(''); - } - else - { - $oP->p(''); - } - - if ($bIsEscalateButton) - { - $sStimulusCode = 'ev_timeout'; - $oP->p(''); - } - - $oP->add('
'); - if (isset($aEditFields['ticket_log'])) - { - $oP->add("
"); - $oP->add('

'.$aEditFields['ticket_log']['label'].'

'); - $oP->add($aEditFields['ticket_log']['value']); - $oP->add('
'); - } - else - { - $oP->add('

'.MetaModel::GetLabel($sClass, 'ticket_log').'

'); - $oP->add($oObj->GetAsHTML('ticket_log')); - } - $oP->add('
'); - $oP->add(''); - - $oP->WizardFormEnd(); - $oP->add(''); -} - -/** - * Get The organization of the current user (i.e. the organization of its contact) - * @param WebPage $oP The current page, for errors output - * @return Organization The user's org or null in case of problem... - */ -function GetUserOrg() -{ - $oOrg = null; - $iContactId = UserRights::GetContactId(); - $oContact = MetaModel::GetObject('Contact', $iContactId, false); // false => Can fail - if (is_object($oContact)) - { - $oOrg = MetaModel::GetObject('Organization', $oContact->Get('org_id'), false); // false => can fail - } - else - { - throw new Exception(Dict::S('Portal:ErrorNoContactForThisUser')); - } - return $oOrg; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Main program -// -/////////////////////////////////////////////////////////////////////////////// - -try -{ - require_once(APPROOT.'/application/startup.inc.php'); - require_once(APPROOT.'/application/portalwebpage.class.inc.php'); - $oAppContext = new ApplicationContext(); - $sOperation = utils::ReadParam('operation', ''); - - require_once(APPROOT.'/application/loginwebpage.class.inc.php'); - LoginWebPage::DoLogin(false /* bMustBeAdmin */, true /* IsAllowedToPortalUsers */); // Check user rights and prompt if needed - - ApplicationContext::SetUrlMakerClass('MyPortalURLMaker'); - - $oUserOrg = GetUserOrg(); - - $sCode = $oUserOrg->Get('code'); - $sAlternateStylesheet = ''; - if (@file_exists("./$sCode/portal.css")) - { - $sAlternateStylesheet = "$sCode"; - } - - $oP = new PortalWebPage(Dict::S('Portal:Title'), $sAlternateStylesheet); - - $oP->EnableDisconnectButton(utils::CanLogOff()); - $oP->SetWelcomeMessage(Dict::Format('Portal:WelcomeUserOrg', UserRights::GetUserFriendlyName(), $oUserOrg->GetName())); - - if (is_object($oUserOrg)) - { - switch($sOperation) - { - case 'show_closed': - DisplayMainMenu($oP); - ShowClosedTickets($oP); - break; - - case 'create_request': - DisplayMainMenu($oP); - CreateRequest($oP, $oUserOrg); - break; - - case 'details': - DisplayMainMenu($oP); - $oObj = $oP->FindObjectFromArgs(array('UserRequest')); - DisplayObject($oP, $oObj, $oUserOrg); - break; - - case 'update_request': - DisplayMainMenu($oP); - $oObj = $oP->FindObjectFromArgs(array('UserRequest')); - switch(get_class($oObj)) - { - case 'UserRequest': - $aAttList = array('ticket_log', 'user_satisfaction', 'user_commment'); - break; - - default: - throw new Exception("Implementation issue: unexpected class '".get_class($oObj)."'"); - } - try - { - $oP->DoUpdateObjectFromPostedForm($oObj, $aAttList); - } - catch(TransactionException $e) - { - $oP->add("

".Dict::S('UI:Error:ObjectAlreadyUpdated')."

\n"); - } - DisplayObject($oP, $oObj, $oUserOrg); - break; - - case 'show_ongoing': - default: - DisplayMainMenu($oP); - ShowOngoingTickets($oP); - } - } - $oP->output(); -} -catch(CoreException $e) -{ - require_once(APPROOT.'/setup/setuppage.class.inc.php'); - $oP = new SetupPage(Dict::S('UI:PageTitle:FatalError')); - $oP->add("

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

\n"); - $oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc())); - $oP->output(); - - if (MetaModel::IsLogEnabledIssue()) - { - if (MetaModel::IsValidClass('EventIssue')) - { - try - { - $oLog = new EventIssue(); - - $oLog->Set('message', $e->getMessage()); - $oLog->Set('userinfo', ''); - $oLog->Set('issue', $e->GetIssue()); - $oLog->Set('impact', 'Page could not be displayed'); - $oLog->Set('callstack', $e->getTrace()); - $oLog->Set('data', $e->getContextData()); - $oLog->DBInsertNoReload(); - } - catch(Exception $e) - { - IssueLog::Error("Failed to log issue into the DB"); - } - } - - IssueLog::Error($e->getMessage()); - } - - // For debugging only - //throw $e; -} -catch(Exception $e) -{ - require_once(APPROOT.'/setup/setuppage.class.inc.php'); - $oP = new SetupPage(Dict::S('UI:PageTitle:FatalError')); - $oP->add("

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

\n"); - $oP->error(Dict::Format('UI:Error_Details', $e->getMessage())); - $oP->output(); - - if (MetaModel::IsLogEnabledIssue()) - { - if (MetaModel::IsValidClass('EventIssue')) - { - try - { - $oLog = new EventIssue(); - - $oLog->Set('message', $e->getMessage()); - $oLog->Set('userinfo', ''); - $oLog->Set('issue', 'PHP Exception'); - $oLog->Set('impact', 'Page could not be displayed'); - $oLog->Set('callstack', $e->getTrace()); - $oLog->Set('data', array()); - $oLog->DBInsertNoReload(); - } - catch(Exception $e) - { - IssueLog::Error("Failed to log issue into the DB"); - } - } - - IssueLog::Error($e->getMessage()); - } -} -?> + + * @author Romain Quetiez + * @author Denis Flaven + * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL + */ +require_once('../approot.inc.php'); +require_once(APPROOT.'/application/application.inc.php'); +require_once(APPROOT.'/application/nicewebpage.class.inc.php'); +require_once(APPROOT.'/application/wizardhelper.class.inc.php'); + +/** + * Displays the portal main menu + * @param WebPage $oP The current web page + * @return void + */ +function DisplayMainMenu(WebPage $oP) +{ + $oP->AddMenuButton('showongoing', 'Portal:ShowOngoing', '../portal/index.php?operation=show_ongoing'); + $oP->AddMenuButton('newrequest', 'Portal:CreateNewRequest', '../portal/index.php?operation=create_request'); + $oP->AddMenuButton('showclosed', 'Portal:ShowClosed', '../portal/index.php?operation=show_closed'); + if (UserRights::CanChangePassword()) + { + $oP->AddMenuButton('change_pwd', 'Portal:ChangeMyPassword', '../portal/index.php?loginop=change_pwd'); + } +} + +/** + * Displays the current tickets + * @param WebPage $oP The current web page + * @return void + */ +function ShowOngoingTickets(WebPage $oP) +{ + $oP->add("
\n"); + $oP->add("

".Dict::S('Portal:OpenRequests')."

\n"); + ListOpenRequests($oP); + $oP->add("
\n"); + + $oP->add("
\n"); + $oP->add("

".Dict::S('Portal:ResolvedRequests')."

\n"); + ListResolvedRequests($oP); + $oP->add("
\n"); +} + +/** + * Displays the closed tickets + * @param WebPage $oP The current web page + * @return void + */ +function ShowClosedTickets(WebPage $oP) +{ + $oP->add("
\n"); + //$oP->add("

".Dict::S('Portal:ListClosedTickets')."

\n"); + ListClosedTickets($oP); + $oP->add("
\n"); +} + +/** + * Displays the form to select a Service Category Id (among the valid ones for the specified user Organization) + * @param WebPage $oP Web page for the form output + * @param Organization $oUserOrg The organization of the current user + * @return void + */ +function SelectServiceCategory($oP, $oUserOrg) +{ + $aParameters = $oP->ReadAllParams(PORTAL_ALL_PARAMS); + + $oP->add("
\n"); + $oP->WizardFormStart('request_wizard', 1); + + $oP->add("

".Dict::S('Portal:SelectService')."

\n"); + $oP->add("\n"); + $oSearch = DBObjectSearch::FromOQL(PORTAL_SERVICECATEGORY_QUERY); + $oSet = new CMDBObjectSet($oSearch, array(), array('org_id' => $oUserOrg->GetKey())); + while($oService = $oSet->Fetch()) + { + $id = $oService->GetKey(); + $sChecked = ""; + if (isset($aParameters['service_id']) && ($id == $aParameters['service_id'])) + { + $sChecked = "checked"; + } + $oP->p(""); + } + $oP->add("

"); + $oP->p("

".$oService->GetAsHTML('description')."

\n"); + + $oP->DumpHiddenParams($aParameters, array('service_id')); + $oP->add(""); + $oP->WizardFormButtons(BUTTON_BACK | BUTTON_NEXT | BUTTON_CANCEL); + $oP->WizardFormEnd(); + $oP->WizardCheckSelectionOnSubmit(Dict::S('Portal:PleaseSelectOneService')); + $oP->add("
\n"); +} + +/** + * Displays the form to select a Service Subcategory Id (among the valid ones for the specified user Organization) + * and based on the page's parameter 'service_id' + * @param WebPage $oP Web page for the form output + * @param Organization $oUserOrg The organization of the current user + * @return void + */ + +function SelectServiceSubCategory($oP, $oUserOrg) +{ + $aParameters = $oP->ReadAllParams(PORTAL_ALL_PARAMS); + + $iSvcId = $aParameters['service_id']; + $iDefaultSubSvcId = isset($aParameters['servicesubcategory_id']) ? $aParameters['servicesubcategory_id'] : 0; + + $iDefaultWizNext = 2; + + $oSearch = DBObjectSearch::FromOQL(PORTAL_SERVICE_SUBCATEGORY_QUERY); + $oSet = new CMDBObjectSet($oSearch, array(), array('svc_id' => $iSvcId, 'org_id' => $oUserOrg->GetKey())); + $oServiceCategory = MetaModel::GetObject('Service', $iSvcId, false); + if (is_object($oServiceCategory)) + { + $oP->add("
\n"); + $oP->add("

".Dict::Format('Portal:SelectSubcategoryFrom_Service', $oServiceCategory->GetName())."

\n"); + $oP->WizardFormStart('request_wizard', $iDefaultWizNext); + $oP->add("\n"); + while($oSubService = $oSet->Fetch()) + { + $id = $oSubService->GetKey(); + $sChecked = ""; + if ($id == $iDefaultSubSvcId) + { + $sChecked = "checked"; + } + + $oP->add(""); + + $oP->add(""); + + $oP->add(""); + $oP->add(""); + } + $oP->add("
"); + $oP->add("

"); + $oP->add("
"); + $oP->add("

"); + $oP->add("

".$oSubService->GetAsHTML('description')."

"); + $oP->add("
\n"); + $oP->DumpHiddenParams($aParameters, array('servicesubcategory_id')); + $oP->add(""); + $oP->WizardFormButtons(BUTTON_BACK | BUTTON_NEXT | BUTTON_CANCEL); + $oP->WizardFormEnd(); + $oP->WizardCheckSelectionOnSubmit(Dict::S('Portal:PleaseSelectAServiceSubCategory')); + $oP->add("
\n"); + } + else + { + $oP->p("Error: Invalid Service: id = $iSvcId"); + } +} + +/** + * Displays the form for the final step of the UserRequest creation + * @param WebPage $oP The current web page for the form output + * @param Organization $oUserOrg The organization of the current user + * @return void + */ +function RequestCreationForm($oP, $oUserOrg) +{ + $oP->add_script( +<<ReadAllParams(PORTAL_ALL_PARAMS); + + // Example: $aList = array('title', 'description', 'impact', 'emergency'); + $aList = explode(',', PORTAL_REQUEST_FORM_ATTRIBUTES); + + $sDescription = ''; + if (isset($aParameters['template_id'])) + { + $oTemplate = MetaModel::GetObject('Template', $aParameters['template_id'], false); + if (is_object($oTemplate)) + { + $sDescription = htmlentities($oTemplate->Get('template'), ENT_QUOTES, 'UTF-8'); + } + } + + $oServiceCategory = MetaModel::GetObject('Service', $aParameters['service_id'], false); + $oServiceSubCategory = MetaModel::GetObject('ServiceSubcategory', $aParameters['servicesubcategory_id'], false); + if (is_object($oServiceCategory) && is_object($oServiceSubCategory)) + { + $oRequest = new UserRequest(); + $oRequest->Set('org_id', $oUserOrg->GetKey()); + $oRequest->Set('caller_id', UserRights::GetContactId()); + $oRequest->Set('service_id', $aParameters['service_id']); + $oRequest->Set('servicesubcategory_id', $aParameters['servicesubcategory_id']); + + $oAttDef = MetaModel::GetAttributeDef('UserRequest', 'service_id'); + $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $oServiceCategory->GetName()); + $oAttDef = MetaModel::GetAttributeDef('UserRequest', 'servicesubcategory_id'); + $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $oServiceSubCategory->GetName()); + + $iFlags = 0; + foreach($aList as $sAttCode) + { + $value = ''; + if (isset($aParameters[$sAttCode])) + { + $value = $aParameters[$sAttCode]; + $oRequest->Set($sAttCode, $value); + } + } + $aFieldsMap = array(); + foreach($aList as $sAttCode) + { + $value = ''; + $oAttDef = MetaModel::GetAttributeDef(get_class($oRequest), $sAttCode); + $iFlags = $oRequest->GetAttributeFlags($sAttCode); + if (isset($aParameters[$sAttCode])) + { + $value = $aParameters[$sAttCode]; + } + $aArgs = array('this' => $oRequest); + + $sInputId = 'attr_'.$sAttCode; + $aFieldsMap[$sAttCode] = $sInputId; + $sValue = "".$oRequest->GetFormElementForField($oP, get_class($oRequest), $sAttCode, $oAttDef, $value, '', 'attr_'.$sAttCode, '', $iFlags, $aArgs).''; + $aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sValue); + } + $aDetails[] = array('label' => MetaModel::GetLabel('UserRequest', PORTAL_ATTCODE_LOG), 'value' => ''); + + $oP->add_linked_script("../js/json.js"); + $oP->add_linked_script("../js/forms-json-utils.js"); + $oP->add_linked_script("../js/wizardhelper.js"); + $oP->add_linked_script("../js/wizard.utils.js"); + $oP->add_linked_script("../js/linkswidget.js"); + $oP->add_linked_script("../js/extkeywidget.js"); + $oP->add_linked_script("../js/jquery.blockUI.js"); + $oP->add("
\n"); + $oP->add("

".Dict::S('Portal:DescriptionOfTheRequest')."

\n"); + $oP->WizardFormStart('request_form', 3); + //$oP->add("\n"); + $oP->details($aDetails); + + $oAttPlugin = new AttachmentPlugIn(); + $oAttPlugin->OnDisplayRelations($oRequest, $oP, true /* edit */); + + $oP->DumpHiddenParams($aParameters, $aList); + $oP->add(""); + $oP->WizardFormButtons(BUTTON_BACK | BUTTON_FINISH | BUTTON_CANCEL); + $oP->WizardFormEnd(); + $oP->add("\n"); + $iFieldsCount = count($aFieldsMap); + $sJsonFieldsMap = json_encode($aFieldsMap); + + $oP->add_ready_script( +<<ReadAllParams(PORTAL_ALL_PARAMS); + $sTransactionId = utils::ReadPostedParam('transaction_id', ''); + if (!utils::IsTransactionValid($sTransactionId)) + { + $oP->add("

".Dict::S('UI:Error:ObjectAlreadyCreated')."

\n"); + //ShowOngoingTickets($oP); + return; + } + + // Validate the parameters + // 1) ServiceCategory + $oSearch = DBObjectSearch::FromOQL(PORTAL_VALIDATE_SERVICECATEGORY_QUERY); + $oSet = new CMDBObjectSet($oSearch, array(), array('id' => $aParameters['service_id'], 'org_id' => $oUserOrg->GetKey())); + if ($oSet->Count() != 1) + { + // Invalid service for the current user ! + throw new Exception("Invalid Service Category: id={$aParameters['service_id']} - count: ".$oSet->Count()); + } + $oServiceCategory = $oSet->Fetch(); + + // 2) Service Subcategory + $oSearch = DBObjectSearch::FromOQL(PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY); + $oSet = new CMDBObjectSet($oSearch, array(), array('service_id' => $aParameters['service_id'], 'id' =>$aParameters['servicesubcategory_id'],'org_id' => $oUserOrg->GetKey() )); + if ($oSet->Count() != 1) + { + // Invalid subcategory + throw new Exception("Invalid ServiceSubcategory: id={$aParameters['servicesubcategory_id']} for service category ".$oServiceCategory->GetName()."({$aParameters['service_id']}) - count: ".$oSet->Count()); + } + $oServiceSubCategory = $oSet->Fetch(); + + $oRequest = new UserRequest(); + $oRequest->Set('org_id', $oUserOrg->GetKey()); + $oRequest->Set('caller_id', UserRights::GetContactId()); + $aList = array('service_id', 'servicesubcategory_id', 'title', 'description', 'impact'); + $oRequest->UpdateObjectFromPostedForm(); + if (isset($aParameters['moreinfo'])) + { + // There is a template, insert it into the description + $oRequest->Set(PORTAL_ATTCODE_LOG, $aParameters['moreinfo']); + } + + if ((PORTAL_ATTCODE_TYPE != '') && (PORTAL_SET_TYPE_FROM != '')) + { + $oRequest->Set(PORTAL_ATTCODE_TYPE, $oServiceSubCategory->Get(PORTAL_SET_TYPE_FROM)); + } + + /////$oP->DoUpdateObjectFromPostedForm($oObj); + $oAttPlugin = new AttachmentPlugIn(); + $oAttPlugin->OnFormSubmit($oRequest); + + list($bRes, $aIssues) = $oRequest->CheckToWrite(); + if ($bRes) + { + $oRequest->DBInsert(); + $oP->add("

".Dict::Format('UI:Title:Object_Of_Class_Created', $oRequest->GetName(), MetaModel::GetName(get_class($oRequest)))."

\n"); + + //DisplayObject($oP, $oRequest, $oUserOrg); + ShowOngoingTickets($oP); + } + else + { + RequestCreationForm($oP, $oUserOrg); + $sIssueDesc = Dict::Format('UI:ObjectCouldNotBeWritten', implode(', ', $aIssues)); + $oP->add_ready_script("alert('".addslashes($sIssueDesc)."');"); + } +} + +/** + * Prompts the user for creating a new request + * @param WebPage $oP The current web page + * @return void + */ +function CreateRequest(WebPage $oP, Organization $oUserOrg) +{ + switch($oP->GetWizardStep()) + { + case 0: + default: + SelectServiceCategory($oP, $oUserOrg); + break; + + case 1: + SelectServiceSubCategory($oP, $oUserOrg); + break; + + case 2: + RequestCreationForm($oP, $oUserOrg); + break; + + case 3: + DoCreateRequest($oP, $oUserOrg); + break; + } +} + +/** + * Lists all the currently opened User Requests for the current user + * @param WebPage $oP The current web page + * @return void + */ +function ListOpenRequests(WebPage $oP) +{ + $oUserOrg = GetUserOrg(); + + $sOQL = 'SELECT UserRequest WHERE org_id = :org_id AND status NOT IN ("closed")'; + $oSearch = DBObjectSearch::FromOQL($sOQL); + $iUser = UserRights::GetContactId(); + if ($iUser > 0) + { + $oSearch->AddCondition('caller_id', $iUser); + } + $oSet = new CMDBObjectSet($oSearch, array(), array('org_id' => $oUserOrg->GetKey())); + $aZList = array('finalclass', 'title', 'start_date', 'status', 'servicesubcategory_id', 'priority', 'caller_id'); + $oP->DisplaySet($oSet, $aZList, Dict::S('Portal:NoOpenRequest')); +} + +/** + * Lists all the currently resolved (not yet closed) User Requests for the current user + * @param WebPage $oP The current web page + * @return void + */ +function ListResolvedRequests(WebPage $oP) +{ + $oUserOrg = GetUserOrg(); + + $sOQL = 'SELECT UserRequest WHERE org_id = :org_id AND status = "resolved"'; + $oSearch = DBObjectSearch::FromOQL($sOQL); + $iUser = UserRights::GetContactId(); + if ($iUser > 0) + { + $oSearch->AddCondition('caller_id', $iUser); + } + $oSet = new CMDBObjectSet($oSearch, array(), array('org_id' => $oUserOrg->GetKey())); + $aZList = array('finalclass', 'title', 'start_date', 'status', 'servicesubcategory_id', 'priority', 'caller_id'); + $oP->DisplaySet($oSet, $aZList, Dict::S('Portal:NoOpenRequest')); +} + +/** + * Lists all the currently closed tickets + * @param WebPage $oP The current web page + * @return void + */ +function ListClosedTickets(WebPage $oP) +{ + $aAttSpecs = array('ref', 'start_date', 'close_date', 'service_id', 'caller_id'); + $aZList = array('title', 'start_date', 'close_date', 'servicesubcategory_id'); + + $oP->DisplaySearchForm('UserRequest', $aAttSpecs, array('operation' => 'show_closed'), 'search_', false /* => not closed */); + + $oUserOrg = GetUserOrg(); + + // UserRequest + $oSearch = $oP->PostedParamsToFilter('UserRequest', $aAttSpecs, 'search_'); + if(is_null($oSearch)) + { + $oSearch = new DBObjectSearch('UserRequest'); + } + $oSearch->AddCondition('org_id', $oUserOrg->GetKey()); + $oSearch->AddCondition('status', 'closed'); + $iUser = UserRights::GetContactId(); + if ($iUser > 0) + { + $oSearch->AddCondition('caller_id', $iUser); + } + $oSet1 = new CMDBObjectSet($oSearch); + $oP->add("

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

".Dict::S('Portal:ClosedRequests')."

\n"); + $oP->DisplaySet($oSet1, $aZList, Dict::S('Portal:NoClosedRequest')); + $oP->add("

\n"); +} + + +/** + * Display an object - to be customized + * @param WebPage $oP The current web page + * @param Object $oObj Any kind of object + * @param Object $oUserOrg The organization of the logged in user + * @return void + */ +function DisplayObject($oP, $oObj, $oUserOrg) +{ + switch(get_class($oObj)) + { + case 'UserRequest': + ShowDetailsRequest($oP, $oObj); + break; + + default: + throw new Exception("The class ".get_class($oObj)." is not handled through the portal"); + } +} + +/** + * Displays the details of a request + * @param WebPage $oP The current web page + * @param Object $oObj The target object + * @return void + */ +function ShowDetailsRequest(WebPage $oP, $oObj) +{ + $sClass = get_class($oObj); + + $bIsEscalateButton = false; + $bIsCloseButton = false; + $bEditAttachments = false; + switch($oObj->GetState()) + { + case 'new': + case 'assigned': + case 'frozen': + $aEditAtt = array( + PORTAL_ATTCODE_LOG => '????' + ); + $bEditAttachments = true; + // disabled - $bIsEscalateButton = true; + break; + + case 'escalated_tto': + case 'escalated_ttr': + $aEditAtt = array( + PORTAL_ATTCODE_LOG => '????' + ); + $bEditAttachments = true; + break; + + case 'resolved': + $aEditAtt = array( + // non, read-only dans cet etat - 'ticket_log' => '????', + 'user_satisfaction' => '????', + PORTAL_ATTCODE_COMMENT => '????', + ); + $bIsCloseButton = true; + break; + + case 'closed': + case 'closure_requested': + default: + $aEditAtt = array(); + break; + } + +// REFACTORISER LA MISE EN FORME + $oP->add("

".$oObj->GetIcon()." ".Dict::Format('Portal:TitleRequestDetailsFor_Request', $oObj->GetName())."

\n"); + + switch($sClass) + { + case 'UserIssue': + $aAttList = array('col:0'=> array('ref','caller_id','impact','perimeter','servicesubcategory_id','title'),'col:1'=> array('status','priority','start_date','resolution_date','last_update','agent_id')); + break; + + case 'UserRequest': + $aAttList = array('col:0'=> array('ref','caller_id','servicesubcategory_id','title'),'col:1'=> array('status','priority','start_date','resolution_date','last_update','agent_id')); + break; + + default: + array('col:0'=> array('ref','service_id','servicesubcategory_id','title'),'col:1'=> array('status','start_date')); + break; + } + + // Remove the edited attribute from the shown attributes + // + foreach($aEditAtt as $sAttCode => $foo) + { + foreach($aAttList as $col => $aColumn) + { + if (in_array($sAttCode, $aColumn)) + { + if(($index = array_search($sAttCode, $aColumn)) !== false) + { + unset($aAttList[$col][$index]); + } + } + } + } + + $oP->add("
\n"); + $oP->WizardFormStart('request_form', null); + + $oP->add('
'); + $oP->add('
'); + + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add(''); + +// REFACTORISER + $oP->add(''); + $oP->add(''); + $oP->add(''); + + if (count($aEditAtt) > 0) + { + $oP->add(''); + $oP->add('
'); + $oP->DisplayObjectDetails($oObj, $aAttList['col:0']); + $oP->add(''); + $oP->DisplayObjectDetails($oObj, $aAttList['col:1']); + $oP->add('
'); + $oAttPlugin = new AttachmentPlugIn(); + if ($bEditAttachments) + { + $oAttPlugin->EnableDelete(false); + $oAttPlugin->OnDisplayRelations($oObj, $oP, true /* edit */); + } + else + { + $oAttPlugin->OnDisplayRelations($oObj, $oP, false /* read */); + } + $oP->add('
'); + + //$oP->add("\n"); + //$oP->add(''); + $oP->add(''); + } + + $oP->add(''); + $oP->add(''); + $oP->add(''); + + $oP->add('
'); + //$oP->add("

".Dict::Format('Portal:CommentsFor_Request', $oObj->GetName())."

\n"); + $oP->add(""); + $oP->add("GetKey()."\">"); + $oP->add(""); + $oP->add("\n"); + $oP->add_script( +<< $foo) + { + $sValue = $oObj->Get($sAttCode); + $sDisplayValue = $oObj->GetEditValue($sAttCode); + $aArgs = array('this' => $oObj, 'formPrefix' => ''); + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + $sInputId = 'input_'.$sAttCode; + $sHTMLValue = "".cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', 0 /*$iFlags*/, $aArgs).''; + + $aEditFields[$sAttCode] = array( + 'label' => MetaModel::GetLabel($sClass, $sAttCode), + 'value' => $sHTMLValue + ); + } + foreach($aEditFields as $sAttCode => $aFieldSpec) + { + if ($sAttCode == PORTAL_ATTCODE_LOG) + { + // Skip, the public log will be displayed below the buttons + continue; + } + $oP->add("
"); + $oP->add('

'.$aFieldSpec['label'].'

'); + $oP->add($aFieldSpec['value']); + $oP->add('
'); + } + // $oP->p(''); + if($bIsCloseButton) + { + $sStimulusCode = 'ev_close'; + $oP->p(''); + } + else + { + $oP->p(''); + } + + if ($bIsEscalateButton) + { + $sStimulusCode = 'ev_timeout'; + $oP->p(''); + } + + $oP->add('
'); + if (isset($aEditFields[PORTAL_ATTCODE_LOG])) + { + $oP->add("
"); + $oP->add('

'.$aEditFields[PORTAL_ATTCODE_LOG]['label'].'

'); + $oP->add($aEditFields[PORTAL_ATTCODE_LOG]['value']); + $oP->add('
'); + } + else + { + $oP->add('

'.MetaModel::GetLabel($sClass, PORTAL_ATTCODE_LOG).'

'); + $oP->add($oObj->GetAsHTML(PORTAL_ATTCODE_LOG)); + } + $oP->add('
'); + $oP->add(''); + + $oP->WizardFormEnd(); + $oP->add(''); +} + +/** + * Get The organization of the current user (i.e. the organization of its contact) + * @param WebPage $oP The current page, for errors output + * @return Organization The user's org or null in case of problem... + */ +function GetUserOrg() +{ + $oOrg = null; + $iContactId = UserRights::GetContactId(); + $oContact = MetaModel::GetObject('Contact', $iContactId, false); // false => Can fail + if (is_object($oContact)) + { + $oOrg = MetaModel::GetObject('Organization', $oContact->Get('org_id'), false); // false => can fail + } + else + { + throw new Exception(Dict::S('Portal:ErrorNoContactForThisUser')); + } + return $oOrg; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Main program +// +/////////////////////////////////////////////////////////////////////////////// + +try +{ + require_once(APPROOT.'/application/startup.inc.php'); + require_once(APPROOT.'/application/portalwebpage.class.inc.php'); + $oAppContext = new ApplicationContext(); + $sOperation = utils::ReadParam('operation', ''); + + require_once(APPROOT.'/application/loginwebpage.class.inc.php'); + LoginWebPage::DoLogin(false /* bMustBeAdmin */, true /* IsAllowedToPortalUsers */); // Check user rights and prompt if needed + + ApplicationContext::SetUrlMakerClass('MyPortalURLMaker'); + + if (!class_exists('UserRequest')) + { + $oP = new WebPage(Dict::S('Portal:Title')); + $oP->p(dict::Format('Portal:NoRequestMgmt', UserRights::GetUserFriendlyName())); + } + else + { + $oUserOrg = GetUserOrg(); + + $sCode = $oUserOrg->Get('code'); + $sAlternateStylesheet = ''; + if (@file_exists("./$sCode/portal.css")) + { + $sAlternateStylesheet = "$sCode"; + } + + $oP = new PortalWebPage(Dict::S('Portal:Title'), $sAlternateStylesheet); + + $oP->EnableDisconnectButton(utils::CanLogOff()); + $oP->SetWelcomeMessage(Dict::Format('Portal:WelcomeUserOrg', UserRights::GetUserFriendlyName(), $oUserOrg->GetName())); + + if (is_object($oUserOrg)) + { + switch($sOperation) + { + case 'show_closed': + DisplayMainMenu($oP); + ShowClosedTickets($oP); + break; + + case 'create_request': + DisplayMainMenu($oP); + CreateRequest($oP, $oUserOrg); + break; + + case 'details': + DisplayMainMenu($oP); + $oObj = $oP->FindObjectFromArgs(array('UserRequest')); + DisplayObject($oP, $oObj, $oUserOrg); + break; + + case 'update_request': + DisplayMainMenu($oP); + $oObj = $oP->FindObjectFromArgs(array('UserRequest')); + switch(get_class($oObj)) + { + case 'UserRequest': + $aAttList = array(PORTAL_ATTCODE_LOG, 'user_satisfaction', PORTAL_ATTCODE_COMMENT); + break; + + default: + throw new Exception("Implementation issue: unexpected class '".get_class($oObj)."'"); + } + try + { + $oP->DoUpdateObjectFromPostedForm($oObj, $aAttList); + } + catch(TransactionException $e) + { + $oP->add("

".Dict::S('UI:Error:ObjectAlreadyUpdated')."

\n"); + } + DisplayObject($oP, $oObj, $oUserOrg); + break; + + case 'show_ongoing': + default: + DisplayMainMenu($oP); + ShowOngoingTickets($oP); + } + } + } + $oP->output(); +} +catch(CoreException $e) +{ + require_once(APPROOT.'/setup/setuppage.class.inc.php'); + $oP = new SetupPage(Dict::S('UI:PageTitle:FatalError')); + $oP->add("

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

\n"); + $oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc())); + $oP->output(); + + if (MetaModel::IsLogEnabledIssue()) + { + if (MetaModel::IsValidClass('EventIssue')) + { + try + { + $oLog = new EventIssue(); + + $oLog->Set('message', $e->getMessage()); + $oLog->Set('userinfo', ''); + $oLog->Set('issue', $e->GetIssue()); + $oLog->Set('impact', 'Page could not be displayed'); + $oLog->Set('callstack', $e->getTrace()); + $oLog->Set('data', $e->getContextData()); + $oLog->DBInsertNoReload(); + } + catch(Exception $e) + { + IssueLog::Error("Failed to log issue into the DB"); + } + } + + IssueLog::Error($e->getMessage()); + } + + // For debugging only + //throw $e; +} +catch(Exception $e) +{ + require_once(APPROOT.'/setup/setuppage.class.inc.php'); + $oP = new SetupPage(Dict::S('UI:PageTitle:FatalError')); + $oP->add("

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

\n"); + $oP->error(Dict::Format('UI:Error_Details', $e->getMessage())); + $oP->output(); + + if (MetaModel::IsLogEnabledIssue()) + { + if (MetaModel::IsValidClass('EventIssue')) + { + try + { + $oLog = new EventIssue(); + + $oLog->Set('message', $e->getMessage()); + $oLog->Set('userinfo', ''); + $oLog->Set('issue', 'PHP Exception'); + $oLog->Set('impact', 'Page could not be displayed'); + $oLog->Set('callstack', $e->getTrace()); + $oLog->Set('data', array()); + $oLog->DBInsertNoReload(); + } + catch(Exception $e) + { + IssueLog::Error("Failed to log issue into the DB"); + } + } + + IssueLog::Error($e->getMessage()); + } +} +?>