From 59c5abecf63a7fde340082f2149bbaefc9eae1ce Mon Sep 17 00:00:00 2001 From: tomolimo Date: Tue, 28 Feb 2017 13:56:37 +0100 Subject: [PATCH] RC1 --- ajax/asynchronousdatas.php | 50 ++ ajax/dropdownProcesses.php | 9 +- front/cases.front.php | 115 +-- front/processmaker.form.php | 4 +- front/processmaker.helpdesk.form.php | 25 +- front/tracking.injector.php | 2 +- hook.php | 279 ++++++- inc/case.class.php | 4 +- inc/caselink.class.php | 12 + inc/caselinkaction.class.php | 12 + inc/crontaskaction.class.php | 22 + inc/processmaker.class.php | 1128 +++++++++++++++++++------- inc/task.class.php | 48 +- inc/user.class.php | 2 +- js/cases.helpdesk.js | 9 +- js/cases.js | 118 +-- locales/en_GB.php | 8 +- locales/fr_FR.php | 5 +- processmaker.xml | 2 +- setup.php | 25 +- 20 files changed, 1353 insertions(+), 526 deletions(-) create mode 100644 ajax/asynchronousdatas.php create mode 100644 inc/caselink.class.php create mode 100644 inc/caselinkaction.class.php create mode 100644 inc/crontaskaction.class.php diff --git a/ajax/asynchronousdatas.php b/ajax/asynchronousdatas.php new file mode 100644 index 0000000..5f1424c --- /dev/null +++ b/ajax/asynchronousdatas.php @@ -0,0 +1,50 @@ +getFromDB( $datas['id'] ) && $asyncdata->fields['state'] == PluginProcessmakerCrontaskaction::WAITING_DATAS ) { + $initialdatas = json_decode($asyncdata->fields['postdatas'], true); + $initialdatas['form'] = array_merge( $initialdatas['form'], $datas['form'] ) ; + $asyncdata->update( array( 'id' => $datas['id'], 'state' => PluginProcessmakerCrontaskaction::DATAS_READY, 'postdatas' => json_encode($initialdatas, JSON_HEX_APOS | JSON_HEX_QUOT) ) ) ; + $ret = array( 'code' => '0', 'message' => 'Done' ); + } else { + $ret = array( 'code' => '2', 'message' => 'Case is not existing, or state is not WAITING_DATAS' ); + } + + break; + default: + $ret = array( 'code' => '1', 'message' => 'Method not supported' ) ; + } + + echo json_encode( $ret, JSON_HEX_APOS | JSON_HEX_QUOT ) ; + +} diff --git a/ajax/dropdownProcesses.php b/ajax/dropdownProcesses.php index 48cd90e..9877afa 100644 --- a/ajax/dropdownProcesses.php +++ b/ajax/dropdownProcesses.php @@ -32,6 +32,10 @@ if (!($item = getItemForItemtype($_REQUEST['itemtype']))) { exit(); } +$one_item = -1; +if (isset($_POST['_one_id'])) { + $one_item = $_POST['_one_id']; +} // Count real items returned $count = 0; @@ -39,6 +43,7 @@ if (!isset($_REQUEST['emptylabel']) || ($_REQUEST['emptylabel'] == '')) { $_REQUEST['emptylabel'] = Dropdown::EMPTY_VALUE; } +$search=""; if (!empty($_REQUEST['searchText'])) { $search = Search::makeTextSearch($_REQUEST['searchText']); } @@ -46,14 +51,14 @@ if (!empty($_REQUEST['searchText'])) { $processes = array(); // Empty search text : display first -//if (empty($_REQUEST['searchText'])) { +if (empty($_REQUEST['searchText'])) { if ($_REQUEST['display_emptychoice']) { if (($one_item < 0) || ($one_item == 0)) { array_push($processes, array('id' => 0, 'text' => $_REQUEST['emptylabel'])); } } -//} +} $result = PluginProcessmakerProcess::getSqlSearchResult(false, $search); diff --git a/front/cases.front.php b/front/cases.front.php index 8e82daa..95b9956 100644 --- a/front/cases.front.php +++ b/front/cases.front.php @@ -1,5 +1,5 @@ login( ) ; if( isset( $_REQUEST['form'] ) ) { - // save the case variables - //$resultSave = $myProcessMaker->sendVariables( $myCase->getID() , $_REQUEST['form'] ) ; - $resultSave = $myProcessMaker->saveForm( $_REQUEST, $_SERVER['HTTP_COOKIE'] ) ; - //$myCase->sendVariables( $_REQUEST['form'] ) ; - // now derivate the case !!! - $pmRouteCaseResponse = $myProcessMaker->routeCase( $myCase->getID(), $_REQUEST['DEL_INDEX']) ; - - // now tries to get some variables to setup content for new task and to append text to solved task - $infoForTasks = $myProcessMaker->getVariables( $myCase->getID(), array( "GLPI_ITEM_TASK_CONTENT", - "GLPI_ITEM_APPEND_TO_TASK", - "GLPI_NEXT_GROUP_TO_BE_ASSIGNED", - "GLPI_ITEM_TITLE", - "GLPI_TICKET_FOLLOWUP_CONTENT", - "GLPI_TICKET_FOLLOWUP_IS_PRIVATE", - "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID", - "GLPI_ITEM_TASK_ENDDATE", - "GLPI_ITEM_TASK_STARTDATE", - "GLPI_ITEM_SET_STATUS" - ) ); - $itemSetStatus = ''; - if( array_key_exists( 'GLPI_ITEM_SET_STATUS', $infoForTasks ) ) { - $itemSetStatus = $infoForTasks[ 'GLPI_ITEM_SET_STATUS' ] ; - } - - $txtItemTitle = '' ; - if( array_key_exists( 'GLPI_ITEM_TITLE', $infoForTasks ) ) { - $txtItemTitle = $infoForTasks[ 'GLPI_ITEM_TITLE' ] ; - } - - $txtToAppendToTask = '' ; - if( array_key_exists( 'GLPI_ITEM_APPEND_TO_TASK', $infoForTasks ) ) { - $txtToAppendToTask = $infoForTasks[ 'GLPI_ITEM_APPEND_TO_TASK' ] ; - } - - $txtTaskContent = '' ; - if( array_key_exists( 'GLPI_ITEM_TASK_CONTENT', $infoForTasks ) ) { - $txtTaskContent = $infoForTasks[ 'GLPI_ITEM_TASK_CONTENT' ] ; - } - - $groupId = 0 ; - if( array_key_exists( 'GLPI_NEXT_GROUP_TO_BE_ASSIGNED', $infoForTasks ) ) { - $groupId = $infoForTasks[ 'GLPI_NEXT_GROUP_TO_BE_ASSIGNED' ] ; - } - - $taskStartDate = '' ; - $taskEndDate = '' ; - if( array_key_exists( 'GLPI_ITEM_TASK_ENDDATE', $infoForTasks ) ) { - $taskEndDate = $infoForTasks[ 'GLPI_ITEM_TASK_ENDDATE' ] ; - } - if( array_key_exists( 'GLPI_ITEM_TASK_STARTDATE', $infoForTasks ) ) { - $taskStartDate = $infoForTasks[ 'GLPI_ITEM_TASK_STARTDATE' ] ; - if( $taskEndDate == '' ) { - // at least - $taskEndDate = $taskStartDate ; - } - } - - $createFollowup = false ; // by default - if( array_key_exists( 'GLPI_TICKET_FOLLOWUP_CONTENT', $infoForTasks ) && $infoForTasks[ 'GLPI_TICKET_FOLLOWUP_CONTENT' ] != '') { - //&& array_key_exists( 'GLPI_TICKET_FOLLOWUP_IS_PRIVATE', $infoForTasks ) - //&& array_key_exists( 'GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID', $infoForTasks ) - $createFollowup = true ; - } - // reset those variables - $resultSave = $myProcessMaker->sendVariables( $myCase->getID() , array( "GLPI_ITEM_APPEND_TO_TASK" => '', - "GLPI_ITEM_TASK_CONTENT" => '', - "GLPI_NEXT_GROUP_TO_BE_ASSIGNED" => '', - "GLPI_TICKET_FOLLOWUP_CONTENT" => '', - "GLPI_TICKET_FOLLOWUP_IS_PRIVATE" => '', - "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID" => '', - "GLPI_ITEM_TASK_ENDDATE" => '', - "GLPI_ITEM_TASK_STARTDATE" => '', - 'GLPI_ITEM_TITLE' => '', - "GLPI_ITEM_SET_STATUS" => '' - ) ) ; - - // print_r( $pmRouteCaseResponse ) ; - // die() ; - - // now manage tasks associated with item - $itemType = $myCase->getField('itemtype'); - $itemId = $myCase->getField('items_id'); - - // switch own task to 'done' and create a new one - $myProcessMaker->solveTask( $myCase->getID(), $_REQUEST['DEL_INDEX'], $txtToAppendToTask ) ; - - // create a followup if requested - if( $createFollowup && $itemType == 'Ticket' ) { - $myProcessMaker->addTicketFollowup( $itemId, $infoForTasks ) ; - } - $caseInfo = $myProcessMaker->getCaseInfo( $myCase->getID(), $_REQUEST['DEL_INDEX']) ; - if( property_exists( $pmRouteCaseResponse, 'routing' ) ) { - foreach( $pmRouteCaseResponse->routing as $route ) { - $myProcessMaker->addTask( $itemType, $itemId, $caseInfo, $route->delIndex, PluginProcessmakerUser::getGLPIUserId( $route->userId ), $groupId, $route->taskId, $txtTaskContent, $taskStartDate, $taskEndDate ) ; - // if end date was specicied, then must change due date of the PM task - if( $taskEndDate != '' ) { - $PM_DB->query( "UPDATE APP_DELEGATION SET DEL_TASK_DUE_DATE='$taskEndDate' WHERE APP_UID='".$caseInfo->caseId."' AND DEL_INDEX=".$route->delIndex); - } - } - } - if( $txtItemTitle != '') { - // we are going to change the title of current GLPI Item - $item = new $itemType ; - $item->getFromDB( $itemId ) ; - $item->update( array('id' => $itemId, 'name' => $txtItemTitle) ) ; - } - - if( $itemSetStatus != '' ) { - $myProcessMaker->setItemStatus($itemType, $itemId, $itemSetStatus ) ; - } - // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED - $myCase->update( array( 'id' => $myCase->getID(), 'case_status' => $caseInfo->caseStatus ) ) ; + $myProcessMaker->derivateCase( $myCase, $_REQUEST); //, $_SERVER['HTTP_COOKIE'] ) ; } } diff --git a/front/processmaker.form.php b/front/processmaker.form.php index 755c10d..ca818e4 100644 --- a/front/processmaker.form.php +++ b/front/processmaker.form.php @@ -27,13 +27,13 @@ switch( $_POST["action"] ) { $myProcessMaker = new PluginProcessmakerProcessmaker() ; $myProcessMaker->login() ; - $resultCase = $myProcessMaker->newCase( $_POST['plugin_processmaker_process_id'], array( 'GLPI_ITEM_CAN_BE_SOLVED' => 0, 'GLPI_SELFSERVICE_CREATED' => '1') ) ; + $resultCase = $myProcessMaker->newCase( $_POST['plugin_processmaker_process_id'], array( 'GLPI_ITEM_CAN_BE_SOLVED' => 0, 'GLPI_SELFSERVICE_CREATED' => '1', 'GLPI_URL' => $CFG_GLPI['url_base'].$CFG_GLPI['root_doc']) ) ; if ($resultCase->status_code == 0){ // case is created // Must show it... // $rand = rand( ) ; - Html::redirect($CFG_GLPI['root_doc']."/plugins/processmaker/front/processmaker.helpdesk.form.php?process_id=".$_POST['plugin_processmaker_process_id']."&case_id=".$resultCase->caseId."&rand=$rand&itilcategories_id=".$_POST["itilcategories_id"]."&type=".$_REQUEST["type"]); + Html::redirect($CFG_GLPI['root_doc']."/plugins/processmaker/front/processmaker.helpdesk.form.php?process_id=".$_POST['plugin_processmaker_process_id']."&case_id=".$resultCase->caseId."&rand=$rand&itilcategories_id=".$_POST["itilcategories_id"]."&type=".$_REQUEST["type"]."&entities_id=".$_REQUEST['entities_id']); } else { Session::addMessageAfterRedirect($LANG['processmaker']['item']['error'][$resultCase->status_code]."
$resultCase->message ($resultCase->status_code)", true, ERROR); //echo "Error creating case: $resultCase->message \n"; diff --git a/front/processmaker.helpdesk.form.php b/front/processmaker.helpdesk.form.php index 3392ca4..d36a7f6 100644 --- a/front/processmaker.helpdesk.form.php +++ b/front/processmaker.helpdesk.form.php @@ -20,8 +20,10 @@ function processMakerShowProcessList ($ID, $from_helpdesk) { echo ""; echo ""; echo ""; + echo ""; + echo ""; // Dropdown::show('PluginProcessmakerProcessmaker', array( 'name' => 'plugin_processmaker_process_id', 'condition' => "is_active=1 and is_helpdeskvisible=1")); // condition is used to prevent start of none-active and none-helpdesk-visible cases - PluginProcessmakerProcess::dropdown( array( 'entity' => $_SESSION['glpiactive_entity'], 'name' => 'plugin_processmaker_process_id' )); + PluginProcessmakerProcess::dropdown( array( 'value' => 0, 'entity' => $_SESSION['glpiactive_entity'], 'name' => 'plugin_processmaker_process_id' )); echo ""; echo ""; echo ""; @@ -907,7 +909,7 @@ function showFormHelpdesk($ID, $pmItem, $caseInfo, $ticket_template=false) { } $email = UserEmail::getDefaultForUser($ID); - $default_use_notif = Entity::getUsedConfig('is_notif_enable_default', $_SESSION['glpiactive_entity'], '', 1); + $default_use_notif = Entity::getUsedConfig('is_notif_enable_default', $_REQUEST['entities_id'], '', 1); // Set default values... $default_values = array('_users_id_requester_notif' @@ -925,12 +927,12 @@ function showFormHelpdesk($ID, $pmItem, $caseInfo, $ticket_template=false) { 'urgency' => 3, 'items_id' => 0, - 'entities_id' => $_SESSION['glpiactive_entity'], + 'entities_id' => $_REQUEST['entities_id'], 'plan' => array(), 'global_validation' => CommonITILValidation::NONE, '_add_validation' => 0, 'type' => Entity::getUsedConfig('tickettype', - $_SESSION['glpiactive_entity'], + $_REQUEST['entities_id'], '', Ticket::INCIDENT_TYPE), '_right' => "id", '_filename' => array(), @@ -1018,7 +1020,7 @@ function showFormHelpdesk($ID, $pmItem, $caseInfo, $ticket_template=false) { 'use_notification' => $values['_users_id_requester_notif']['use_notification'], 'entity_restrict' - => $_SESSION["glpiactive_entity"]); + => $_REQUEST['entities_id']); Ajax::UpdateItemOnSelectEvent("dropdown_nodelegate".$rand, "show_result".$rand, $CFG_GLPI["root_doc"]."/ajax/dropdownDelegationUsers.php", @@ -1074,7 +1076,7 @@ function showFormHelpdesk($ID, $pmItem, $caseInfo, $ticket_template=false) { // Load ticket template if available : $tt = $ticket->getTicketTemplateToUse($ticket_template, $values['type'], $values['itilcategories_id'], - $_SESSION["glpiactive_entity"]); + $_REQUEST['entities_id']); // Predefined fields from template : reset them if (isset($values['_predefined_fields'])) { @@ -1140,7 +1142,7 @@ function showFormHelpdesk($ID, $pmItem, $caseInfo, $ticket_template=false) { if ($tt->isHiddenField('locations_id')) { echo ""; } - echo ""; + echo ""; echo ""; echo "
"; @@ -1148,7 +1150,7 @@ function showFormHelpdesk($ID, $pmItem, $caseInfo, $ticket_template=false) { echo ""; @@ -1175,7 +1177,7 @@ function showFormHelpdesk($ID, $pmItem, $caseInfo, $ticket_template=false) { } $opt = array('value' => $values['itilcategories_id'], 'condition' => $condition, - 'entity' => $_SESSION["glpiactive_entity"], + 'entity' => $_REQUEST['entities_id'], 'on_change' => 'this.form.submit()'); if ($values['itilcategories_id'] && $tt->isMandatoryField("itilcategories_id")) { @@ -1517,8 +1519,9 @@ if (isset($_REQUEST['case_id'])) { processMakerShowProcessList(Session::getLoginUserID(), 1); else { // before showing the case, we must check the rights for this user to view it, if entity has been changed in the meanwhile - $processList = PluginProcessmakerProcessmaker::getProcessesWithCategoryAndProfile( $_REQUEST["itilcategories_id"], $_REQUEST["type"], $_SESSION['glpiactiveprofile']['id'], $_SESSION['glpiactive_entity'] ) ; - if( in_array_recursive( $_REQUEST['process_id'], $processList ) ) { + // and must check if entity of the ticket is in the tree of authorized entities for current profile + $processList = PluginProcessmakerProcessmaker::getProcessesWithCategoryAndProfile( $_REQUEST["itilcategories_id"], $_REQUEST["type"], $_SESSION['glpiactiveprofile']['id'], $_REQUEST['entities_id'] ) ; + if( in_array( $_REQUEST['entities_id'], $_SESSION['glpiactiveentities']) && in_array_recursive( $_REQUEST['process_id'], $processList ) ) { processMakerShowCase(Session::getLoginUserID(), 1); } else { Html::redirect($CFG_GLPI["root_doc"]."/front/helpdesk.public.php?create_ticket=1"); diff --git a/front/tracking.injector.php b/front/tracking.injector.php index 230a6f0..2f47b5e 100644 --- a/front/tracking.injector.php +++ b/front/tracking.injector.php @@ -28,7 +28,7 @@ if( isset($_POST["_from_helpdesk"]) && $_POST["_from_helpdesk"] == 1 // if not we will continue // special case if RUMT plugin is enabled and no process is available and category is 'User Management' then must start RUMT. - $processList = PluginProcessmakerProcessmaker::getProcessesWithCategoryAndProfile( $_POST["itilcategories_id"], $_POST["type"], $_SESSION['glpiactiveprofile']['id'], $_SESSION['glpiactive_entity'] ) ; + $processList = PluginProcessmakerProcessmaker::getProcessesWithCategoryAndProfile( $_POST["itilcategories_id"], $_POST["type"], $_SESSION['glpiactiveprofile']['id'], $_POST["entities_id"] ) ; // currently only one process should be assigned to this itilcategory so this array should contain only one row $processQt = count( $processList ) ; diff --git a/hook.php b/hook.php index d9c2148..b60ebed 100644 --- a/hook.php +++ b/hook.php @@ -310,7 +310,7 @@ function plugin_processmaker_install() { $DB->query($query) or die("error adding columns 'itilcategories_id' and 'type' to glpi_plugin_processmaker_processes" . $DB->error()); } - if( !FieldExists( 'glpi_plugin_processmaker_processes', 'project_type') ) { // since version 3.0 + if( !FieldExists( 'glpi_plugin_processmaker_processes', 'project_type') ) { $query = "ALTER TABLE `glpi_plugin_processmaker_processes` ADD COLUMN `project_type` VARCHAR(50) NOT NULL DEFAULT 'classic';" ; @@ -352,7 +352,6 @@ function plugin_processmaker_install() { ) COLLATE='utf8_general_ci' ENGINE=InnoDB - AUTO_INCREMENT=57 ; "; @@ -375,6 +374,66 @@ function plugin_processmaker_install() { // $config->update( array( 'id' => $config->getID(), 'taskcategories_id' => $pmCategory ) ) ; //} + if (!TableExists("glpi_plugin_processmaker_crontaskactions")) { + $query = "CREATE TABLE `glpi_plugin_processmaker_crontaskactions` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `plugin_processmaker_caselinks_id` INT(11) NULL DEFAULT NULL, + `itemtype` VARCHAR(100) NOT NULL, + `items_id` INT(11) NOT NULL DEFAULT '0', + `users_id` INT(11) NOT NULL DEFAULT '0', + `toclaim` TINYINT(1) NOT NULL DEFAULT '0', + `postdatas` TEXT NULL DEFAULT NULL, + `state` INT(11) NOT NULL , + `date_mod` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`) + ) + COLLATE='utf8_general_ci' + ENGINE=InnoDB;" ; + $DB->query($query) or die("error creating glpi_plugin_processmaker_crontaskactions" . $DB->error()); + } + + if (!TableExists("glpi_plugin_processmaker_caselinks")) { + $query = "CREATE TABLE `glpi_plugin_processmaker_caselinks` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `is_active` TINYINT(1) NOT NULL DEFAULT '0', + `is_externaldata` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '0:insert data from case,1:wait for external application to set datas', + `is_self` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '0:use linked tickets, 1:use self', + `sourcetask_guid` VARCHAR(32) NULL DEFAULT NULL, + `targettask_guid` VARCHAR(32) NULL DEFAULT NULL, + `targetprocess_guid` VARCHAR(32) NULL DEFAULT NULL, + `targetdynaform_guid` VARCHAR(32) NULL DEFAULT NULL, + `sourcecondition` TEXT NULL, + `targettoclaim` TINYINT(1) NOT NULL DEFAULT '0', + `externalapplication` TEXT NULL, + `date_mod` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `is_active` (`is_active`), + INDEX `is_externaldata` (`is_externaldata`), + INDEX `is_self` (`is_self`) + ) + COLLATE='utf8_general_ci' + ENGINE=InnoDB;" ; + $DB->query($query) or die("error creating glpi_plugin_processmaker_caselinks" . $DB->error()); + } + + + if (!TableExists("glpi_plugin_processmaker_caselinkactions")) { + $query = "CREATE TABLE `glpi_plugin_processmaker_caselinkactions` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `plugin_processmaker_caselinks_id` INT(11) NULL DEFAULT NULL, + `name` VARCHAR(255) NOT NULL, + `value` TEXT NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `caselinks_id_name` (`plugin_processmaker_caselinks_id`, `name`) + ) + COLLATE='utf8_general_ci' + ENGINE=InnoDB + ;" ; + $DB->query($query) or die("error creating glpi_plugin_processmaker_caselinkactions" . $DB->error()); + } + + // no longer used since 2.6 //$myProcessMaker = new PluginProcessmakerProcessmaker() ; //$myProcessMaker->login(true) ; // to force admin login @@ -393,6 +452,7 @@ function plugin_processmaker_install() { CronTask::Register('PluginProcessmakerProcessmaker', 'pmusers', DAY_TIMESTAMP, array( 'state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL)); //CronTask::Register('PluginProcessmakerProcessmaker', 'pmnotifications', DAY_TIMESTAMP, array( 'state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL)); CronTask::Register('PluginProcessmakerProcessmaker', 'pmorphancases', DAY_TIMESTAMP, array('param' => 10, 'state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL)); + CronTask::Register('PluginProcessmakerProcessmaker', 'pmtaskactions', MINUTE_TIMESTAMP, array('state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL)); // required because autoload doesn't work for unactive plugin' @@ -640,4 +700,219 @@ function plugin_processmaker_post_init(){ function plugin_processmaker_giveItem($itemtype,$ID,$data,$num){ return ; +} + + +/** + * Summary of plugin_item_add_update_processmaker_tasks + * @param mixed $parm + */ +function plugin_item_update_processmaker_tasks($parm){ + global $DB, $CFG_GLPI; + + // we need to test if a specific case is completed, and if so + // we should complete the linked cases (via linked tickets) + $pmTaskCat = new PluginProcessmakerTaskCategory ; + if( $pmTaskCat->getFromDBbyCategory( $parm->fields['taskcategories_id'] ) + && in_array( 'state', $parm->updates ) + && $parm->input['state'] == 2) { // the task has just been set to DONE state + + //$taskList = array( array( 'sourcetaskguid' => '54949951157c000b2336474053483376', + // 'sourcecondition' => '@@RELEASE_DONE == 1' , + // 'targettaskguid' => '95599365257bffa6d6170d9068913760', + // 'targetprocessguid' => '51126098657bd96b286ded7016691792', + // 'targetdynaformguid' => '28421020557bffc5b374850018853291', + // 'targettoclaim' => true, + // 'targetactions' => array( 'RELEASE_DONE' => '@@RELEASE_DONE' ) + // ) ) ; + + $itemtype = str_replace( 'Task', '', $parm->getType() ) ; + + //foreach( $taskList as $targetTask ) { + foreach( $DB->request( 'glpi_plugin_processmaker_caselinks', "is_active = 1 AND sourcetask_guid='".$pmTaskCat->fields['pm_task_guid']."'") as $targetTask ) { + + $srcCaseId = PluginProcessmakerProcessmaker::getCaseIdFromItem( $itemtype, $parm->fields['tickets_id']) ; + + // Must check the condition + $casevariables = array(); + $matches = array() ; + if( preg_match_all( "/@@(\w+)/u", $targetTask['sourcecondition'], $matches ) ) { + $casevariables = $matches[1] ; + } + //foreach( $targetTask['targetactions'] as $actionvalue ){ + foreach( $DB->request( 'glpi_plugin_processmaker_caselinkactions', 'plugin_processmaker_caselinks_id = '.$targetTask['id']) as $actionvalue ){ + $targetTask['targetactions'][$actionvalue['name']] = $actionvalue['value']; + if( preg_match_all( "/@@(\w+)/u", $actionvalue['value'], $matches ) ) { + $casevariables = array_merge( $casevariables, $matches[1] ) ; + } + } + $externalapplication = false ; // by default + if( $targetTask['is_externaldata'] && isset($targetTask['externalapplication']) ) { + // must read some values + $externalapplication = json_decode( $targetTask['externalapplication'], true ) ; + // must be of the form + // {"method":"POST","url":"http://arsupd201.ar.ray.group:8000/search_by_userid/","params":{"user":"@@USER_ID","system":"GPP","list":"@@ROLE_LIST"}} + // Where method is the POST, GET, ... method + // url is the URL to be called + // params is a list of parameters to get from running case + foreach ( $externalapplication['params'] as $paramname => $variable ) { + if( preg_match_all( "/@@(\w+)/u", $variable, $matches ) ) { + $casevariables = array_merge( $casevariables, $matches[1] ) ; + } + } + } + + + // ask for those case variables + $myProcessMaker = new PluginProcessmakerProcessmaker() ; + $myProcessMaker->login( ) ; + // now tries to get the variables to check condition + $infoForTasks = $myProcessMaker->getVariables( $srcCaseId, $casevariables ); + foreach($infoForTasks as $casevar => $varval ){ + $infoForTasks[ "@@$casevar" ] = "'$varval'" ; + unset( $infoForTasks[ $casevar ] ) ; + } + $targetTask['sourcecondition'] = str_replace( array_keys($infoForTasks), $infoForTasks, $targetTask['sourcecondition'] ) ; + + + if( eval( "return ".$targetTask['sourcecondition'].";" ) ){ + // look at each linked ticket if a case is attached and then if a task like $val is TO_DO + // then will try to routeCase for each tasks in $val + + $postdatas = array(); + foreach( $targetTask['targetactions'] as $action => $actionvalue) { + $postdatas['form'][$action] = eval( "return ".str_replace( array_keys($infoForTasks), $infoForTasks, $actionvalue)." ;" ) ; + } + $postdatas['UID'] = $targetTask['targetdynaform_guid']; + $postdatas['__DynaformName__'] = $targetTask['targetprocess_guid']."_".$targetTask['targetdynaform_guid'] ; + $postdatas['__notValidateThisFields__'] = '[]'; + $postdatas['DynaformRequiredFields'] = '[]'; + $postdatas['form']['btnGLPISendRequest'] = 'submit' ; + + //foreach ( $externalapplication['params'] as $paramname => $variable ) { + // $externalapplicationparams[$paramname] = eval( "return ".str_replace( array_keys($infoForTasks), $infoForTasks, $variable)." ;" ) ; + //} + + $externalapplicationparams = array() ; + if( $externalapplication ) { + // must call curl + foreach ( $externalapplication['params'] as $paramname => $variable ) { + $externalapplicationparams[$paramname] = eval( "return ".str_replace( array_keys($infoForTasks), $infoForTasks, $variable)." ;" ) ; + } + $externalapplicationparams['callback']=$CFG_GLPI['root_doc']."/plugins/processmaker/ajax/asynchronousdatas.php"; + $ch = curl_init(); + $externalapplication['url'] = eval( "return '".str_replace( array_keys($infoForTasks), $infoForTasks, $externalapplication['url'])."' ;" ) ; // '??? + curl_setopt($ch, CURLOPT_URL, $externalapplication['url'] ); + } + + if( $targetTask['is_self'] ) { + // MUST BE done on a add task hook, and not on an update task hook + + //$query = "SELECT glpi_plugin_processmaker_cases.id, MAX(glpi_plugin_processmaker_tasks.del_index) AS del_index FROM glpi_tickettasks + // JOIN glpi_plugin_processmaker_taskcategories ON glpi_plugin_processmaker_taskcategories.taskcategories_id=glpi_tickettasks.taskcategories_id + // JOIN glpi_plugin_processmaker_cases ON glpi_plugin_processmaker_cases.processes_id=glpi_plugin_processmaker_taskcategories.processes_id + // RIGHT JOIN glpi_plugin_processmaker_tasks ON glpi_plugin_processmaker_tasks.items_id=glpi_tickettasks.id AND glpi_plugin_processmaker_tasks.case_id=glpi_plugin_processmaker_cases.id + // WHERE glpi_plugin_processmaker_taskcategories.pm_task_guid = '".$targetTask['targettask_guid']."' AND glpi_tickettasks.state = 1 AND glpi_tickettasks.tickets_id=".$parm->fields['tickets_id'] ; + + //$res = $DB->query($query) ; + //if( $res && $DB->numrows($res) > 0 && $case=$DB->fetch_assoc($res) && isset($case['id']) && isset($case['del_index']) ) { + //foreach( $DB->request($query) as $case ) { + $taskCase = $myProcessMaker->taskCase( $srcCaseId ) ; + foreach( $taskCase as $task ) { + // search for target task guid + if( $task->guid == $targetTask['targettask_guid'] ) + break ; + } + + $postdatas['APP_UID'] = $srcCaseId; + $postdatas['DEL_INDEX'] = $task->delegate; + + //need to get the 'ProcessMaker' user + $pmconfig = PluginProcessmakerConfig::getInstance() ; + + $cronaction = new PluginProcessmakerCrontaskaction; + $cronaction->add( array( 'plugin_processmaker_caselinks_id' => $targetTask['id'], + 'itemtype' => $itemtype, + 'items_id' => $parm->fields['tickets_id'], + 'users_id' => $pmconfig->fields['users_id'], + 'toclaim' => $targetTask['targettoclaim'], + 'state' => ($targetTask['is_externaldata'] ? PluginProcessmakerCrontaskaction::WAITING_DATAS : PluginProcessmakerCrontaskaction::DATAS_READY), + 'postdatas' => json_encode( $postdatas, JSON_HEX_APOS | JSON_HEX_QUOT) + ), + null, + false) ; + + if( $externalapplication ) { + // must call external application in order to get the needed data asynchroneously + // must be of the form + // {"url":"http://arsupd201.ar.ray.group:8000/search_by_userid/","params":{"user":"@@USER_ID","system":"GPP","list":"@@ROLE_LIST"}} + // url is the URL to be called + + $externalapplicationparams['record_id'] = $cronaction->getID(); + + $externalapplicationparams = json_encode( $externalapplicationparams, JSON_HEX_APOS | JSON_HEX_QUOT); + //$externalapplicationparams = http_formdata_flat_hierarchy( $externalapplicationparams ) ; + + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $externalapplicationparams); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen($externalapplicationparams))); + + $response = curl_exec ($ch); + + curl_close ($ch); + } +// } + } else { + foreach( Ticket_Ticket::getLinkedTicketsTo( $parm->fields['tickets_id'] ) as $tlink ){ + if( $tlink['link'] == Ticket_Ticket::LINK_TO ) { + $query = "SELECT glpi_plugin_processmaker_cases.id, MAX(glpi_plugin_processmaker_tasks.del_index) AS del_index FROM glpi_tickettasks + JOIN glpi_plugin_processmaker_taskcategories ON glpi_plugin_processmaker_taskcategories.taskcategories_id=glpi_tickettasks.taskcategories_id + JOIN glpi_plugin_processmaker_cases ON glpi_plugin_processmaker_cases.processes_id=glpi_plugin_processmaker_taskcategories.processes_id + RIGHT JOIN glpi_plugin_processmaker_tasks ON glpi_plugin_processmaker_tasks.items_id=glpi_tickettasks.id AND glpi_plugin_processmaker_tasks.case_id=glpi_plugin_processmaker_cases.id + WHERE glpi_plugin_processmaker_taskcategories.pm_task_guid = '".$targetTask['targettask_guid']."' AND glpi_tickettasks.state = 1 AND glpi_tickettasks.tickets_id=".$tlink['tickets_id'] ; + foreach( $DB->request($query) as $case ) { + // must be only one row + + $postdatas['APP_UID'] = $case['id']; + $postdatas['DEL_INDEX'] = $case['del_index']; + + $cronaction = new PluginProcessmakerCrontaskaction; + $cronaction->add( array( 'plugin_processmaker_caselinks_id' => $targetTask['id'], + 'itemtype' => $itemtype, + 'items_id' => $parm->fields['tickets_id'], + 'users_id' => Session::getLoginUserID(), + 'toclaim' => $targetTask['targettoclaim'], + 'state' => ($targetTask['is_externaldata'] ? PluginProcessmakerCrontaskaction::WAITING_DATAS : PluginProcessmakerCrontaskaction::DATAS_READY), + 'postdatas' => json_encode( $postdatas, JSON_HEX_APOS | JSON_HEX_QUOT) + ), + null, + false) ; + } + //if( $externalapplication ) { + // // must call external application in order to get the needed data asynchroneously + // // must be of the form + // // {"method":"POST","url":"http://arsupd201.ar.ray.group:8000/search_by_userid/","params":{"user":"@@USER_ID","system":"GPP","list":"@@ROLE_LIST"}} + // // Where method is the POST, GET + // // url is the URL to be called + // $externalapplicationparams['record_id']=$cronaction->getID(); + // $externalapplicationparams = http_formdata_flat_hierarchy( $externalapplicationparams ) ; + // if( $externalapplication['method'] != 'GET') { + // switch($externalapplication['method']) { + // case 'POST' : + // curl_setopt($ch, CURLOPT_POST, 1); + // curl_setopt($ch, CURLOPT_POSTFIELDS, $externalapplicationparams); + // break; + // } + // } + // $response = curl_exec ($ch); + + // curl_close ($ch); + //} + } + } + } + } + + } + } } \ No newline at end of file diff --git a/inc/case.class.php b/inc/case.class.php index 2b4efe9..7db7661 100644 --- a/inc/case.class.php +++ b/inc/case.class.php @@ -544,7 +544,7 @@ class PluginProcessmakerCase extends CommonDBTM { echo ""; echo ""; // Dropdown::show('PluginProcessmakerProcessmaker', array( 'entity' => $item->fields['entities_id'], 'name' => 'plugin_processmaker_process_id', 'condition' => "is_active=1")); // condition is used to prevent start of none-active cases - PluginProcessmakerProcess::dropdown(array( 'entity' => $item->fields['entities_id'], 'name' => 'plugin_processmaker_process_id', 'condition' => "is_active=1")); + PluginProcessmakerProcess::dropdown(array( 'value' => 0, 'entity' => $item->fields['entities_id'], 'name' => 'plugin_processmaker_process_id', 'condition' => "is_active=1")); echo ""; @@ -648,7 +648,7 @@ class PluginProcessmakerCase extends CommonDBTM { */ public static function canSolve ($parm) { $myCase = new self; - if( $myCase->getCaseFromItemTypeAndItemId( $parm->getType(), $parm->getID() ) ) { + if( $myCase->getCaseFromItemTypeAndItemId( $parm['item']->getType(), $parm['item']->getID() ) ) { $pmVar = $myCase->getVariables( array( 'GLPI_ITEM_CAN_BE_SOLVED' ) ) ; if( $myCase->fields['case_status'] != 'COMPLETED' && $myCase->fields['case_status'] != 'CANCELLED' && (!isset($pmVar['GLPI_ITEM_CAN_BE_SOLVED']) || $pmVar['GLPI_ITEM_CAN_BE_SOLVED'] != 1) ) { // then item can't be solved diff --git a/inc/caselink.class.php b/inc/caselink.class.php new file mode 100644 index 0000000..7ef6e54 --- /dev/null +++ b/inc/caselink.class.php @@ -0,0 +1,12 @@ +status_code = $status ; -// $this->message = $message ; -// if( $time_st == '' ) -// $this->time_stamp = date() ; -// else -// $this->time_stamp = $time_st ; -// } - -//} - - $pmHideSolution = false ; +if( !function_exists('http_formdata_flat_hierarchy') ) { /** * Summary of http_formdata_flat_hierarchy * @param mixed $data @@ -72,6 +48,7 @@ class getVariableStruct { return $vars; } +} /** * PluginProcessmakerProcessmaker short summary. @@ -103,7 +80,6 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { * * @return string **/ - static function getTable() { return "glpi_plugin_processmaker_processes"; @@ -113,10 +89,12 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { * Summary of addTicketFollowup * @param mixed $itemId * @param mixed $txtForFollowup + * @param integer $users_id optional, if null will uses logged-in user */ - public function addTicketFollowup( $itemId, $txtForFollowup ) { + public function addTicketFollowup( $itemId, $txtForFollowup, $users_id=null ) { $fu = new TicketFollowup() ; - $input = array() ; + $fu->getEmpty() ; // to get default values + $input = $fu->fields ; if( isset( $txtForFollowup['GLPI_TICKET_FOLLOWUP_CONTENT'] ) ) { $input['content']=$txtForFollowup['GLPI_TICKET_FOLLOWUP_CONTENT']; } @@ -127,7 +105,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $input['requesttypes_id']=$txtForFollowup['GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID']; } $input['tickets_id']=$itemId; - $input['users_id']= Session::getLoginUserID( true ) ; // $this->taskWriter; + $input['users_id']= (isset($users_id) ? $users_id : Session::getLoginUserID( true )) ; // $this->taskWriter; $fu->add( $input ) ; } @@ -192,38 +170,10 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { // return $tab; //} - //function useSession( $session, $lang = "en" ) { - // try { - // if( $this->openSoap( $lang ) ) { - // $this->pmSession = $session ; - // } - - // return $this->pmSession ; - // } - // catch ( Exception $e ) { - // Toolbox::logDebug( $e ); - // } - //} - - - //function openSession($username = "glpi", $password = "md5:2b0a4830b22f1f5ef5f8c239f9c8f07e", $lang="en" ) { - // try { - // if( $this->openSoap( $lang ) ) { - // $locSession = $this->pmSoapClient->login( array( 'userid' => $username, 'password' => $password) ) ; - // if( $locSession->status_code == 0 ) - // $this->pmSession = $locSession->message ; - // } - - // return $this->pmSession ; - // } - // catch ( Exception $e ) { - // Toolbox::logDebug( $e ); - // } - //} /** * Summary of login - * + * @param mixed $admin_or_user if true will be admin, otherwise is user name (or user id), or current user * @return true if login has been correctly done with current GLPI user, or if a PM session was already open * false if an exception occured (like SOAP error or PM login error) */ @@ -253,7 +203,11 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { // get the password of the user $pmusr = new PluginProcessmakerUser ; $gusr = new User ; - $gusr->getFromDBbyName( ($admin_or_user !== false ? $admin_or_user : $_SESSION["glpiname"]) ) ; + if( is_numeric($admin_or_user) ) { + $gusr->getFromDB( $admin_or_user ) ; + } else { + $gusr->getFromDBbyName( $admin_or_user !== false ? $admin_or_user : $_SESSION["glpiname"]) ; + } $pmusr->getFromDB( $gusr->getID() ) ; if( !isset($pmusr->fields['password']) || $pmusr->fields['password'] == "" ) { $pass = md5(Toolbox::encrypt( $gusr->getID().$gusr->getName().time(), GLPIKEY) ) ; @@ -264,7 +218,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $PM_DB->query("UPDATE rbac_users SET USR_PASSWORD='".$pass."' WHERE USR_UID='".$pmusr->fields['pm_users_id']."' ") ; $PM_DB->query("UPDATE users SET USR_PASSWORD='".$pass."' WHERE USR_UID='".$pmusr->fields['pm_users_id']."' ") ; } - $locSession = $this->pmSoapClient->login( array( 'userid' => ($admin_or_user !== false ? $admin_or_user : $_SESSION["glpiname"]), 'password' => 'md5:'.$pmusr->fields['password']) ) ; + $locSession = $this->pmSoapClient->login( array( 'userid' => $gusr->fields['name'], 'password' => 'md5:'.$pmusr->fields['password']) ) ; if( is_object( $locSession ) && $locSession->status_code == 0 ) { $_SESSION["pluginprocessmaker"]["session"]["id"] = $locSession->message ; $_SESSION["pluginprocessmaker"]["session"]["date"] = $locSession->timestamp ; @@ -438,7 +392,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { * Embedded taskList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#taskList.28.29) * A session must be open before with login() * Normalizes output to an array, even when only one element is returned by PM - * @return an array of taskListStruct objects, or false when exception occured + * @return array of taskListStruct objects, or false when exception occured */ function taskCase( $caseId ) { try { @@ -739,7 +693,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { * @param string $caseId The uID of the case * @param array $vars an array of variable name that will be read from the case as case variables * Normalizes output to an array, even when only one element is returned by PM - * @return an associative array (variable_name => value), or false when exception occured. The return array can be empty if requested variables are not found. + * @return array: an associative array (variable_name => value), or false when exception occured. The return array can be empty if requested variables are not found. */ function getVariables( $caseId, $vars = array() ) { try { @@ -987,12 +941,95 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { // return array('description' => $LANG['processmaker']['cron']['pmnotifications'] ); case 'pmorphancases' : return array('description' => $LANG['processmaker']['cron']['pmorphancases']['description'], 'parameter' => $LANG['processmaker']['cron']['pmorphancases']['parameter'] ); + case 'pmtaskactions' : + return array('description' => $LANG['processmaker']['cron']['pmtaskactions'] ); } return array(); } /** - * summary of cronOrphanCases + * summary of cronPMTaskActions + * Execute 1 task managed by the plugin + * @param: $task CronTask class for log / stat + * @return integer + * >0 : done + * <0 : to be run again (not finished) + * 0 : nothing to do + */ + static function cronPMTaskActions($task) { + global $DB, $CFG_GLPI; + + $actionCode = 0; // by default + $error = false ; + $task->setVolume(0); // start with zero + + $pm = new self; + $existingpmsession = isset($_SESSION["pluginprocessmaker"]["session"]) ; + $formerusers_id = 0 ; + // get the list of taskactions to be done + foreach( $DB->request( getTableForItemType('PluginProcessmakerCrontaskaction'), ' `state` = '.PluginProcessmakerCrontaskaction::DATAS_READY ) as $taskaction ) { + + try{ + + if( $formerusers_id != $taskaction['users_id']) { + unset($_SESSION["pluginprocessmaker"]["session"]) ; // to reset previous user login if any + } + + $pm->login($taskaction['users_id']); + + $postdatas = json_decode($taskaction['postdatas'], true) ; + + if( $taskaction['toclaim'] ) { + // must do a claim before solving task + if( !$pm->claimCase( $postdatas['APP_UID'], $postdatas['DEL_INDEX'] ) ) + throw new Exception("Can't claim case"); + + $donotif = $CFG_GLPI["use_mailing"]; + $CFG_GLPI["use_mailing"] = false ; + + // now manage tasks associated with item + $pm->claimTask( $postdatas['APP_UID'], $postdatas['DEL_INDEX'], $taskaction['users_id'] ) ; + + $CFG_GLPI["use_mailing"] = $donotif ; + + } + $myCase = new PluginProcessmakerCase ; + if( $myCase->getFromDB( $postdatas['APP_UID'] )) { + + //$cookies = json_decode($taskaction['cookies'], true) ; + $pm->derivateCase( $myCase, $postdatas, $taskaction['users_id'] ) ; + } + + $tkaction = new PluginProcessmakerCrontaskaction; + $tkaction->update( array( 'id' => $taskaction['id'], 'state' => PluginProcessmakerCrontaskaction::DONE ) ) ; + + $task->addVolume(1); + $task->log( "Applied task action id: '".$taskaction['id']."'" ) ; + + } catch( Exception $e ) { + $task->log( "Can't apply task action id: '".$taskaction['id']."'" ) ; + $error = true ; + } + + $formerusers_id = $taskaction['users_id'] ; + } + + if( $existingpmsession ) { + unset($_SESSION["pluginprocessmaker"]["session"]) ; // reset the one created during the foreach + if (!Session::isCron()) { + $pm->login(); // re-log default user + } + } + + + if($error) + return -1 ; + else + return $actionCode; + + } + /** + * summary of cronPMOrphanCases * Execute 1 task managed by the plugin * @param: $task CronTask class for log / stat * @return integer @@ -1003,6 +1040,10 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { static function cronPMOrphanCases($task) { global $PM_DB, $DB ; + if (!isset($PM_DB)) { + $PM_DB = new PluginProcessmakerDB ; + } + // get list of case assigned to GLPi items $draftCases = array(0) ; $query = "SELECT case_num FROM glpi_plugin_processmaker_cases WHERE case_status = 'DRAFT';" ; @@ -1125,7 +1166,11 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { * 0 : nothing to do */ static function cronPMUsers($task) { - global $DB, $PM_DB, $GLOBALS ; + global $DB, $PM_DB ; + + if (!isset($PM_DB)) { + $PM_DB = new PluginProcessmakerDB ; + } $actionCode = 0; // by default $error = false ; @@ -1153,8 +1198,8 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { foreach($DB->request("SELECT glpi_users.id, glpi_users.name, glpi_users.realname, glpi_users.firstname, glpi_users.is_active, glpi_users.is_deleted, glpi_plugin_processmaker_users.pm_users_id as pmUserId FROM glpi_users LEFT JOIN glpi_plugin_processmaker_users on glpi_plugin_processmaker_users.id = glpi_users.id - WHERE name not like '*%'") as $dbuser) { - $glpiUserList[ strtolower($dbuser['name'])] = $dbuser ; + WHERE name not like '*%'") as $dbgroup) { + $glpiUserList[ strtolower($dbgroup['name'])] = $dbgroup ; } $arrayDiff = array_diff_key( $glpiUserList, $pmUserList ) ; @@ -1259,50 +1304,57 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { - // so now treat GLPI pseudo-groups - foreach($DB->request("SELECT id, name, realname, firstname, is_active, is_deleted FROM glpi_users WHERE name LIKE '*%'") as $dbuser) { - $glpiPseudoUserList[$dbuser['name']] = $dbuser ; + // so now treat GLPI groups + $glpiGroupList = array(); + foreach($DB->request("SELECT id, name, is_task, is_usergroup FROM glpi_groups WHERE is_task=1 AND is_usergroup=1") as $dbgroup) { + $glpiGroupList[$dbgroup['name']] = $dbgroup; } - foreach($PM_DB->request("SELECT * FROM content WHERE content.CON_CATEGORY='GRP_TITLE' AND content.CON_LANG='en'") as $dbuser){ - $pmGroupList[$dbuser['CON_VALUE']] = $dbuser ; - } + $pmGroupList = self::getPMGroups(); // array(); + //foreach($PM_DB->request("SELECT * FROM content WHERE content.CON_CATEGORY='GRP_TITLE' AND content.CON_LANG='en'") as $dbgroup){ + // $pmGroupList[$dbgroup['CON_VALUE']] = $dbgroup; + //} // here we can compare group lists like done for the users - $arrayDiff = array_diff_key( $glpiPseudoUserList, $pmGroupList ) ; + $arrayDiff = array_diff_key( $glpiGroupList, $pmGroupList ) ; - // then for each pseudo-group we must check if it exists, and if not create a real PM group - foreach( $arrayDiff as $pseudoGroup ) { + // then for each group we must check if it exists, and if not create a real PM group + foreach( $arrayDiff as $group ) { // it is not existing in PM // then create - $pmResult = $myProcessMaker->createGroup( $pseudoGroup['name'] ) ; + $pmResult = $myProcessMaker->createGroup( $group['name'] ) ; if( $pmResult->status_code == 0) { $task->addVolume(1); - $task->log( "Added group: '".$pseudoGroup['name']."'" ) ; + $task->log( "Added group: '".$group['name']."'" ) ; } } - // review and update all users in each pseudo-groups - $pmGroupList = array() ; // reset groups and get the new complete list from PM DB - foreach($PM_DB->request("SELECT * FROM content WHERE content.CON_CATEGORY='GRP_TITLE' AND content.CON_LANG='en'") as $dbuser){ - $pmGroupList[$dbuser['CON_VALUE']] = $dbuser ; - } + // review and update all users in each group + $pmGroupList = self::getPMGroups(); // array(); + //$pmGroupList = array() ; // reset groups and get the new complete list from PM DB + //foreach($PM_DB->request("SELECT * FROM content WHERE content.CON_CATEGORY='GRP_TITLE' AND content.CON_LANG='en'") as $dbgroup){ + // $pmGroupList[$dbgroup['CON_VALUE']] = $dbgroup ; + //} // now should refresh the existing users into groups - $arrayDiff = array_intersect_key( $glpiPseudoUserList, $pmGroupList ) ; - foreach( $arrayDiff as $pseudoGroup ){ - // for each pseudo group will delete users and re-create them + $arrayDiff = array_intersect_key( $glpiGroupList, $pmGroupList ) ; + foreach( $arrayDiff as $group ){ + // for each group will delete users and re-create them // not really optimized, but this way we are sure that groups are synchronized // must be redesigned - $query = "DELETE FROM group_user WHERE group_user.GRP_UID='".$pmGroupList[$pseudoGroup['name']]['CON_ID']."';"; + $query = "DELETE FROM group_user WHERE group_user.GRP_UID='".$pmGroupList[$group['name']]['CON_ID']."';"; $PM_DB->query( $query ) ; // and insert all users from real GLPI group - foreach( $DB->request("select glpi_groups_users.users_id, glpi_plugin_processmaker_users.pm_users_id from glpi_groups join glpi_groups_users on glpi_groups_users.groups_id=glpi_groups.id join glpi_plugin_processmaker_users on glpi_plugin_processmaker_users.id=glpi_groups_users.users_id where glpi_groups.name='".$pseudoGroup['name']."'") as $user ) { - $query = "INSERT INTO group_user (`GRP_UID`, `USR_UID`) VALUES ( '".$pmGroupList[$pseudoGroup['name']]['CON_ID']."', '".$user['pm_users_id']."' )" ; + foreach( $DB->request("SELECT glpi_groups_users.users_id, glpi_plugin_processmaker_users.pm_users_id + FROM glpi_groups + JOIN glpi_groups_users ON glpi_groups_users.groups_id=glpi_groups.id + JOIN glpi_plugin_processmaker_users ON glpi_plugin_processmaker_users.id=glpi_groups_users.users_id + WHERE glpi_groups.name='".$group['name']."'") as $user ) { + $query = "INSERT INTO group_user (`GRP_UID`, `USR_UID`) VALUES ( '".$pmGroupList[$group['name']]['CON_ID']."', '".$user['pm_users_id']."' )" ; $PM_DB->query( $query ) ; } $task->addVolume(1); - $task->log( "Updated users into PM group: '".$pseudoGroup['name']."'" ) ; + $task->log( "Updated users into PM group: '".$group['name']."'" ) ; } // now should renew the duedate of the users @@ -1327,10 +1379,17 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $caseInfo = $myProcessMaker->getCaseInfo( $parm->input['processmaker_caseid'], $parm->input['processmaker_delindex']) ; $parm->input['name'] = $PM_DB->escape($caseInfo->caseName ) ; - $caseInitialDueDate = $myProcessMaker->getVariables( $parm->input['processmaker_caseid'], array( 'GLPI_ITEM_INITIAL_DUE_DATE' )) ; + $caseInitialDueDate = $myProcessMaker->getVariables( $parm->input['processmaker_caseid'], array( 'GLPI_ITEM_TITLE', 'GLPI_ITEM_INITIAL_DUE_DATE' )) ; if( array_key_exists( 'GLPI_ITEM_INITIAL_DUE_DATE', $caseInitialDueDate ) ) { $parm->input['due_date'] = $caseInitialDueDate[ 'GLPI_ITEM_INITIAL_DUE_DATE' ]." 23:59:59" ; } + $txtItemTitle = $caseInfo->caseName; + if( array_key_exists( 'GLPI_ITEM_TITLE', $caseInitialDueDate ) ) { + $txtItemTitle = $caseInitialDueDate[ 'GLPI_ITEM_TITLE' ] ; + // reset those variables + $resultSave = $myProcessMaker->sendVariables( $parm->input['processmaker_caseid'] , array( "GLPI_ITEM_TITLE" => '') ) ; + } + $parm->input['name'] = $PM_DB->escape($txtItemTitle ) ; $procDef = new PluginProcessmakerProcess; $procDef->getFromDBbyExternalID( $caseInfo->processId ) ; @@ -1371,7 +1430,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { // here we create a fake task that will be used to store the creator of the case // this is due for traceability only - $myProcessMaker->add1stTask( $myCase->fields['itemtype'], $myCase->fields['items_id'], $caseInfo); + $myProcessMaker->add1stTask( $myCase->fields['itemtype'], $myCase->fields['items_id'], $caseInfo, array( 'notif' => false) ); // no notif // route case $pmRouteCaseResponse = $myProcessMaker->routeCase( $myCase->getID(), $parm->input['processmaker_delindex'] ) ; @@ -1397,11 +1456,16 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { "GLPI_ITEM_SET_STATUS" => '' ) ) ; // routing has been done, then solve 1st task - $myProcessMaker->solveTask( $myCase->getID(), $parm->input['processmaker_delindex'], $txtToAppendToTask ) ; + $myProcessMaker->solveTask( $myCase->getID(), $parm->input['processmaker_delindex'], array( 'txtToAppend' => $txtToAppendToTask, 'notif' => false) ) ; // and create GLPI tasks for the newly created PM tasks. foreach( $pmRouteCaseResponse->routing as $route ) { - $myProcessMaker->addTask( $myCase->fields['itemtype'], $myCase->fields['items_id'], $caseInfo, $route->delIndex, PluginProcessmakerUser::getGLPIUserId( $route->userId ), 0, $route->taskId ) ; + $myProcessMaker->addTask( $myCase->fields['itemtype'], + $myCase->fields['items_id'], + $caseInfo, $route->delIndex, + PluginProcessmakerUser::getGLPIUserId( $route->userId ), + 0, + $route->taskId ) ; } if( $itemSetStatus != '' ) { @@ -1453,54 +1517,78 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { } - //function getTabNameForItem(CommonGLPI $item, $withtemplate=0) { - // global $LANG; - - // if (!$withtemplate) { - // switch ($item->getType()) { - // case 'Phone' : - // if ($_SESSION['glpishow_count_on_tabs']) { - // return self::createTabEntry('Example', - // countElementsInTable($this->getTable())); - // } - // return 'Example'; - // } - // } - // return ''; - //} - - ///** - // * Summary of displayTabContentForItem - // * @param CommonGLPI $item - // * @param integer $tabnum - // * @param integer $withtemplate - // * @return boolean - // */ - //static function displayTabContentForItem(CommonGLPI $item, integer $tabnum=1, integer $withtemplate=0) { - - // if ($item->getType()=='Phone') { - // echo "Plugin Example on Phone"; - // } - // return true; - //} + /** + * Summary of addWatcher + * add $techId as watcher to $glpi_item when techId has no rights on it + * @param string $itemType is the type of the CommonITILObject + * @param integer $itemId is the id of the ITIL object + * @param integer $techId is the users_id to be added + * @return boolean true if added, + */ + public static function addWatcher( $itemType, $itemId, $techId ) { + global $CFG_GLPI; // currently use $CFG_GLPI to disable notif + //$plug = new Plugin; + if( $techId && $itemType != '' && $itemId > 0 ) { //!$plug->isActivated('arbehaviours') && + $glpi_item = getItemForItemtype( $itemType ); + $glpi_item->getFromDB( $itemId ) ; + // then we should check if this user has rights on the item, if not then we must add it to the watcher list! + $glpi_item = getItemForItemtype( $itemType ); + $glpi_item->getFromDB( $itemId ) ; + $user_entities = Profile_User::getUserEntities( $techId, true, true ) ; + $user_can_view = in_array( $glpi_item->fields['entities_id'], $user_entities ); + if( !$glpi_item->isUser( CommonITILActor::REQUESTER, $techId ) + && !$glpi_item->isUser( CommonITILActor::OBSERVER, $techId ) + && !$glpi_item->isUser( CommonITILActor::ASSIGN, $techId ) + && !$user_can_view ) { + // then we must add this tech user to watcher list + $glpi_item_user = getItemForItemtype( $glpi_item->getType() . "_User" ); + $donotif = $CFG_GLPI["use_mailing"]; + $CFG_GLPI["use_mailing"] = false ; + $glpi_item_user->add( array( $glpi_item::getForeignKeyField() => $glpi_item->getId(), 'users_id' => $techId, 'type' => CommonITILActor::OBSERVER, '_disablenotif' => true ) ) ; // , '_no_notif' => true + $CFG_GLPI["use_mailing"]= $donotif; + return true; + } + } + return false; + } /** * Summary of addTask * adds a GLPI task to given item - * @param $itemType String item type to which a task must be added - * @param $iteId integer item# to which a task must be added - * @param $caseInfo getCaseInfoResponse object (see: getCaseInfo() function) - * @param $del_index integer index of the delegation - * @param $techId integer GLPI user id to which a task must be assigned, if == 0 then we should look-up in DB the pseudo-group to be assigned to the task + * @param $itemType string item type to which a task will be added + * @param $itemId integer item id to which a task will be added + * @param $caseInfo mixed getCaseInfoResponse object (see: getCaseInfo() function) + * @param $delIndex integer index of the delegation + * @param $techId integer GLPI user id to which a task must be assigned, if == 0 will use $groupId and/or $pmTaskId + * @param $groupId string PM group guid to assign to task, used when $techId == 0 + * @param $pmTaskId string PM task guid, used when $groupId == 0 AND $techID == 0 + * @param $options array of options, default values are + * 'txtTaskContent' => '', + * 'start_date' => '', + * 'end_date' => '', + * 'notif' => true * @return */ - public function addTask( $itemType, $itemId, $caseInfo, $delIndex, $techId, $groupId, $pmTaskId, $txtTaskContent = '', $start_date = '', $end_date = '' ) { - global $DB, $PM_DB, $LANG, $CFG_GLPI, $_SESSION ; + public function addTask( $itemType, $itemId, $caseInfo, $delIndex, $techId, $groupId, $pmTaskId, $options=array() ) { + global $DB, $PM_DB, $LANG, $CFG_GLPI, $_SESSION ; + + $default_options = array( + 'txtTaskContent' => '', + 'start_date' => '', + 'end_date' => '', + 'notif' => true + ) ; + foreach($default_options as $key => $opt){ + if(!isset($options[$key])){ + $options[$key] = $opt ; + } + } $glpi_task = getItemForItemtype( "{$itemType}Task" ); + $glpi_task->getEmpty(); $input = array() ; // will contain all data for the Task @@ -1514,96 +1602,67 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $pmProcess = new PluginProcessmakerProcess ; $pmProcess->getFromDB( $pmtaskcat->fields['processes_id'] ) ; - if( $start_date == '' ) { - $start_date = new DateTime( $_SESSION["glpi_currenttime"] ) ; + if( $options['start_date'] == '' ) { + $options['start_date'] = new DateTime( $_SESSION["glpi_currenttime"] ) ; } else { - $start_date = new DateTime( $start_date ) ; + $options['start_date'] = new DateTime( $options['start_date'] ) ; } - $input['begin'] = $start_date->format("Y-m-d H:i:s"); + $input['begin'] = $options['start_date']->format("Y-m-d H:i:s"); - if( $end_date == '' || $end_date <= $input['begin']) { - $end_date = $start_date ; - $end_date->add( new DateInterval('PT1M') ) ; + if( $options['end_date'] == '' || $options['end_date'] <= $input['begin']) { + $options['end_date'] = clone $options['start_date'] ; + $options['end_date']->add( new DateInterval('PT15M') ) ; } else { - $end_date = new DateTime( $end_date ) ; + $options['end_date'] = new DateTime( $options['end_date'] ) ; + } + $input['end'] = $options['end_date']->format("Y-m-d H:i:s") ; + $input['plan']['begin'] = $input['begin']; + $temp = $options['start_date']->diff( $options['end_date'] ); + $input['plan']['_duration'] = $temp->d * DAY_TIMESTAMP + $temp->h * HOUR_TIMESTAMP + $temp->i * MINUTE_TIMESTAMP + $temp->s; + if( $input['plan']['_duration'] == 0 ) { + $input['plan']['_duration'] = 60; // at least } - $input['end'] = $end_date->format("Y-m-d H:i:s") ; - //if( $end_date == '' ) { - // $loc_date = new DateTime( $_SESSION["glpi_currenttime"] ) ; - // $input['begin'] = $loc_date->format("Y-m-d H:i:s"); - // $loc_date->add( new DateInterval('PT1M') ) ; - // $input['end'] = $loc_date->format("Y-m-d H:i:s") ; - //} else { - // $loc_date = new DateTime( $end_date) ; - // $input['end'] = $loc_date->format("Y-m-d H:i:s") ; - // $loc_date->sub( new DateInterval('PT1M') ) ; - // $input['begin'] = $loc_date->format("Y-m-d H:i:s"); - //} - - //$input['date'] = $start_date->format("Y-m-d H:i:s"); $input['users_id'] = $this->taskWriter ; - $user_can_view = true ; // by default - $plug = new Plugin; - // manage groups if( $techId == 0 ) { // then we must look-up DB to get the pseudo-group that will be assigned to the task - $pseudogroup=''; + $groupname=''; if( $groupId == 0 ) { $query = "SELECT content.CON_VALUE FROM task_user JOIN content ON content.CON_ID=task_user.USR_UID AND content.CON_CATEGORY='GRP_TITLE' AND content.CON_LANG = 'en' WHERE task_user.tas_uid='$pmTaskId' AND task_user.tu_relation=2 LIMIT 1;" ; - //$query = "select glpi.glpi_users.id as glpi_user_id from wf_workflow.task_user - // join wf_workflow.content on wf_workflow.content.CON_ID=wf_workflow.task_user.USR_UID and wf_workflow.content.CON_CATEGORY='GRP_TITLE' and wf_workflow.content.CON_LANG = 'en' - // join glpi.glpi_users on glpi.glpi_users.name=wf_workflow.content.CON_VALUE COLLATE utf8_unicode_ci - // where wf_workflow.task_user.tas_uid='$pmTaskId' and wf_workflow.task_user.tu_relation=2 LIMIT 1;" ; } else { $query = "SELECT CON_VALUE FROM content WHERE content.CON_ID='$groupId' AND content.CON_CATEGORY='GRP_TITLE' AND content.CON_LANG = 'en' ;" ; - //$query = "select glpi.glpi_users.id as glpi_user_id from wf_workflow.content - // join glpi.glpi_users on glpi.glpi_users.name=wf_workflow.content.CON_VALUE COLLATE utf8_unicode_ci - // where wf_workflow.content.CON_ID='$groupId' and wf_workflow.content.CON_CATEGORY='GRP_TITLE' and wf_workflow.content.CON_LANG = 'en' ;" ; } // as there is a LIMIT of 1 // or // as there is only one group per guid // then we should have at maximun 1 record foreach( $PM_DB->request($query) as $onlyrec ) { - $pseudogroup = $onlyrec['CON_VALUE'] ; + $groupname = $onlyrec['CON_VALUE'] ; } - $query = "SELECT glpi.glpi_users.id AS glpi_user_id FROM glpi.glpi_users WHERE glpi.glpi_users.name LIKE '$pseudogroup';"; + $groups_id_tech = 0; + $query = "SELECT id AS glpi_group_id FROM glpi_groups WHERE name LIKE '$groupname';"; $res = $DB->query($query) ; if( $DB->numrows($res) > 0) { $row = $DB->fetch_array( $res ) ; - $techId = $row['glpi_user_id'] ; + $groups_id_tech = $row['glpi_group_id'] ; } - } elseif( !$plug->isActivated('arbehaviours') ) { // check is done during Task add in this plugin - // this is a real user not a pseudo-user - // then we should check if this user has rights on the item, if not then we must add it to the watcher list! - $glpi_item = getItemForItemtype( $itemType ); - $glpi_item->getFromDB( $itemId ) ; - //$glpi_tech = new User() ; - //$glpi_tech->getFromDB( $techId ) ; - // several possibilities - // $techId may be requester - $user_entities = Profile_User::getUserEntities( $techId, true, true ) ; - $user_can_view = in_array( $glpi_item->fields['entities_id'], $user_entities ); - if( !$glpi_item->isUser( CommonITILActor::REQUESTER, $techId ) && !$glpi_item->isUser( CommonITILActor::OBSERVER, $techId ) && !$glpi_item->isUser( CommonITILActor::ASSIGN, $techId ) && !$user_can_view ) { - // then we must add this tech user to watcher list - $glpi_item_user = getItemForItemtype( "{$itemType}_User" ); - $glpi_item_user->add( array( strtolower(getPlural( $itemType )).'_id' => $itemId, 'users_id' => $techId, 'type' => CommonITILActor::OBSERVER, '_no_notif' => true ) ) ; - } + } else { + // adds the user tech to ticket watcher if neccessary + self::addWatcher( $itemType, $itemId, $techId ); } // manage task description $input['content'] = "" ; // by default empty :) - if( $txtTaskContent != '' ) { - $input['content'] = $txtTaskContent ; + if( $options['txtTaskContent'] != '' ) { + $input['content'] = $options['txtTaskContent'] ; } elseif( !$pmProcess->fields["hide_case_num_title"] ) { $input['content'] = $LANG['processmaker']['item']['task']['case'].$caseInfo->caseName ; @@ -1618,25 +1677,23 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $input['is_private'] = 0 ; $input['actiontime'] = 0 ; - //$input['begin'] = $start_date->format("Y-m-d H:i:s"); - //$start_date->add( new DateInterval('PT1M') ) ; - //$input['end'] = $start_date->format("Y-m-d H:i:s") ; $input['state'] = 1 ; // == TO_DO - $input['users_id_tech'] = $techId ; // Session::getLoginUserID() ; //PluginProcessmakerUsers::getGLPIUserId( $pmInfo['caseInfo']->currentUsers[0]->userId ) ; + if( $techId ) { + $input['users_id_tech'] = $techId; + } elseif( $groups_id_tech ) { + $input['groups_id_tech'] = $groups_id_tech; + } + $donotif = $CFG_GLPI["use_mailing"]; + if( !$options['notif'] ) { + //$input['_no_notif'] = true; + $CFG_GLPI["use_mailing"] = false; + } $glpi_task->add( Toolbox::addslashes_deep( $input ) ) ; + $CFG_GLPI["use_mailing"] = $donotif; if($glpi_task->getId() > 0 ) { - // task has been created then send notifications for tech with no default rigths to the item entity - // now done in GLPI core - //if( !$user_can_view ) { - // // to cheat the entity rigths, passes default user_entity to raiseEvent(), to be sure that task_tech will receive a notification. - // // drawback: notifications that are entity based could be missing. - // // tip: $user_entities[0] is the user's default entity - // NotificationEvent::raiseEvent('add_task', $glpi_item, array( 'entities_id' => $user_entities[0], 'task_id' => $glpi_task->getId(), 'is_private' => 0 ) ) ; - //} - - // and store link to task in DB + // stores link to task in DB $query = "INSERT INTO glpi_plugin_processmaker_tasks (items_id, itemtype, case_id, del_index) VALUES (".$glpi_task->getId().", '".$glpi_task->getType()."', '".$caseInfo->caseId."', ".$delIndex.");" ; $DB->query( $query ) ; } @@ -1645,15 +1702,42 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { /** * Summary of add1stTask * adds a GLPI task to ticket - * @param $ticket_id integer ticket# to which a task must be added - * @param $caseInfo getCaseInfoResponse object (see: getCaseInfo() function) + * @param $intemType string itemtype of object (Ticket, Problem, ....) + * @param $itemId integer item id to which a task will be added + * @param $caseInfo mixed getCaseInfoResponse object (see: getCaseInfo() function) + * @param $options array of options, defaults are: + * 'txtTaskContent' => '', is content of the task + * 'userId' => false, is user id to be assigned to task + * 'notif' => true, if true notifications will be sent * @return */ - public function add1stTask ( $itemType, $itemId, $caseInfo, $txtTaskContent='', $userId=false ) { + public function add1stTask ( $itemType, $itemId, $caseInfo, $options=array() ) { + + $default_options = array( + 'txtTaskContent' => '', + 'userId' => false, + 'notif' => true + ) ; + foreach($default_options as $key => $opt){ + if(!isset($options[$key])){ + $options[$key] = $opt ; + } + } $start_date = new DateTime( $_SESSION["glpi_currenttime"] ) ; $official_date_time = $_SESSION["glpi_currenttime"] ; $_SESSION["glpi_currenttime"] = $start_date->sub(new DateInterval("PT1S"))->format("Y-m-d H:i:s") ; - $this->addTask( $itemType, $itemId, $caseInfo, $caseInfo->currentUsers[0]->delIndex, ($userId ? $userId : Session::getLoginUserID()), 0, $caseInfo->currentUsers[0]->taskId, $txtTaskContent ) ; + $userId = $options['userId'] ? $options['userId'] : Session::getLoginUserID() ; + unset($options['userId']); // unset it as it's not in the options of addTask + + $this->addTask( $itemType, + $itemId, + $caseInfo, + $caseInfo->currentUsers[0]->delIndex, + $userId, + 0, + $caseInfo->currentUsers[0]->taskId, + $options + ) ; $_SESSION["glpi_currenttime"] = $official_date_time ; } @@ -1704,7 +1788,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { * @param mixed $newTech */ public function reassignTask ( $caseId, $delIndex, $newDelIndex, $newTech) { - global $DB ; + global $DB, $CFG_GLPI ; // $CFG_GLPI is only used to _disablenotif $query = "SELECT * FROM glpi_plugin_processmaker_tasks WHERE case_id='$caseId' and del_index=$delIndex; "; $res = $DB->query($query) ; @@ -1714,21 +1798,28 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $glpi_task->getFromDB( $row['items_id'] ) ; $itemType = str_replace( 'Task', '', $row['itemtype'] ) ; - $glpi_item = getItemForItemtype( $itemType ); - $glpi_item->getFromDB( $glpi_task->fields[ getForeignKeyFieldForItemType( $itemType ) ] ) ; + $foreignkey = getForeignKeyFieldForItemType( $itemType ) ; - $plug = new Plugin; - if( !$plug->isActivated('arbehaviours') ) { // check is done during Task update in this plugin - $user_entities = Profile_User::getUserEntities( $newTech, true, true ) ; - $user_can_view = in_array( $glpi_item->fields['entities_id'], $user_entities ); - if( !$glpi_item->isUser( CommonITILActor::REQUESTER, $newTech ) && !$glpi_item->isUser( CommonITILActor::OBSERVER, $newTech ) && !$glpi_item->isUser( CommonITILActor::ASSIGN, $newTech ) && !$user_can_view ) { - // then we must add this tech user to watcher list - $glpi_item_user = getItemForItemtype( "{$itemType}_User" ); - $glpi_item_user->add( array( $glpi_item->getForeignKeyField() => $glpi_item->getId() , 'users_id' => $newTech, 'type' => CommonITILActor::OBSERVER, '_no_notif' => true ) ) ; - } - } + //$glpi_item = getItemForItemtype( $itemType ); + //$glpi_item->getFromDB( $glpi_task->fields[ getForeignKeyFieldForItemType( $itemType ) ] ) ; - $glpi_task->update( array( 'id' => $row['items_id'], $glpi_item->getForeignKeyField() => $glpi_item->getId(), 'users_id_tech' => $newTech )) ; + //$plug = new Plugin; + //if( !$plug->isActivated('arbehaviours') ) { // check is done during Task update in this plugin + // $user_entities = Profile_User::getUserEntities( $newTech, true, true ) ; + // $user_can_view = in_array( $glpi_item->fields['entities_id'], $user_entities ); + // if( !$glpi_item->isUser( CommonITILActor::REQUESTER, $newTech ) && !$glpi_item->isUser( CommonITILActor::OBSERVER, $newTech ) && !$glpi_item->isUser( CommonITILActor::ASSIGN, $newTech ) && !$user_can_view ) { + // // then we must add this tech user to watcher list + // $glpi_item_user = getItemForItemtype( "{$itemType}_User" ); + // $donotif = $CFG_GLPI["use_mailing"] ; + // $CFG_GLPI["use_mailing"] = false; + // $glpi_item_user->add( array( $glpi_item->getForeignKeyField() => $glpi_item->getId() , 'users_id' => $newTech, 'type' => CommonITILActor::OBSERVER ) ) ; // , '_no_notif' => true + // $CFG_GLPI["use_mailing"] = $donotif; + // } + //} + + self::addWatcher( $itemType, $glpi_task->fields[ $foreignkey ], $newTech ); + + $glpi_task->update( array( 'id' => $row['items_id'], $foreignkey => $glpi_task->fields[ $foreignkey ], 'users_id_tech' => $newTech )) ; // this is now done into GLPI core //if( !$user_can_view ) { @@ -1746,11 +1837,26 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { /** * Summary of solveTask - * @param mixed $caseId - * @param mixed $delIndex + * @param string $caseId + * @param int $delIndex + * @param array $options + * 'txtToAppend' => '' : text to append to solved task + * 'notif' => true : if true will send notifications + * 'users_id_tech' => is the users_id of the tech that solved the task */ - public function solveTask( $caseId, $delIndex, $txtToAppend = '' ) { - global $DB ; + public function solveTask( $caseId, $delIndex, $options=array() ) { + global $DB, $CFG_GLPI ; + + $default_options = array( + 'txtToAppend' => '', + 'notif' => true, + 'users_id_tech' => null + ) ; + foreach($default_options as $key => $opt){ + if(!isset($options[$key])){ + $options[$key] = $opt ; + } + } $query = "SELECT * FROM glpi_plugin_processmaker_tasks WHERE case_id='$caseId' and del_index=$delIndex; "; $res = $DB->query($query) ; @@ -1763,17 +1869,37 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $itemFKField = getForeignKeyFieldForItemType( $glpi_task->getItilObjectItemType() ) ; $hostItem->getFromDB( $glpi_task->fields[ $itemFKField ] ) ; $duration = $this->computeTaskDuration( $glpi_task, $hostItem->fields['entities_id'] ) ; - if( $txtToAppend <> "" ) $txtToAppend = "\n
".$txtToAppend ; - $glpi_task->update( array( 'id' => $row['items_id'], 'state' => 2, 'end' => $_SESSION["glpi_currenttime"], $itemFKField => $hostItem->getID(), 'actiontime' => $duration, 'users_id_tech' => Session::getLoginUserID(), 'content' => $DB->escape($glpi_task->fields[ 'content' ].$txtToAppend) )) ; + if( $options['txtToAppend'] != "" ) { + $options['txtToAppend'] = "\n
".$options['txtToAppend'] ; + } + $params = array( 'id' => $row['items_id'], + 'state' => 2, + 'end' => $_SESSION["glpi_currenttime"], + $itemFKField => $hostItem->getID(), + 'actiontime' => $duration, + 'users_id_tech' => (isset($options['users_id_tech']) ? $options['users_id_tech'] : Session::getLoginUserID()), + 'groups_id_tech' => 0, + 'content' => $DB->escape($glpi_task->fields[ 'content' ].$options['txtToAppend']) + ); + $donotif = $CFG_GLPI["use_mailing"]; + if( !$options['notif'] ) { + $CFG_GLPI["use_mailing"] = false ; + // $params['_no_notif']=true; + } + $glpi_task->update( $params ) ; + $CFG_GLPI["use_mailing"]= $donotif; } } /** * Summary of claimTask + * will unassign group, and assign tech * @param mixed $caseId * @param mixed $delIndex + * @param mixed $users_id_tech optional is the id of the tech + * who's claimed the task, default current logged-in user */ - public function claimTask( $caseId, $delIndex ) { + public function claimTask( $caseId, $delIndex, $users_id_tech=null ) { global $DB ; $query = "SELECT * FROM glpi_plugin_processmaker_tasks WHERE case_id='$caseId' and del_index=$delIndex; "; @@ -1781,7 +1907,16 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { if( $DB->numrows($res) > 0) { $row = $DB->fetch_array( $res ) ; $glpi_task = new $row['itemtype'] ; - $glpi_task->update( array( 'id' => $row['items_id'], 'users_id_tech' => Session::getLoginUserID() )) ; + $glpi_task->getFromDB( $row['items_id'] ) ; + + $itemType = str_replace( 'Task', '', $row['itemtype'] ) ; + $glpi_item = getItemForItemtype( $itemType ); + $glpi_item->getFromDB( $glpi_task->fields[ getForeignKeyFieldForItemType( $itemType ) ] ) ; + + $glpi_task->update( array( 'id' => $row['items_id'], + $glpi_item->getForeignKeyField() => $glpi_item->getId(), + 'users_id_tech' => (isset($users_id_tech)?$users_id_tech: Session::getLoginUserID()), + 'groups_id_tech' => 0 )) ; } } @@ -1792,7 +1927,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { * get case id for an id item_id of type item_type (if a case if attached to it) * @param string $item_type, the type for the item ("Ticket", "Problem", ...) * @param integer $item_id, the id for the item - * @return getCaseInfoResponse object, false if no case is attached to item, or if an error occurred + * @return string the case guid, false if no case is attached to item, or if an error occurred */ public static function getCaseIdFromItem ($item_type, $item_id ) { global $DB ; @@ -1851,11 +1986,13 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { //private $pmCurrentCaseID = null ; public static function pre_show_item_processmakerticket($params) { - global $LANG; - $plug = new Plugin; - if( !$plug->isActivated('arbehaviours') && !is_array($params['item']) && is_subclass_of( $params['item'], 'CommonITILTask') ) { + //global $LANG; + + //$plug = new Plugin; + + if( !is_array($params['item']) && is_subclass_of( $params['item'], 'CommonITILTask') ) { // must check if Task is bound to a PM task - $pmTask = new PluginProcessmakerTask; + $pmTask = new PluginProcessmakerTask($params['item']->getType()); if( $pmTask->getFromDBByQuery("WHERE itemtype='".$params['item']->getType()."' and items_id=".$params['item']->getId())) { //echo 'Test' ; $params['item']->fields['can_edit'] = false ; // to prevent task edition @@ -1888,7 +2025,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { } //if( ($plug = new Plugin) && !$plug->isActivated('arbehaviours') ) { - // if ($parm->getID() && in_array($parm->getType(), array('Ticket'))) { + // if ($params['item']->getID() && is_subclass_of( $params['item'], 'CommonITILObject')) { // // then we are in a ticket // if (isset($_REQUEST['glpi_tab']) && $_SESSION['glpiactiveprofile']['interface'] != "helpdesk" ) { // $data = self::multiexplode(array('$','_'), $_REQUEST['glpi_tab']); @@ -1907,7 +2044,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { // if( ($data[0] == "Ticket" && $tabnum == 2) || $tabnum == -1) { // // then we are showing the Solution tab // // then we must prevent solving of ticket if a case is running - // if( !PluginProcessmakerCase::canSolve( $parm ) ) { + // if( !PluginProcessmakerCase::canSolve( $params['item'] ) ) { // // then output a new div to hide solution // $pmHideSolution = true ; // echo ""; - if( $tabnum == -1 ) - echo ""; - echo "
+ $message = "
@@ -1959,12 +2095,12 @@ class PluginProcessmakerProcessmaker extends CommonDBTM {

- ".$LANG['processmaker']['item']['preventsolution'][1]." + ".$messageOne."

- ".$LANG['processmaker']['item']['preventsolution'][2]." + ".$messageTwo."

@@ -1977,13 +2113,139 @@ class PluginProcessmakerProcessmaker extends CommonDBTM {
"; - } + } + + $pmHideSolution = true ; + $itemtype = strtolower($itemtype); + if ($tabnum == 1 && isset($_SESSION['glpiactiveprofile'][$itemtype.'_status'])) { + // don't display message if arbehaviours is install + if (!($plugin->isInstalled('arbehaviours') && $plugin->isActivated('arbehaviours'))) { + self::displayMessage($message, '', WARNING); + + //save current $_SESSION['glpiactiveprofile'][$itemtype.'_status''] + $_SESSION['glpiactiveprofile'][$itemtype.'_status_save'] = $_SESSION['glpiactiveprofile'][$itemtype.'_status']; + // for all $params['options']['itemtype']. status, disable solved ( life cycles ) + foreach ($_SESSION['glpiactiveprofile'][$itemtype.'_status'] as $key => $value) { + $_SESSION['glpiactiveprofile'][$itemtype.'_status'][$key][CommonITILObject::SOLVED] = 0; + } + } + } else { + // then output a new div and hide solution for content + echo $message; + echo ""; + + } + $itemtype = strtolower($itemtype); + // replace $_SESSION['glpiactiveprofile'][$itemtype.'_status'] with saved value + if ($tabnum == 1 && isset($_SESSION['glpiactiveprofile'][$itemtype.'_status_save'])) { + $_SESSION['glpiactiveprofile'][$itemtype.'_status'] = $_SESSION['glpiactiveprofile'][$itemtype.'_status_save']; + } + + } + } + + } + break; + + } + + } + + + ///** + // * Summary of post_show_item_processmakerticket + // * @param $parm + // */ + //public static function post_show_item_processmakerticket($parm) { + // global $LANG, $pmHideSolution; + // if( ($plug = new Plugin) && !$plug->isActivated('arbehaviours') ) { + // if ($parm->getID() && in_array($parm->getType(), array('Ticket'))) { + // // then we are in a ticket + // if (isset($_REQUEST['glpi_tab']) && $_SESSION['glpiactiveprofile']['interface'] != "helpdesk" ) { + // $data = explode('$', $_REQUEST['glpi_tab']); + // $itemtype = $data[0]; + // // Default set + // $tabnum = 1; + // if (isset($data[1])) { + // $tabnum = $data[1]; + // } + // elseif ($itemtype == -1 ) + // $tabnum = -1 ; + + // if( $tabnum == 2 || $tabnum == -1 ) { + // // then we are showing the Solution tab + // // if a case is running + // // then we must prevent solution to be input + // if( $pmHideSolution ) { //isset($pmVar['GLPI_ITEM_CAN_BE_SOLVED']) && $pmVar['GLPI_ITEM_CAN_BE_SOLVED'] != 1 ) { //if( $pmInfo !== null && ( $pmInfo->caseStatus != 'COMPLETED' && $pmInfo->caseStatus != 'CANCELLED' )) { + + // echo "
"; + // if( $tabnum == -1 ) + // echo "
"; + // echo "
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //

+ // ".$LANG['processmaker']['item']['preventsolution'][1]." + //
+ //
+ //

+ //

+ // ".$LANG['processmaker']['item']['preventsolution'][2]." + // + //

+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
"; + // } + // } + // } + // } + // } + //} + ///** // * Summary of canedit_item_processmakertickettask // * @param $parm @@ -2046,28 +2308,31 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { * Summary of saveForm * This function posts dynaform variables to PM, using the CURL module. * @param mixed $request: is the $_REQUEST server array - * @param string $cookie: is the $_SERVER['HTTP_COOKIE'] string + * //@param string $cookie: is the $_SERVER['HTTP_COOKIE'] string * @return mixed: returns false if request failed, otherwise, returns true */ - public function saveForm( $request, $cookie ) { + public function saveForm( $request ) { //, $cookie ) { - function HandleHeaderLine( $curl, $header_line ) { - global $cookies; - $temp = explode( ": ", $header_line ) ; - if( is_array( $temp ) && $temp[0] == 'Set-Cookie' ) { - $temp2 = explode( "; ", $temp[1]) ; - //$cookies .= $temp2[0].'; ' ; - curl_setopt($curl, CURLOPT_COOKIE, $temp2[0]."; " ) ; - } - return strlen($header_line); - } + if( !function_exists( 'HandleHeaderLine' ) ) { + function HandleHeaderLine( $curl, $header_line ) { + //global $cookies; + $temp = explode( ": ", $header_line ) ; + if( is_array( $temp ) && $temp[0] == 'Set-Cookie' ) { + $temp2 = explode( "; ", $temp[1]) ; + //$cookies .= $temp2[0].'; ' ; + curl_setopt($curl, CURLOPT_COOKIE, $temp2[0]."; " ) ; + } + return strlen($header_line); + } + } $data = http_formdata_flat_hierarchy( $request ) ; $ch = curl_init(); + //to be able to trace network traffic with a local proxy // curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1 ) ; - // curl_setopt($ch, CURLOPT_PROXY, "localhost:10000"); + //curl_setopt($ch, CURLOPT_PROXY, "localhost:8888"); curl_setopt($ch, CURLOPT_HEADER, 1); // curl_setopt($ch, CURLOPT_VERBOSE, 1); // curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); @@ -2107,34 +2372,46 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { foreach( $item->datas['tasks'] as &$task ) { // we must check if task category is PM task category or not, if yes then we add task category comment to datas $task['##task.description##'] = str_replace( '##processmaker.taskcomment##', $task['##task.categorycomment##'], $task['##task.description##'] ) ; } - //$config = PluginProcessmakerConfig::getInstance() ; - //$taskCat = new TaskCategory ; - //$target = reset( $item->target ) ; // to get first target in target array without knowing the key for this value - //// save current translations - //if( isset( $_SESSION['glpi_dropdowntranslations'] ) ) - // $trans = $_SESSION['glpi_dropdowntranslations'] ; - //// load available translations for this user - //$_SESSION['glpi_dropdowntranslations'] = DropdownTranslation::getAvailableTranslations($target['language']); - //foreach( $item->datas['tasks'] as &$task ) { // we must check if task category is PM task category or not, if yes then we add task category comment to datas - // $taskCat->getFromDB( $task['##task.category_id##'] ) ; - // $ancestors = getAncestorsOf( 'glpi_taskcategories', $task['##task.category_id##'] ) ; //$ancestors = json_decode($taskCat->fields['ancestors_cache'], true) ; - // if( in_array( $config->fields['taskcategories_id'], $ancestors) ) { - // $loc = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $target['language'], $taskCat->fields['comment'] ) ; - // //$task['##processmaker.taskcomment##'] = $loc; //['comment'] ; - // $task['##task.description##'] = str_replace( '##processmaker.taskcomment##', $loc, $task['##task.description##'] ) ; - // } - //} - //// restore default translations - //if( isset( $trans ) ) - // $_SESSION['glpi_dropdowntranslations'] = $trans ; - //else - // unset( $_SESSION['glpi_dropdowntranslations'] ) ; } } - /** + /** + * Summary of plugin_item_get_pdfdatas_processmaker + * @param mixed $item + */ + public static function plugin_item_get_pdfdatas_processmaker($item){ + if( isset( $item->datas ) ){ + $config = PluginProcessmakerConfig::getInstance() ; + $taskCat = new TaskCategory ; + + // save current translations + if( isset( $_SESSION['glpi_dropdowntranslations'] ) ) { + $trans = $_SESSION['glpi_dropdowntranslations'] ; + } + // load available translations for this user + $_SESSION['glpi_dropdowntranslations'] = DropdownTranslation::getAvailableTranslations($_SESSION['glpilanguage']); + + $taskCat->getFromDB( $item->datas['taskcategories_id'] ) ; + $ancestors = getAncestorsOf( 'glpi_taskcategories', $item->datas['taskcategories_id']) ; + if( in_array( $config->fields['taskcategories_id'], $ancestors) ) { + $loc_completename = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'completename', $_SESSION['glpilanguage'], $taskCat->fields['completename'] ) ; + $loc_comment = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskCat->fields['comment'] ) ; + $item->datas['content'] = $loc_completename."\n\n".str_replace( "##processmaker.taskcomment##\n##ticket.url##_PluginProcessmakerCase\$processmakercases", $loc_comment, $item->datas['content']) ; + } + // restore default translations + if( isset( $trans ) ) { + $_SESSION['glpi_dropdowntranslations'] = $trans ; + } else { + unset( $_SESSION['glpi_dropdowntranslations'] ) ; + } + } + + } + + + /** * Summary of getProcessesWithCategoryAndProfile * @param mixed $category * @param mixed $type @@ -2146,7 +2423,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $processList = array( ) ; $entityAncestors = implode( ", ", getAncestorsOf( getTableForItemType( 'Entity' ), $entity ) ) ; - if( strlen( $entityAncestors ) != 0 ) { + if( strlen( $entityAncestors ) > 0 ) { $entityAncestors = " OR (entities_id IN ($entityAncestors) AND is_recursive = 1) " ; } @@ -2163,7 +2440,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { } public function startNewCase( $processId, $itemType, $itemId, $userId=null ) { - global $DB; + global $DB, $CFG_GLPI; $requesters = PluginProcessmakerProcessmaker::getItemUsers( $itemType, $itemId, CommonITILActor::REQUESTER) ; // 1 for requesters if( !key_exists( 0, $requesters ) ) { @@ -2206,10 +2483,11 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { 'GLPI_ITEM_PRIORITY' => $locItem->fields['priority'], 'GLPI_TICKET_GLOBAL_VALIDATION' => $locItem->fields['global_validation'] , 'GLPI_TICKET_TECHNICIAN_GLPI_ID' => $userId, //$technicians[0]['glpi_id'], + 'GLPI_URL' => $CFG_GLPI['url_base'].$CFG_GLPI['root_doc'], 'GLPI_TICKET_TECHNICIAN_PM_ID' => PluginProcessmakerUser::getPMUserId( $userId ) //$technicians[0]['pm_id'] ) ) ; - if ($resultCase->status_code == 0){ + if ($resultCase->status_code === 0){ $caseInfo = $this->getCaseInfo( $resultCase->caseId ); //$query = "UPDATE APPLICATION SET APP_STATUS='TO_DO' WHERE APP_UID='".$resultCase->caseId."' AND APP_STATUS='DRAFT'" ; @@ -2226,9 +2504,249 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { //$query = "INSERT INTO glpi_plugin_processmaker_cases (items_id, itemtype, id, case_num, case_status, processes_id) VALUES ($itemId, '$itemType', '".$resultCase->caseId."', ".$resultCase->caseNumber.", '".$caseInfo->caseStatus."', '".$caseInfo->processId."');" ; //$res = $DB->query($query) ; - $this->add1stTask($itemType, $itemId, $caseInfo, '', $userId ) ; -} + $this->add1stTask($itemType, $itemId, $caseInfo, array( 'userId' => $userId ) ) ; + } return $resultCase; } + + + /** + * Summary of derivateCase + * in $request must be present + * 'UID', 'APP_UID' and DEL_INDEX' + * + * @param mixed $myCase + * @param mixed $request + * @param mixed $users_id + */ + public function derivateCase( $myCase, $request, $users_id=null ) { //$cookies, + global $PM_DB; + + // save the case variables + $resultSave = $this->saveForm( $request ) ;//, $_SERVER['HTTP_COOKIE'] ) ; + + // now derivate the case !!! + $pmRouteCaseResponse = $this->routeCase( $myCase->getID(), $request['DEL_INDEX']) ; + + // now tries to get some variables to setup content for new task and to append text to solved task + $infoForTasks = $this->getVariables( $myCase->getID(), array( "GLPI_ITEM_TASK_CONTENT", + "GLPI_ITEM_APPEND_TO_TASK", + "GLPI_NEXT_GROUP_TO_BE_ASSIGNED", + "GLPI_ITEM_TITLE", + "GLPI_TICKET_FOLLOWUP_CONTENT", + "GLPI_TICKET_FOLLOWUP_IS_PRIVATE", + "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID", + "GLPI_ITEM_TASK_ENDDATE", + "GLPI_ITEM_TASK_STARTDATE", + "GLPI_ITEM_SET_STATUS" + ) ); + $itemSetStatus = ''; + if( array_key_exists( 'GLPI_ITEM_SET_STATUS', $infoForTasks ) ) { + $itemSetStatus = $infoForTasks[ 'GLPI_ITEM_SET_STATUS' ] ; + } + + $txtItemTitle = '' ; + if( array_key_exists( 'GLPI_ITEM_TITLE', $infoForTasks ) ) { + $txtItemTitle = $infoForTasks[ 'GLPI_ITEM_TITLE' ] ; + } + + $txtToAppendToTask = '' ; + if( array_key_exists( 'GLPI_ITEM_APPEND_TO_TASK', $infoForTasks ) ) { + $txtToAppendToTask = $infoForTasks[ 'GLPI_ITEM_APPEND_TO_TASK' ] ; + } + + $txtTaskContent = '' ; + if( array_key_exists( 'GLPI_ITEM_TASK_CONTENT', $infoForTasks ) ) { + $txtTaskContent = $infoForTasks[ 'GLPI_ITEM_TASK_CONTENT' ] ; + } + + $groupId = 0 ; + if( array_key_exists( 'GLPI_NEXT_GROUP_TO_BE_ASSIGNED', $infoForTasks ) ) { + $groupId = $infoForTasks[ 'GLPI_NEXT_GROUP_TO_BE_ASSIGNED' ] ; + } + + $taskStartDate = '' ; + $taskEndDate = '' ; + if( array_key_exists( 'GLPI_ITEM_TASK_ENDDATE', $infoForTasks ) ) { + $taskEndDate = $infoForTasks[ 'GLPI_ITEM_TASK_ENDDATE' ] ; + } + if( array_key_exists( 'GLPI_ITEM_TASK_STARTDATE', $infoForTasks ) ) { + $taskStartDate = $infoForTasks[ 'GLPI_ITEM_TASK_STARTDATE' ] ; + if( $taskEndDate == '' ) { + // at least + $taskEndDate = $taskStartDate ; + } + } + + $createFollowup = false ; // by default + if( array_key_exists( 'GLPI_TICKET_FOLLOWUP_CONTENT', $infoForTasks ) && $infoForTasks[ 'GLPI_TICKET_FOLLOWUP_CONTENT' ] != '') { + //&& array_key_exists( 'GLPI_TICKET_FOLLOWUP_IS_PRIVATE', $infoForTasks ) + //&& array_key_exists( 'GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID', $infoForTasks ) + $createFollowup = true ; + } + + // reset those variables + $resultSave = $this->sendVariables( $myCase->getID() , array( "GLPI_ITEM_APPEND_TO_TASK" => '', + "GLPI_ITEM_TASK_CONTENT" => '', + "GLPI_NEXT_GROUP_TO_BE_ASSIGNED" => '', + "GLPI_ITEM_TITLE" => '', + "GLPI_TICKET_FOLLOWUP_CONTENT" => '', + "GLPI_TICKET_FOLLOWUP_IS_PRIVATE" => '', + "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID" => '', + "GLPI_ITEM_TASK_ENDDATE" => '', + "GLPI_ITEM_TASK_STARTDATE" => '', + "GLPI_ITEM_SET_STATUS" => '') ) ; + + // print_r( $pmRouteCaseResponse ) ; + // die() ; + + // now manage tasks associated with item + $itemType = $myCase->getField('itemtype'); + $itemId = $myCase->getField('items_id'); + + // switch own task to 'done' and create a new one + $this->solveTask( $myCase->getID(), $request['DEL_INDEX'], array( 'txtToAppend' => $txtToAppendToTask, 'users_id_tech' => $users_id ) ) ; + + // create a followup if requested + if( $createFollowup && $itemType == 'Ticket' ) { + $this->addTicketFollowup( $itemId, $infoForTasks ) ; + } + $caseInfo = $this->getCaseInfo( $myCase->getID(), $request['DEL_INDEX']) ; + if( property_exists( $pmRouteCaseResponse, 'routing' ) ) { + foreach( $pmRouteCaseResponse->routing as $route ) { + $this->addTask( $itemType, + $itemId, + $caseInfo, + $route->delIndex, + PluginProcessmakerUser::getGLPIUserId( $route->userId ), + $groupId, + $route->taskId, + array( 'txtTaskContent' => $txtTaskContent, + 'start_date' => $taskStartDate, + 'end_date' => $taskEndDate) + ) ; + + // if end date was specicied, then must change due date of the PM task + if( $taskEndDate != '' ) { + $PM_DB->query( "UPDATE APP_DELEGATION SET DEL_TASK_DUE_DATE='$taskEndDate' WHERE APP_UID='".$caseInfo->caseId."' AND DEL_INDEX=".$route->delIndex); + } + } + } + + if( $txtItemTitle != '') { + // we are going to change the title of current GLPI Item + $item = new $itemType ; + $item->getFromDB( $itemId ) ; + $item->update( array('id' => $itemId, 'name' => $txtItemTitle) ) ; + } + + if( $itemSetStatus != '' ) { + $this->setItemStatus($itemType, $itemId, $itemSetStatus ) ; + } + + // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED + $myCase->update( array( 'id' => $myCase->getID(), 'case_status' => $caseInfo->caseStatus ) ) ; + } + + + /** + * Summary of getPMGroups + * @return array + */ + public static function getPMGroups( ) { + global $PM_DB; + $pmGroupList = array(); + foreach($PM_DB->request("SELECT * FROM content WHERE content.CON_CATEGORY='GRP_TITLE' AND content.CON_LANG='en'") as $dbgroup){ + $pmGroupList[$dbgroup['CON_VALUE']] = $dbgroup; + } + return $pmGroupList; + } + + + /** + * Summary of displayMessage + * Show a html message bottom-right of screen + * @param string $html_message message to be shown + * @param string $title if '' then title bar is not shown (default '') + * @param string $msgtype the type of the message (ERROR | WARNING | INFO) + * @return void + **/ + static private function displayMessage($html_message, $title='',$msgtype='info_msg') { + + //set title and css class + switch ($msgtype) { + case ERROR: + $title = __('Error'); + $class = 'err_msg'; + break; + case WARNING: + $title = __('Warning'); + $class = 'warn_msg'; + break; + case INFO: + $title = __('Information'); + $class = 'info_msg'; + break; + } + + echo "
"; + echo $html_message; + echo "
"; + + $scriptblock = " + $(document).ready(function() { + var _of = window; + var _at = 'right-20 bottom-20'; + //calculate relative dialog position + $('.message_after_redirect').each(function() { + var _this = $(this); + if (_this.attr('aria-describedby') != 'message_after_redirect_$msgtype') { + _of = _this; + _at = 'right top-' + (10 + _this.outerHeight()); + } + }); + + $('#message_after_redirect_$msgtype').dialog({ + dialogClass: 'message_after_redirect $class', + minHeight: 40, + minWidth: 200, + position: { + my: 'right bottom', + at: _at, + of: _of, + collision: 'none' + }, + autoOpen: false, + show: { + effect: 'slide', + direction: 'down', + 'duration': 800 + } + }) + .dialog('open');"; + + //do not autoclose errors + if ($msgtype != ERROR) { + $scriptblock .= " + + // close dialog on outside click + $(document.body).on('click', function(e){ + if ($('#message_after_redirect_$msgtype').dialog('isOpen') + && !$(e.target).is('.ui-dialog, a') + && !$(e.target).closest('.ui-dialog').length) { + $('#message_after_redirect_$msgtype').dialog('close'); + // redo focus on initial element + e.target.focus(); + } + });"; + } + + $scriptblock .= " + + }); + "; + + echo Html::scriptBlock($scriptblock); + } } \ No newline at end of file diff --git a/inc/task.class.php b/inc/task.class.php index 2fb02b0..925ad76 100644 --- a/inc/task.class.php +++ b/inc/task.class.php @@ -89,34 +89,36 @@ class PluginProcessmakerTask extends CommonITILTask static function populatePlanning($params) { global $CFG_GLPI; - //echo 'Test' ; + $ret = array(); $events = array() ; - $params['begin'] = '2000-01-01 00:00:00'; - $ret = CommonITILTask::genericPopulatePlanning( 'TicketTask', $params ) ; + if( isset($params['start']) ) { + $params['begin'] = '2000-01-01 00:00:00'; + $ret = CommonITILTask::genericPopulatePlanning( 'TicketTask', $params ) ; - foreach( $ret as $key => $event ) { - if( $event['state'] == 1 || ($params['display_done_events'] == 1 && $event['state'] == 2)) { // if todo or done but need to show them (=planning) - // check if task is one within a case - $pmTask = new self('TicketTask'); - if( $pmTask->getFromDB( $event['tickettasks_id'] ) ) { // $pmTask->getFromDBByQuery( " WHERE itemtype = 'TicketTask' AND items_id = ". $event['tickettasks_id'] ) ) { - $event['editable'] = false; - $event['url'] .= '&forcetab=PluginProcessmakerCase$processmakercases' ; + foreach( $ret as $key => $event ) { + if( $event['state'] == 1 || ($params['display_done_events'] == 1 && $event['state'] == 2)) { // if todo or done but need to show them (=planning) + // check if task is one within a case + $pmTask = new self('TicketTask'); + if( $pmTask->getFromDB( $event['tickettasks_id'] ) ) { // $pmTask->getFromDBByQuery( " WHERE itemtype = 'TicketTask' AND items_id = ". $event['tickettasks_id'] ) ) { + $event['editable'] = false; + $event['url'] .= '&forcetab=PluginProcessmakerCase$processmakercases' ; - $taskCat = new TaskCategory ; - $taskCat->getFromDB( $pmTask->fields['taskcategories_id'] ) ; - $taskComment = isset($taskCat->fields['comment']) ? $taskCat->fields['comment'] : '' ; - if( Session::haveTranslations('TaskCategory', 'comment') ) { - $taskComment = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskComment ) ; + $taskCat = new TaskCategory ; + $taskCat->getFromDB( $pmTask->fields['taskcategories_id'] ) ; + $taskComment = isset($taskCat->fields['comment']) ? $taskCat->fields['comment'] : '' ; + if( Session::haveTranslations('TaskCategory', 'comment') ) { + $taskComment = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskComment ) ; + } + + $event['content'] = str_replace( '##processmaker.taskcomment##', $taskComment, $event['content'] ) ; + $event['content'] = str_replace( '##ticket.url##_PluginProcessmakerCase$processmakercases', "", $event['content'] ) ; //"."Click to manage task"." + //if( $event['state'] == 1 && $event['end'] < $params['start'] ) { // if todo and late + // $event['name'] = $event['end'].' '.$event['name'] ; //$event['begin'].' to '.$event['end'].' '.$event['name'] ; + // $event['end'] = $params['start'].' 24:00:00'; //.$CFG_GLPI['planning_end']; + //} + $events[$key] = $event ; } - - $event['content'] = str_replace( '##processmaker.taskcomment##', $taskComment, $event['content'] ) ; - $event['content'] = str_replace( '##ticket.url##_PluginProcessmakerCase$processmakercases', "", $event['content'] ) ; //"."Click to manage task"." - if( $event['state'] == 1 && $event['end'] < $params['start'] ) { // if todo and late - $event['name'] = $event['end'].' '.$event['name'] ; //$event['begin'].' to '.$event['end'].' '.$event['name'] ; - $event['end'] = $params['start'].' 24:00:00'; //.$CFG_GLPI['planning_end']; - } - $events[$key] = $event ; } } } diff --git a/inc/user.class.php b/inc/user.class.php index 92c6647..36bc520 100644 --- a/inc/user.class.php +++ b/inc/user.class.php @@ -178,7 +178,7 @@ class PluginProcessmakerUser extends CommonDBTM { * Summary of getGLPIUserId * returns GLPI user ID from a Processmaker user ID * @param string $pmUserId - * @return int, GLPI user id, or 0 if not found + * @return int GLPI user id, or 0 if not found */ public static function getGLPIUserId( $pmUserId ){ $obj = new self ; diff --git a/js/cases.helpdesk.js b/js/cases.helpdesk.js index 39cb362..1bbb9ea 100644 --- a/js/cases.helpdesk.js +++ b/js/cases.helpdesk.js @@ -41,8 +41,13 @@ function onLoadFrame( evt, caseId, delIndex, caseNumber, processName ) { caseIFrame = document.getElementById('caseiframe'); - if (caseIFrame != undefined && caseIFrame.contentDocument != undefined) { - var contentDocument = caseIFrame.contentDocument; + var contentDocument; + try { + contentDocument = caseIFrame.contentDocument; + } catch (ex) { + contentDocument = false; + } + if (caseIFrame != undefined && contentDocument) { var buttonContinue = contentDocument.getElementById('form[btnGLPISendRequest]'); var txtAreaUseRequestSumUp = contentDocument.getElementById('form[UserRequestSumUp]'); var linkList = contentDocument.getElementsByTagName('a'); diff --git a/js/cases.js b/js/cases.js index 47c5055..9d10837 100644 --- a/js/cases.js +++ b/js/cases.js @@ -20,13 +20,25 @@ function bGLPIHideElement(eltList, attribute, value) { return ret; } -function showMask(elt) { - if( !elt.defaultPrevented ) { - Ext.getBody().moveTo(0, 0); - var myMask = new Ext.LoadMask(Ext.getBody(), { removeMask: false }); - myMask.show(); - } -}; + +function displayOverlay() { + //debugger; + // don't use displayOverlay when submit input open new tab or update parent ( example: pdf generation ) + if (!($(this).is('input[type=submit]') + && $(this).parents('form').length > 0 + && ($(this).parents('form').first().attr('target') == '_blank' || $(this).parents('form').first().attr('target') == '_parent'))) { + $("
").appendTo("body"); + + var timer = window.setInterval(function () { + var count = $('.ui-widget-overlay.ui-front').length; + if (count == 2) { + $($('.ui-widget-overlay.ui-front')[1]).remove(); + window.clearInterval(timer); + } + + }, 10); + } +} function onTaskFrameLoad(event, delIndex, hideClaimButton, csrf) { @@ -41,12 +53,22 @@ function onTaskFrameLoad(event, delIndex, hideClaimButton, csrf) { try { var locContentDocument; var taskFrame = document.getElementById(taskFrameId); - - if (taskFrame != undefined && taskFrame.contentDocument != undefined) { + try { + locContentDocument = taskFrame.contentDocument; + } catch (ex) { + locContentDocument = false; + } + if (taskFrame != undefined && locContentDocument != undefined) { // here we've caught the content of the iframe + // if task resumé, then hide the form part + //debugger; + var form_resume = locContentDocument.getElementsByName('cases_Resume'); + if (form_resume.length > 0 && form_resume[0].style.display != 'none') { + form_resume[0].style.display = 'none'; + } + // then look if btnGLPISendRequest exists, - locContentDocument = taskFrame.contentDocument; var locElt = locContentDocument.getElementById('form[btnGLPISendRequest]'); if (!bShowHideNextStep && locElt != undefined ) { var linkList = locContentDocument.getElementsByTagName('a'); @@ -60,6 +82,7 @@ function onTaskFrameLoad(event, delIndex, hideClaimButton, csrf) { // if yes then change the action of the form POST var node = formList[0]; // must have one element in list: in a dynaform there is one and only one HTML form + node.setAttribute('actionBackup', node.action); var action = node.action.split('?'); node.action = GLPI_HTTP_CASE_FORM + '?' + action[1] + '&DEL_INDEX=' + delIndex; @@ -71,9 +94,8 @@ function onTaskFrameLoad(event, delIndex, hideClaimButton, csrf) { csrfElt.setAttribute("value", csrf) ; node.appendChild(csrfElt); - // try to add showMask function to submit event - // TODO - //node.addEventListener('submit', showMask, true); + // add showMask function to submit event + //node.addEventListener('submit', displayOverlay, true); } else { // then hide the button itself locElt.style.display = 'none'; @@ -94,8 +116,11 @@ function onTaskFrameLoad(event, delIndex, hideClaimButton, csrf) { // to manage Claim var formList = locContentDocument.getElementsByTagName('form'); var node = formList[0]; // must have one element in list: in a dynaform there is one and only one HTML form + node.setAttribute('actionBackup', node.action); + var action = node.action.split('?'); node.action = GLPI_HTTP_CASE_FORM + '?' + action[1] + '&DEL_INDEX=' + delIndex; + bHideClaimCancelButton = true; // TODO //node.addEventListener('submit', showMask); @@ -110,24 +135,15 @@ function onTaskFrameLoad(event, delIndex, hideClaimButton, csrf) { GLPI_RELOAD_PARENT.location.reload(); } - // try to redim caseIFrame - if (!redimIFrame) { - var newHeight; - //var locElt = locContentDocument.getElementsByTagName("table")[0]; - var locElt = locContentDocument.getElementsByTagName("body")[0]; - newHeight = parseInt(getComputedStyle(locElt, null).getPropertyValue('height'), 10) + 60; - //if (locElt) - // newHeight = (locElt.clientHeight < 400 ? 400 : locElt.clientHeight) + locElt.offsetParent.offsetTop ; - //else { - // locElt = locContentDocument.getElementsByTagName("form")[0]; - // newHeight = (locElt.clientHeight < 400 ? 400 : locElt.clientHeight) + locElt.offsetTop ; - //} - //locElt.clientHeight = newHeight; // don't know if this is neccessary!!! --> bugs on IE8 - //NOT NEEDED WITH jQuery: var elts = $('#processmakertabpanel').tabs();//.getItem('task-' + delIndex).setHeight(newHeight); - //debugger; - taskFrame.height = newHeight ; - redimIFrame = true; - } + // try to redim caseIFrame + if (!redimIFrame) { + redimTaskFrame(taskFrame, delIndex); + var redimFrameTimer = window.setInterval(function () { + redimTaskFrame(taskFrame, delIndex); + }, 1000); + + redimIFrame = true; + } } taskFrameTimerCounter = taskFrameTimerCounter + 1; @@ -143,6 +159,21 @@ function onTaskFrameLoad(event, delIndex, hideClaimButton, csrf) { } +function redimTaskFrame(taskFrame, delIndex) { + var newHeight; + try{ + //var locElt = locContentDocument.getElementsByTagName("table")[0]; + var locElt = taskFrame.contentDocument.getElementsByTagName("body")[0]; + newHeight = parseInt(getComputedStyle(locElt, null).getPropertyValue('height'), 10) ; + if (newHeight < 500) { + newHeight = 500; + } + + taskFrame.height = newHeight; + } catch (e) { + } +} + function onTaskFrameActivation(delIndex) { var taskFrameId = "caseiframe-" + delIndex; var taskFrameTimerCounter = 0; @@ -182,23 +213,16 @@ function onTaskFrameActivation(delIndex) { } function clearClass(lociFrame) { - //var otherFrameTimerCounter = 0; - //var otherFrameTimer = window.setInterval(function () { - try { - var locElt = lociFrame.contentDocument.getElementsByTagName('body')[0]; - if (locElt != undefined && locElt.className != '') { - //debugger; - locElt.className = ''; - // window.clearInterval(otherFrameTimer); - //} else { - // otherFrameTimerCounter = otherFrameTimerCounter + 1; - // if (otherFrameTimerCounter > 3000 ) - // window.clearInterval(otherFrameTimer); - } - } catch (ev) { + try { + var locElt = lociFrame.contentDocument.getElementsByTagName('body')[0]; + if (locElt != undefined && locElt.className != '') { + //debugger; + locElt.className = ''; + + } + } catch (ev) { - } - //}, 10); + } } function onOtherFrameLoad(tabPanelName, frameName, eltTagName, isMap3) { diff --git a/locales/en_GB.php b/locales/en_GB.php index 7344176..e17fbe6 100644 --- a/locales/en_GB.php +++ b/locales/en_GB.php @@ -12,8 +12,8 @@ $LANG['processmaker']['profile']['case_delete']="Delete cases"; $LANG['processmaker']['process']['process_guid']="Process GUID"; $LANG['processmaker']['process']['project_type_short']="Project type" ; $LANG['processmaker']['process']['project_type']="Project type (to be changed if not up-to-date)" ; -$LANG['processmaker']['process']['project_type_bpmn']='BPMN'; -$LANG['processmaker']['process']['project_type_classic']='Classic' ; +$LANG['processmaker']['process']['project_type_bpmn']='bpmn'; +$LANG['processmaker']['process']['project_type_classic']='classic' ; $LANG['processmaker']['process']['hide_case_num_title_short']="Hide case number and title"; $LANG['processmaker']['process']['hide_case_num_title']="Hide case number and title in task descriptions"; $LANG['processmaker']['process']['insert_task_comment_short']="Insert Task Category"; @@ -112,8 +112,8 @@ $LANG['processmaker']['search']['processtitle']="Process Title"; $LANG['processmaker']['search']['casetitle']="Case Title"; $LANG['processmaker']['search']['hascase']="Running Case?"; -$LANG['processmaker']['cron']['pmusers']="Syncs GLPI users and pseudo-groups into ProcessMaker." ; -$LANG['processmaker']['cron']['pmnotifications']="Notifications for GLPI Tasks bound to ProcessMaker Tasks." ; +$LANG['processmaker']['cron']['pmusers']="Syncs GLPI users and groups into ProcessMaker." ; +$LANG['processmaker']['cron']['pmtaskactions']="To apply task actions between cases." ; $LANG['processmaker']['cron']['pmorphancases']['description']="Cleaning of orphan cases." ; $LANG['processmaker']['cron']['pmorphancases']['parameter']="Number of days to keep orphan cases"; diff --git a/locales/fr_FR.php b/locales/fr_FR.php index 6b582c6..b81600a 100644 --- a/locales/fr_FR.php +++ b/locales/fr_FR.php @@ -112,7 +112,8 @@ $LANG['processmaker']['search']['processtitle']="Nom du processus"; $LANG['processmaker']['search']['casetitle']="Titre du cas"; $LANG['processmaker']['search']['hascase']="Cas en cours ?"; -$LANG['processmaker']['cron']['pmusers']="Synchro des utilisateurs GLPI et des pseudo-groups avec ProcessMaker." ; -$LANG['processmaker']['cron']['pmnotifications']="Notifications des tâches GLPI liées à des tâches de ProcessMaker." ; +$LANG['processmaker']['cron']['pmusers']="Synchro des utilisateurs GLPI et des groups avec ProcessMaker." ; +//$LANG['processmaker']['cron']['pmnotifications']="Notifications des tâches GLPI liées à des tâches de ProcessMaker." ; +$LANG['processmaker']['cron']['pmtaskactions']="Pour appliquer les actions de tâches entre cas." ; $LANG['processmaker']['cron']['pmorphancases']['description']="Nettoyage des cas orphelins." ; $LANG['processmaker']['cron']['pmorphancases']['parameter']="Nombre de jours avant nettoyage des cas orphelins."; diff --git a/processmaker.xml b/processmaker.xml index 213d66a..8f6a603 100644 --- a/processmaker.xml +++ b/processmaker.xml @@ -23,7 +23,7 @@ - 3.0.0 + 3.1.0 9.1 diff --git a/setup.php b/setup.php index 3b1ebe6..a8c1458 100644 --- a/setup.php +++ b/setup.php @@ -48,9 +48,14 @@ function plugin_init_processmaker() { $PLUGIN_HOOKS['pre_show_item']['processmaker'] = array('PluginProcessmakerProcessmaker', 'pre_show_item_processmakerticket'); - $PLUGIN_HOOKS['post_show_item']['processmaker'] - = array('Ticket' => array('PluginProcessmakerProcessmaker', - 'post_show_item_processmakerticket')); + $PLUGIN_HOOKS['pre_show_tab']['processmaker'] + = array('PluginProcessmakerProcessmaker', 'pre_show_tab_processmaker'); + $PLUGIN_HOOKS['post_show_tab']['processmaker'] + = array('PluginProcessmakerProcessmaker', 'post_show_tab_processmaker'); + + //$PLUGIN_HOOKS['post_show_item']['processmaker'] + // = array('Ticket' => array('PluginProcessmakerProcessmaker', + // 'post_show_item_processmakerticket')); // Display a menu entry ? if (Session::haveRight('config', READ) ) { @@ -70,7 +75,8 @@ function plugin_init_processmaker() { // , 'TicketFollowup' => 'plugin_pre_item_update_processmaker_followup' $PLUGIN_HOOKS['item_update']['processmaker'] = array( - 'TicketSatisfaction' => 'plugin_item_update_processmaker_satisfaction' + 'TicketSatisfaction' => 'plugin_item_update_processmaker_satisfaction', + 'TicketTask' => 'plugin_item_update_processmaker_tasks' ); $PLUGIN_HOOKS['item_add']['processmaker'] = array( @@ -81,6 +87,9 @@ function plugin_init_processmaker() { 'NotificationTargetTicket' => array('PluginProcessmakerProcessmaker', 'plugin_item_get_datas_processmaker') ); + $PLUGIN_HOOKS['item_get_pdfdatas']['processmaker'] = array( + 'PluginPdfTicketTask' => array('PluginProcessmakerProcessmaker', 'plugin_item_get_pdfdatas_processmaker') + ); $PLUGIN_HOOKS['pre_item_purge']['processmaker'] = array( @@ -115,16 +124,16 @@ function plugin_version_processmaker(){ global $LANG; return array ('name' => 'Process Maker', - 'version' => '3.0.0', + 'version' => '3.1.0', 'author' => 'Olivier Moron', 'homepage' => '', - 'minGlpiVersion' => '0.85.0'); + 'minGlpiVersion' => '9.1'); } // Optional : check prerequisites before install : may print errors or add to message after redirect function plugin_processmaker_check_prerequisites(){ - if (version_compare(GLPI_VERSION,'0.85','lt') || version_compare(GLPI_VERSION,'9.2','ge')) { - echo "This plugin requires GLPI 0.85.0 or higher"; + if (version_compare(GLPI_VERSION,'9.1','lt') || version_compare(GLPI_VERSION,'9.2','ge')) { + echo "This plugin requires GLPI 9.1 or higher"; return false; } //$plug = new Plugin ;
".$caseInfo->processName.""; //echo "
".__('Describe the incident or request').""; if (Session::isMultiEntitiesMode()) { - echo "(".Dropdown::getDropdownName("glpi_entities", $_SESSION["glpiactive_entity"]).")"; + echo "(".Dropdown::getDropdownName("glpi_entities", $_REQUEST['entities_id']).")"; } echo "
"; echo ""; echo "