From 96c6e9ba6f3d2d49c800ee25b7b68dffc9f99afc Mon Sep 17 00:00:00 2001 From: tomolimo Date: Tue, 21 May 2019 10:47:15 +0200 Subject: [PATCH] Version to 3.5.1 Compatible with GLPI 9.3 --- README.md | 4 +- ajax/dropdownProcesses.php | 13 +- ajax/dropdownUsers.php | 3 +- front/case.form.php | 9 +- front/case.php | 13 +- front/process_profile.form.php | 7 +- front/processmaker.form.php | 35 +- front/processmaker.helpdesk.form.php | 1 + hook.php | 177 ++----- inc/case.class.php | 435 ++++++++-------- inc/casechangelog.class.php | 9 +- inc/casedynaform.class.php | 3 +- inc/casehistory.class.php | 9 +- inc/caselink.class.php | 215 ++++---- inc/caselinkaction.class.php | 2 +- inc/casemap.class.php | 9 +- inc/config.class.php | 26 +- inc/process.class.php | 272 +++++++--- inc/process_profile.class.php | 11 +- inc/processmaker.class.php | 473 +++++++++--------- inc/selfservicedraft.class.php | 2 +- inc/task.class.php | 15 +- inc/taskcategory.class.php | 38 +- inc/user.class.php | 7 +- install/install.php | 22 +- install/mysql/3.2.8-empty.sql | 167 ------- install/mysql/3.2.9-empty.sql | 168 ------- install/mysql/3.3.0-empty.sql | 179 ------- install/mysql/3.3.1-empty.sql | 186 ------- ...3.3.8-empty.sql => processmaker-empty.sql} | 7 +- install/update.php | 7 + install/update_3_3_1_to_3_3_8.php | 2 +- install/update_3_3_8_to_3_4_9.php | 30 ++ install/update_to_3_2_8.php | 2 +- js/cases.helpdesk.js | 10 +- js/central.js | 9 +- js/domain.js.php | 19 - js/helpdesk.public.js.php | 2 +- js/planning.js | 2 +- pics/small-under_maintenance.png | Bin 0 -> 39576 bytes pics/verysmall-under_maintenance.png | Bin 0 -> 13147 bytes processmaker.xml | 41 +- setup.php | 55 +- 43 files changed, 1027 insertions(+), 1669 deletions(-) delete mode 100644 install/mysql/3.2.8-empty.sql delete mode 100644 install/mysql/3.2.9-empty.sql delete mode 100644 install/mysql/3.3.0-empty.sql delete mode 100644 install/mysql/3.3.1-empty.sql rename install/mysql/{3.3.8-empty.sql => processmaker-empty.sql} (96%) create mode 100644 install/update_3_3_8_to_3_4_9.php delete mode 100644 js/domain.js.php create mode 100644 pics/small-under_maintenance.png create mode 100644 pics/verysmall-under_maintenance.png diff --git a/README.md b/README.md index b7d1bad..d5b74f4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ GLPI plugin that provides an interface with a customized ProcessMaker server (https://github.com/tomolimo/processmaker-server). -version 3.4.5 is compatible with GLPI 9.2 and needs ProcessMaker either 3.0.1.8-RE-1.12 (https://github.com/tomolimo/processmaker-server/releases/tag/3.0.1.8-RE-1.12) or 3.3.0-RE-1.0 (https://github.com/tomolimo/processmaker-server/releases/tag/3.3.0-RE-1.0) +version 3.4.x is compatible with GLPI 9.2 and needs ProcessMaker either 3.0.1.8-RE-1.12 (https://github.com/tomolimo/processmaker-server/releases/tag/3.0.1.8-RE-1.12) or 3.3.0-RE-1.0 (https://github.com/tomolimo/processmaker-server/releases/tag/3.3.0-RE-1.0) + +version 3.5.x is compatible with GLPI 9.3 and needs ProcessMaker 3.3.0-RE-1.x (https://github.com/tomolimo/processmaker-server/releases/latest) This plugin can run classic and bpmn processes diff --git a/ajax/dropdownProcesses.php b/ajax/dropdownProcesses.php index af506a7..ba543e3 100644 --- a/ajax/dropdownProcesses.php +++ b/ajax/dropdownProcesses.php @@ -61,15 +61,22 @@ if (empty($_REQUEST['searchText'])) { } $processall = (isset($_REQUEST['specific_tags']['process_restrict']) && !$_REQUEST['specific_tags']['process_restrict']); +$count_cases_per_item = isset($_REQUEST['specific_tags']['count_cases_per_item']) ? $_REQUEST['specific_tags']['count_cases_per_item'] : []; $result = PluginProcessmakerProcess::getSqlSearchResult(false, $search); if ($DB->numrows($result)) { while ($data = $DB->fetch_array($result)) { $process_entities = PluginProcessmakerProcess::getEntitiesForProfileByProcess($data["id"], $_SESSION['glpiactiveprofile']['id'], true); - if ($processall || in_array( $_REQUEST["entity_restrict"], $process_entities)) { - array_push( $processes, [ 'id' => $data["id"], - 'text' => $data["name"] ]); + $can_add = $data['max_cases_per_item'] == 0 || !isset($count_cases_per_item[$data["id"]]) || $count_cases_per_item[$data["id"]] < $data['max_cases_per_item']; + if ($processall + || ($data['maintenance'] != 1 + && in_array( $_REQUEST["entity_restrict"], $process_entities) + && $can_add) ) { + + array_push( $processes, ['id' => $data["id"], + 'text' => $data["name"] + ]); $count++; } } diff --git a/ajax/dropdownUsers.php b/ajax/dropdownUsers.php index 2ad0286..16785f1 100644 --- a/ajax/dropdownUsers.php +++ b/ajax/dropdownUsers.php @@ -57,8 +57,9 @@ if (!isset($_REQUEST['page'])) { if ($one_item < 0) { $start = ($_REQUEST['page']-1)*$_REQUEST['page_limit']; $LIMIT = "LIMIT $start,".$_REQUEST['page_limit']; + $searchText = isset($_REQUEST['searchText']) ? $_REQUEST['searchText'] : ""; $result = PluginProcessmakerUser::getSqlSearchResult( $_REQUEST['specific_tags']['taskGuid'], false, $_REQUEST['right'], $_REQUEST["entity_restrict"], - $_REQUEST['value'], $used, $_REQUEST['searchText'], $LIMIT); + $_REQUEST['value'], $used, $searchText, $LIMIT); } else { $query = "SELECT DISTINCT `glpi_users`.* FROM `glpi_users` diff --git a/front/case.form.php b/front/case.form.php index 6ed607f..f3f63ac 100644 --- a/front/case.form.php +++ b/front/case.form.php @@ -22,16 +22,13 @@ function glpi_processmaker_case_reload_page() { if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'route' && isset( $_REQUEST['UID'] ) && isset( $_REQUEST['APP_UID'] ) && isset( $_REQUEST['__DynaformName__'] )) { // then get item id from DB if ($locCase->getFromGUID($_REQUEST['APP_UID'])) { - - if (isset( $_REQUEST['form'] )) { - $PM_SOAP->derivateCase($locCase, $_REQUEST); - } + $PM_SOAP->derivateCase($locCase, $_REQUEST); } glpi_processmaker_case_reload_page(); -} else if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'delete') { +} else if (isset($_REQUEST['purge'])) { // delete case from case table, this will also delete the tasks - if ($locCase->getFromDB($_POST['cases_id']) && $locCase->deleteCase()) { + if ($locCase->getFromDB($_REQUEST['id']) && $locCase->deleteCase()) { Session::addMessageAfterRedirect(__('Case has been deleted!', 'processmaker'), true, INFO); } else { Session::addMessageAfterRedirect(__('Unable to delete case!', 'processmaker'), true, ERROR); diff --git a/front/case.php b/front/case.php index 8cb05e5..45bb2ac 100644 --- a/front/case.php +++ b/front/case.php @@ -5,19 +5,8 @@ include_once ("../../../inc/includes.php"); Html::header(__('ProcessMaker', 'processmaker'), $_SERVER['PHP_SELF'], "helpdesk", "PluginProcessmakerCase", "cases"); if (!$PM_SOAP->config->fields['maintenance']) { - if (Session::haveRightsOr("plugin_processmaker_config", [READ, UPDATE])) { + if (Session::haveRightsOr("plugin_processmaker_case", [READ, UPDATE])) { - // force default sort to column id / DESC - if (empty($_SESSION['glpisearch']['PluginProcessmakerCase']) - || isset($_GET["reset"]) - || !isset($_GET["sort"]) - ) { - $_SESSION['glpisearch']['PluginProcessmakerCase']['order'] = 'DESC'; - $_SESSION['glpisearch']['PluginProcessmakerCase']['sort'] = '1'; - if (isset($_GET["reset"])) { - unset($_GET['reset']); - } - } Search::show('PluginProcessmakerCase'); } else { Html::displayRightError(); diff --git a/front/process_profile.form.php b/front/process_profile.form.php index c273793..18d0460 100644 --- a/front/process_profile.form.php +++ b/front/process_profile.form.php @@ -4,14 +4,13 @@ include_once ("../../../inc/includes.php"); Session::checkCentralAccess(); -$right = new PluginProcessmakerProcess_Profile(); +$right = new PluginProcessmakerProcess_Profile(); if (isset($_POST["add"])) { $right->check(-1, UPDATE, $_POST); - if ($right->add($_POST)) { - } + $right->add($_POST); Html::back(); -} +} Html::displayErrorAndDie("lost"); diff --git a/front/processmaker.form.php b/front/processmaker.form.php index a2a0b2f..d70ab35 100644 --- a/front/processmaker.form.php +++ b/front/processmaker.form.php @@ -3,12 +3,9 @@ include_once ("../../../inc/includes.php"); switch ($_POST["action"]) { case 'newcase': - if (isset($_POST['items_id']) && $_POST['items_id'] > 0) { // then this case will be bound to an item - // TODO: we must check if a case is not already existing - // to manage the problem of F5 (Refresh) + if (isset($_POST['items_id']) && $_POST['items_id'] > 0) { - //$hasCase = PluginProcessmakerCase::getIDFromItem($_POST['itemtype'], $_POST['items_id']); - //if ($hasCase === false && $_POST['plugin_processmaker_processes_id'] > 0) { + // then this case will be bound to an item if ($_POST['plugin_processmaker_processes_id'] > 0) { $resultCase = $PM_SOAP->startNewCase($_POST['plugin_processmaker_processes_id'], $_POST['itemtype'], $_POST['items_id'], Session::getLoginUserID()); @@ -18,9 +15,18 @@ switch ($_POST["action"]) { if ($case->getFromGUID($resultCase->caseId)) { $link = $case->getLinkURL(); $task = new PluginProcessmakerTask(); - $task->getFromDBByQuery(" WHERE `plugin_processmaker_cases_id`=".$case->getID()); // normally there is only one and only one first task + + $task->getFromDBByRequest([ + 'WHERE' => [ + 'plugin_processmaker_cases_id' => $case->getID() + ], + ]); + + + //$task->getFromDBByQuery(" WHERE `plugin_processmaker_cases_id`=".$case->getID()); // normally there is only one and only one first task //$link .= '&forcetab=PluginProcessmakerTask$'.$task->getID(); - Session::setActiveTab('PluginProcessmakerCase', 'PluginProcessmakerTask$'.$task->getID()); + + Session::setActiveTab('PluginProcessmakerCase', 'PluginProcessmakerTask$'.$task->fields['id']); $item = new $_POST['itemtype']; $item->getFromDB($_POST['items_id']); unset($_SERVER['REQUEST_URI']); // to prevent use of processmaker.form.php in NavigateList @@ -39,11 +45,18 @@ switch ($_POST["action"]) { Html::back(); } } else { // the case is created before the ticket (used for post-only case creation before ticket creation) + $pm_user_guid = PluginProcessmakerUser::getPMUserId( Session::getLoginUserID() ); $resultCase = $PM_SOAP->newCase( $_POST['plugin_processmaker_processes_id'], - [ 'GLPI_ITEM_CAN_BE_SOLVED' => 0, - 'GLPI_SELFSERVICE_CREATED' => '1', - 'GLPI_ITEM_TYPE' => 'Ticket', - 'GLPI_URL' => $CFG_GLPI['url_base']] ); + ['GLPI_ITEM_CAN_BE_SOLVED' => 0, + 'GLPI_SELFSERVICE_CREATED' => '1', + 'GLPI_ITEM_TYPE' => 'Ticket', + 'GLPI_URL' => $CFG_GLPI['url_base'], + // Specific to Tickets + // GLPI_TICKET_TYPE will contains 1 (= incident) or 2 (= request) + 'GLPI_TICKET_TYPE' => $_POST['type'], + 'GLPI_ITEM_REQUESTER_GLPI_ID' => Session::getLoginUserID(), + 'GLPI_ITEM_REQUESTER_PM_ID' => $pm_user_guid + ] ); if ($resultCase->status_code == 0) { // case is created // Must show it... diff --git a/front/processmaker.helpdesk.form.php b/front/processmaker.helpdesk.form.php index 212a910..5a7175a 100644 --- a/front/processmaker.helpdesk.form.php +++ b/front/processmaker.helpdesk.form.php @@ -54,6 +54,7 @@ function processMakerShowCase($ID, $from_helpdesk) { $rand = rand(); + $PM_SOAP->echoDomain(); echo ""; $tkt = new Ticket; diff --git a/hook.php b/hook.php index 130e12b..85cad3f 100644 --- a/hook.php +++ b/hook.php @@ -24,66 +24,6 @@ function plugin_processmaker_MassiveActions($type) { } -//function plugin_processmaker_MassiveActionsDisplay($options) { - -// switch ($options['itemtype']) { -// case 'PluginProcessmakerProcess' : -// //case 'PluginProcessmakerCase' : -// switch ($options['action']) { -// case "plugin_processmaker_taskrefresh" : -// //case "plugin_processmaker_purgecase" : -// echo ""; -// break; - -// } -// break; -// } -// return ""; -//} - - -//function plugin_processmaker_MassiveActionsProcess($data) { - -// switch ($data['action']) { - -// case "plugin_processmaker_taskrefresh" : -// if ($data['itemtype'] == 'PluginProcessmakerProcess') { -// foreach ($data["item"] as $key => $val) { -// if ($val == 1) { -// $process = new PluginProcessmakerProcess; -// $process->refreshTasks( array( 'id' => $key ) ); - -// } -// } -// } -// break; -// //case "plugin_processmaker_purgecase": -// // if ($data['itemtype'] == 'PluginProcessmakerCase') { -// // foreach ($data["item"] as $key => $val) { -// // if ($val == 1) { -// // $locCase= new PluginProcessmakerCase; -// // //$locCase->( array( 'id' => $key ) ); - -// // } -// // } -// // } -// // break; -// //case 'plugin_processmaker_process_profile_delete' : -// // if ($data['itemtype'] == 'PluginProcessmakerProcess_Profile') { -// // foreach ($data["item"] as $key => $val) { -// // if ($val == 1) { -// // $process_profile = new PluginProcessmakerProcess_Profile; -// // $process_profile->delete( array( 'id' => $key ), true ); - -// // } -// // } -// // } -// // break; - -// } -//} - /** * Summary of plugin_processmaker_install * Creates tables and initializes tasks, "GLPI Requesters" group @@ -192,6 +132,7 @@ function plugin_pre_item_update_processmaker(CommonITILObject $parm) { switch ($key) { case 'global_validation' : $locVar[ 'GLPI_TICKET_GLOBAL_VALIDATION' ] = $val; + $locVar[ 'GLPI_ITEM_GLOBAL_VALIDATION' ] = $val; break; case 'itilcategories_id' : $locVar[ 'GLPI_ITEM_ITIL_CATEGORY_ID' ] = $val; @@ -250,73 +191,6 @@ function plugin_item_update_processmaker_satisfaction($parm) { } } -///** -// * Summary of plugin_pre_item_purge_processmaker -// * @param mixed $parm is the object -// */ -//function plugin_pre_item_purge_processmaker ( $parm ) { - -// if ($parm->getType() == 'Ticket_User' && is_array( $parm->fields ) && isset( $parm->fields['type'] ) && $parm->fields['type'] == 2) { -// $itemId = $parm->fields['tickets_id']; -// $itemType = 'Ticket'; -// $technicians = PluginProcessmakerProcessmaker::getItemUsers( $itemType, $itemId, 2 ); // 2 for technicians - -// if (PluginProcessmakerCase::getIDFromItem($itemType, $itemId) && count($technicians) == 1) { -// $parm->input = null; // to cancel deletion of the last tech in the ticket -// } -// } -//} - -///** -// * Summary of plugin_item_purge_processmaker -// * @param mixed $parm is the object -// */ -//function plugin_item_purge_processmaker($parm) { -// global $DB, $PM_SOAP; - -// //$objects = ['Ticket', 'Change', 'Problem']; -// $object_users = ['Ticket_User', 'Change_User', 'Problem_User']; - -// if (in_array($parm->getType(), $object_users) && is_array( $parm->fields ) && isset( $parm->fields['type'] ) && $parm->fields['type'] == 2) { - -// // We just deleted a tech from this ticket then we must if needed "de-assign" the tasks assigned to this tech -// // and re-assign them to the first tech in the list !!!! - -// $itemType = strtolower(explode('_', $parm->getType())[0]); // $parm->getType() returns 'Ticket_User'; -// $itemId = $parm->fields[$itemType.'s_id']; -// $cases = PluginProcessmakerCase::getIDsFromItem($itemType, $itemId); -// foreach ($cases as $cases_id) { -// // cases are existing for this item -// $locCase = new PluginProcessmakerCase; -// if ($locCase->getFromDB($cases_id)) { -// $technicians = PluginProcessmakerProcessmaker::getItemUsers($itemType, $itemId, CommonITILActor::ASSIGN); - -// $locVars = array( 'GLPI_TICKET_TECHNICIAN_GLPI_ID' => $technicians[0]['glpi_id'], -// 'GLPI_ITEM_TECHNICIAN_GLPI_ID' => $technicians[0]['glpi_id'], -// 'GLPI_TICKET_TECHNICIAN_PM_ID' => $technicians[0]['pm_id'], -// 'GLPI_ITEM_TECHNICIAN_PM_ID' => $technicians[0]['pm_id'] -// ); - -// // and we must find all tasks assigned to this former user and re-assigned them to new user (if any :))! -// $caseInfo = $locCase->getCaseInfo( ); -// if ($caseInfo !== false) { -// $locCase->sendVariables( $locVars); -// // need to get info on the thread of the GLPI current user -// // we must retreive currentGLPI user from this array -// $GLPICurrentPMUserId = PluginProcessmakerUser::getPMUserId( $parm->fields['users_id'] ); -// if (property_exists($caseInfo, 'currentUsers') && is_array( $caseInfo->currentUsers )) { -// foreach ($caseInfo->currentUsers as $caseUser) { -// if ($caseUser->userId == $GLPICurrentPMUserId && in_array( $caseUser->delThreadStatus, array('DRAFT', 'OPEN', 'PAUSE' ) )) { -// $locCase->reassignCase($caseUser->delIndex, $caseUser->taskId, $caseUser->delThread, $parm->fields['users_id'], $technicians[0]['pm_id'] ); -// } -// } -// } -// } - -// } -// } -// } -//} function plugin_processmaker_post_init() { global $PM_DB, $PM_SOAP; @@ -352,22 +226,26 @@ function plugin_processmaker_change_profile() { function plugin_item_update_processmaker_tasks($parm) { global $DB, $CFG_GLPI, $PM_SOAP; - // 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 + && $parm->input['state'] == Planning::DONE + && $parm->oldvalues['state'] == Planning::TODO) { // the task has just been set to DONE state - $itemtype = str_replace( 'Task', '', $parm->getType() ); + //$itemtype = str_replace( 'Task', '', $parm->getType() ); $pmTask = new PluginProcessmakerTask($parm->getType()); $pmTask->getFromDB($parm->fields['id']); $locCase = new PluginProcessmakerCase; - $locCase->getFromDB($pmTask->fields['plugin_processmaker_cases_id']); //Item($itemtype, $parm->fields['tickets_id']); + $locCase->getFromDB($pmTask->fields['plugin_processmaker_cases_id']); $srccase_guid = $locCase->fields['case_guid']; + $msg = ' $locCase: '.str_replace("\n", "\n ", print_r($locCase, true))."\n"; + $msg .= ' $task: '.str_replace("\n", "\n ", print_r($parm, true))."\n"; + $msg .= ' $pmTask: '.str_replace("\n", "\n ", print_r($pmTask, true))."\n"; + $msg .= "\n"; + foreach ($DB->request( 'glpi_plugin_processmaker_caselinks', "is_active = 1 AND sourcetask_guid='".$pmTaskCat->fields['pm_task_guid']."'") as $targetTask) { // Must check the condition @@ -390,7 +268,7 @@ function plugin_item_update_processmaker_tasks($parm) { // 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"}} + // {"method":"POST","url":"urloftheservice","params":json_object} // 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 @@ -410,9 +288,20 @@ function plugin_item_update_processmaker_tasks($parm) { $infoForTasks[ "@@$casevar" ] = "'$varval'"; unset( $infoForTasks[ $casevar ] ); } + + $msg .= " ***********\n"; + $msg .= ' $targetTask: '.str_replace("\n", "\n ", print_r($targetTask, true))."\n"; + $targetTask['sourcecondition'] = str_replace( array_keys($infoForTasks), $infoForTasks, $targetTask['sourcecondition'] ); - if (eval( "return ".$targetTask['sourcecondition'].";" )) { + $eval = eval( "return (".$targetTask['sourcecondition']." ? 1 : 0);" ); + + $msg .= ' $infoForTasks: '.str_replace("\n", "\n ", print_r($infoForTasks, true))."\n"; + $msg .= ' $targetTask[\'sourcecondition\']: '.str_replace("\n", "\n ", print_r($targetTask['sourcecondition'], true))."\n"; + $msg .= ' $result: '."$eval\n"; + $msg .= "\n"; + + if ($eval) { // 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 @@ -436,9 +325,13 @@ function plugin_item_update_processmaker_tasks($parm) { $ch = curl_init(); $externalapplication['url'] = eval( "return '".str_replace( array_keys($infoForTasks), $infoForTasks, $externalapplication['url'])."' ;" ); // '??? curl_setopt($ch, CURLOPT_URL, $externalapplication['url'] ); + if (isset($externalapplication['method']) && $externalapplication['method'] == 'POST') { + curl_setopt($ch, CURLOPT_POST, 1); + } } if ($targetTask['is_self']) { + $PM_SOAP->login(true); $taskCase = $PM_SOAP->taskCase( $srccase_guid ); foreach ($taskCase as $task) { // search for target task guid @@ -446,6 +339,7 @@ function plugin_item_update_processmaker_tasks($parm) { break; } } + $PM_SOAP->login(); $postdata['APP_UID'] = $srccase_guid; $postdata['DEL_INDEX'] = $task->delegate; @@ -470,20 +364,22 @@ function plugin_item_update_processmaker_tasks($parm) { 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":"urloftheservice","params":{"user":"@@USER_ID","system":"GPP","list":"@@ROLE_LIST"}} // url is the URL to be called $externalapplicationparams['id'] = $cronaction->getID(); $externalapplicationparams = json_encode( $externalapplicationparams, JSON_HEX_APOS | JSON_HEX_QUOT); - curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $externalapplicationparams); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . strlen($externalapplicationparams), 'Expect:']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 ); + curl_setopt($ch, CURLOPT_VERBOSE, 1); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $pmconfig->fields['ssl_verify']); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $pmconfig->fields['ssl_verify']); - //curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1 ) ; - //curl_setopt($ch, CURLOPT_PROXY, "localhost:8889"); + //curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1 ) ; + //curl_setopt($ch, CURLOPT_PROXY, "localhost:8889"); $response = curl_exec ($ch); @@ -493,6 +389,7 @@ function plugin_item_update_processmaker_tasks($parm) { } // } } else { + // TODO to review this part of code as it is no longer usable like this !!! 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 @@ -531,5 +428,9 @@ function plugin_item_update_processmaker_tasks($parm) { } } + + $msg .= "================\n"; + Toolbox::logInFile("processmaker", $msg); + } } diff --git a/inc/case.class.php b/inc/case.class.php index 3dbfe2e..907507a 100644 --- a/inc/case.class.php +++ b/inc/case.class.php @@ -28,13 +28,13 @@ class PluginProcessmakerCase extends CommonDBTM { //} - //static function canView() { - // return Session::haveRightsOr('plugin_processmaker_case', [READ, UPDATE]); - //} + static function canView() { + return Session::haveRightsOr('plugin_processmaker_case', [READ, UPDATE]); + } - //function canViewItem() { - // return Session::haveRightsOr('plugin_processmaker_case', READ); - //} + function canViewItem() { + return Session::haveRight('plugin_processmaker_case', READ); + } //static function canUpdate( ) { // return Session::haveRight('plugin_processmaker_config', UPDATE); @@ -44,25 +44,31 @@ class PluginProcessmakerCase extends CommonDBTM { // return Session::haveRight('plugin_processmaker_config', UPDATE); //} + //function canEdit($ID) { + // return parent::canDelete(); + //} function maybeDeleted() { return false; } - static function canDelete() { - return parent::canDelete(); - } + //static function canDelete() { + // return parent::canDelete(); + //} - function canDeleteItem() { - return parent::canDeleteItem(); - } + //function canDeleteItem() { + // return parent::canDeleteItem(); + //} static function canPurge() { - return self::canDelete(); + return true; //self::canDelete(); } function canPurgeItem() { - return $this->canDeleteItem(); + return $_SESSION['glpiactiveprofile']['interface'] == 'central' + && $this->fields['plugin_processmaker_cases_id'] == 0 + && $this->canDeleteItem() + && (self::canDelete() || $this->fields['case_status'] == PluginProcessmakerCase::DRAFT); } static function canCancel() { @@ -83,7 +89,7 @@ class PluginProcessmakerCase extends CommonDBTM { // case is a sub-case $tabname = __('Sub-case', 'processmaker'); } - return [ __CLASS__ => $tabname." ".self::getStatus($item->fields['case_status']).""]; + return [ 'main' => $tabname." ".self::getStatus($item->fields['case_status']).""]; } else { $items_id = $item->getID(); $itemtype = $item->getType(); @@ -114,13 +120,13 @@ class PluginProcessmakerCase extends CommonDBTM { * @param integer $items_id is the item id * @return integer cases_id */ - static function getIDFromItem($itemtype, $items_id) { - $tmp = New self; - if ($tmp->getFromDBByQuery(" WHERE items_id=$items_id and itemtype='$itemtype'")) { - return $tmp->getID(); - } - return false; - } + //static function getIDFromItem($itemtype, $items_id) { + // $tmp = New self; + // if ($tmp->getFromDBByQuery(" WHERE items_id=$items_id and itemtype='$itemtype'")) { + // return $tmp->getID(); + // } + // return false; + //} /** @@ -133,7 +139,12 @@ class PluginProcessmakerCase extends CommonDBTM { static function getIDsFromItem($itemtype, $items_id) { $ret = []; $dbu = new DbUtils; - foreach ($dbu->getAllDataFromTable( self::getTable(), "items_id=$items_id AND itemtype='$itemtype'") as $case) { + $restrict = [ + "items_id" => $items_id, + "itemtype" => $itemtype,]; + + //foreach ($dbu->getAllDataFromTable( self::getTable(), "items_id=$items_id AND itemtype='$itemtype'") as $case) + foreach ($dbu->getAllDataFromTable( self::getTable(), $restrict) as $case) { $ret[] = $case['id']; } return $ret; @@ -156,7 +167,12 @@ class PluginProcessmakerCase extends CommonDBTM { * @return boolean */ function getFromGUID($case_guid) { - return $this->getFromDBByQuery(" WHERE case_guid='$case_guid'"); + $restrict=[ + 'WHERE' => [ + 'case_guid' => $case_guid, + ], + ]; + return $this->getFromDBByRequest($restrict); } @@ -477,9 +493,6 @@ class PluginProcessmakerCase extends CommonDBTM { */ static function showCaseInfoTab(CommonGLPI $case, $tabnum = 1, $withtemplate = 0) { // echo 'The idea is to show here the GLPI ITIL item to which it is linked, and to give a resume of the current case status, and to give possibility to delete or cancel the case.'; - - echo ""; - $itemtype = $case->fields['itemtype']; $maintitle = __('Case is linked to a %1s', 'processmaker'); @@ -487,7 +500,7 @@ class PluginProcessmakerCase extends CommonDBTM { $maintitle = __('Sub-case is linked to a %1s', 'processmaker'); } - echo ""; + echo ""; Ticket::commonListHeader(Search::HTML_OUTPUT); @@ -502,12 +515,8 @@ class PluginProcessmakerCase extends CommonDBTM { // it's a main case, not a sub-case // and we have the rights to cancel cases - // show a form to be able to cancel the case - $rand = rand(); echo "

"; - echo ""; - echo "
"; echo "
".sprintf($maintitle, $itemtype::getTypeName(1))."
".sprintf($maintitle, $itemtype::getTypeName(1))."
"; echo ""; echo ""; @@ -517,33 +526,27 @@ class PluginProcessmakerCase extends CommonDBTM { echo ""; echo "
".__('Case cancellation', 'processmaker')."
".__('Cancel case', 'processmaker')."
"; - Html::closeForm(); - } // will not show delete button if case is a sub-process // and will show it only if it is a draft or if current glpi user has the right to delete cases and session is central - if ($case->fields['plugin_processmaker_cases_id'] == 0 - && ($case->fields['case_status'] == self::DRAFT - || (plugin_processmaker_haveRight("case", DELETE) - && $_SESSION['glpiactiveprofile']['interface'] == 'central'))) { + if ($case->canPurgeItem($case->getID())) { // then propose a button to delete case - $rand = rand(); + // the button will be effectively shown by the showFormButtons() echo "

"; - echo ""; - echo "
"; echo ""; - echo ""; - echo ""; - echo "
".__('Case deletion', 'processmaker')."
".__('Delete case', 'processmaker').""; - echo ""; - echo ""; - echo ""; - echo "
"; + echo "".__('Case deletion', 'processmaker').""; + // echo "".__('Delete case', 'processmaker').""; + // echo ""; + // echo ""; + // echo ""; + // echo ""; + // echo ""; + echo ""; + echo "

"; - Html::closeForm(); } return; @@ -556,7 +559,7 @@ class PluginProcessmakerCase extends CommonDBTM { * @param CommonITILObject $item */ static function showForItem(CommonITILObject $item) { - global $DB, $CFG_GLPI; + global $DB, $CFG_GLPI, $PM_SOAP; $items_id = $item->getField('id'); $itemtype = $item->getType(); @@ -570,7 +573,7 @@ class PluginProcessmakerCase extends CommonDBTM { $rand = mt_rand(); - $query = "SELECT gppc.`id` AS assocID, gppc.`id` as id, gppp.name as pname, gppc.`case_status`, gppc.`plugin_processmaker_cases_id` + $query = "SELECT gppc.`id` AS assocID, gppc.`id` as id, gppp.id as pid, gppp.name as pname, gppc.`case_status`, gppc.`plugin_processmaker_cases_id` FROM `glpi_plugin_processmaker_cases` as gppc LEFT JOIN `glpi_plugin_processmaker_processes` AS gppp ON gppp.`id`=gppc.`plugin_processmaker_processes_id` WHERE gppc.`itemtype` = '$itemtype' @@ -579,25 +582,33 @@ class PluginProcessmakerCase extends CommonDBTM { $result = $DB->query($query); $cases = []; - $used = []; + $used = []; + $pid = []; if ($numrows = $DB->numrows($result)) { while ($data = $DB->fetch_assoc($result)) { $cases[$data['id']] = $data; - $used[$data['id']] = $data['id']; + $used[$data['id']] = $data['id']; + if (isset($pid[$data['pid']])) { + $pid[$data['pid']] += 1; + } else { + $pid[$data['pid']] = 1; + } } } $columns = ['pname' => __('Process', 'processmaker'), - 'name' => __('Title', 'processmaker'), - 'status' => __('Status', 'processmaker'), - 'sub' => __('Sub-case of', 'processmaker') + 'name' => __('Title', 'processmaker'), + 'status' => __('Status', 'processmaker'), + 'sub' => __('Sub-case of', 'processmaker') ]; // check if item is not solved nor closed if ($canupdate && $item->fields['status'] != CommonITILObject::SOLVED && $item->fields['status'] != CommonITILObject::CLOSED - && $_SESSION['glpiactiveprofile']['interface'] != 'helpdesk') { + && $_SESSION['glpiactiveprofile']['interface'] != 'helpdesk' + && ($numrows < $PM_SOAP->config->fields['max_cases_per_item'] + || $PM_SOAP->config->fields['max_cases_per_item'] == 0)) { echo "
"; echo ""; echo ""; @@ -621,7 +632,8 @@ class PluginProcessmakerCase extends CommonDBTM { PluginProcessmakerProcess::dropdown(['value' => 0, 'entity' => $item->fields['entities_id'], 'name' => 'plugin_processmaker_processes_id', - 'condition' => "is_active=1 $is_itemtype" + 'condition' => "is_active=1 $is_itemtype", + 'specific_tags' => ['count_cases_per_item' => $pid] ]); echo ""; echo ""; @@ -728,7 +740,7 @@ class PluginProcessmakerCase extends CommonDBTM { if ($item->getType() == __CLASS__) { // we are in a case viewing the main tab // the 'Case infos' tab - self::showCaseInfoTab($item, $tabnum, $withtemplate); + //self::showCaseInfoTab($item, $tabnum, $withtemplate); } else { @@ -1099,168 +1111,172 @@ class PluginProcessmakerCase extends CommonDBTM { /** - * Summary of getSearchOptions + * Get default values to search engine to override + **/ + static function getDefaultSearchRequest() { + + $search = ['sort' => 1, + 'order' => 'DESC']; + + return $search; + } + + + /** + * Summary of rawSearchOptions * @return mixed */ - function getSearchOptions() { + function rawSearchOptions() { $tab = []; - $tab['common'] = __('Process cases', 'processmaker'); + $tab[] = [ + 'id' => 'common', + 'name' => __('Process cases', 'processmaker') + ]; - $tab[1]['table'] = self::getTable(); - $tab[1]['field'] = 'id'; - $tab[1]['name'] = __('ID', 'processmaker'); - $tab[1]['datatype'] = 'number'; - $tab[1]['searchtype'] = 'contains'; - $tab[1]['massiveaction'] = false; + $tab[] = [ + 'id' => '1', + 'table' => $this->getTable(), + 'field' => 'id', + 'name' => __('ID'), + 'datatype' => 'number', + 'searchtype' => 'contains', + 'massiveaction' => false + ]; - $tab[2]['table'] = self::getTable(); - $tab[2]['field'] = 'name'; - $tab[2]['name'] = __('Title', 'processmaker'); - $tab[2]['datatype'] = 'itemlink'; - $tab[2]['searchtype'] = 'contains'; - $tab[2]['massiveaction'] = false; + $tab[] = [ + 'id' => '2', + 'table' => $this->getTable(), + 'field' => 'name', + 'name' => __('Title'), + 'datatype' => 'itemlink', + 'searchtype' => 'contains', + 'massiveaction' => false + ]; - $tab[3]['table'] = self::getTable(); - $tab[3]['field'] = 'plugin_processmaker_processes_id'; - $tab[3]['name'] = __('Process', 'processmaker'); - $tab[3]['datatype'] = 'specific'; - $tab[3]['searchtype'] = ['contains', 'equals', 'notequals']; - $tab[3]['massiveaction'] = false; + $tab[] = [ + 'id' => '3', + 'table' => $this->getTable(), + 'field' => 'plugin_processmaker_processes_id', + 'name' => __('Process', 'processmaker'), + 'datatype' => 'specific', + 'searchtype' => [ + '0' => 'contains', + '1' => 'equals', + '2' => 'notequals' + ], + 'massiveaction' => false + ]; - $tab[7]['table'] = self::getTable(); - $tab[7]['field'] = 'itemtype'; - $tab[7]['name'] = __('Item type', 'processmaker'); - $tab[7]['massiveaction'] = false; - $tab[7]['datatype'] = 'specific'; - $tab[7]['searchtype'] = ['contains', 'equals', 'notequals']; + $tab[] = [ + 'id' => '7', + 'table' => $this->getTable(), + 'field' => 'itemtype', + 'name' => __('Item type'), + 'massiveaction' => false, + 'datatype' => 'specific', + 'searchtype' => [ + '0' => 'contains', + '1' => 'equals', + '2' => 'notequals' + ] + ]; - $tab[8]['table'] = self::getTable(); - $tab[8]['field'] = 'items_id'; - $tab[8]['name'] = __('Item', 'processmaker'); - $tab[8]['massiveaction'] = false; - $tab[8]['datatype'] = 'specific'; - $tab[8]['additionalfields'] = ['itemtype']; + $tab[] = [ + 'id' => '8', + 'table' => $this->getTable(), + 'field' => 'items_id', + 'name' => __('Item'), + 'massiveaction' => false, + 'datatype' => 'specific', + 'additionalfields' => [ + '0' => 'itemtype' + ] + ]; - $tab[9]['table'] = Entity::getTable(); - $tab[9]['field'] = 'name'; - $tab[9]['name'] = __('Item entity', 'processmaker'); - $tab[9]['massiveaction'] = false; - $tab[9]['datatype'] = 'itemlink'; + $tab[] = [ + 'id' => '9', + 'table' => 'glpi_entities', + 'field' => 'name', + 'name' => __('Item entity', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'itemlink' + ]; - $tab[10]['table'] = self::getTable(); - $tab[10]['field'] = 'case_status'; - $tab[10]['name'] = __('Status', 'processmaker'); - $tab[10]['datatype'] = 'specific'; - $tab[10]['searchtype'] = ['contains', 'equals', 'notequals']; - $tab[10]['massiveaction'] = false; + $tab[] = [ + 'id' => '10', + 'table' => $this->getTable(), + 'field' => 'case_status', + 'name' => __('Status'), + 'datatype' => 'specific', + 'searchtype' => [ + '0' => 'contains', + '1' => 'equals', + '2' => 'notequals' + ], + 'massiveaction' => false + ]; - $tab[14]['table'] = self::getTable(); - $tab[14]['field'] = 'plugin_processmaker_cases_id'; - $tab[14]['name'] = __('Sub-case of', 'processmaker'); - $tab[14]['datatype'] = 'specific'; - //$tab[14]['searchtype'] = ['contains', 'equals', 'notequals']; - $tab[14]['massiveaction'] = false; - $tab[14]['nosearch'] = true; + $tab[] = [ + 'id' => '14', + 'table' => $this->getTable(), + 'field' => 'plugin_processmaker_cases_id', + 'name' => __('Sub-case of', 'processmaker'), + 'datatype' => 'specific', + 'massiveaction' => false, + 'nosearch' => true + ]; - $tab[16]['table'] = self::getTable(); - $tab[16]['field'] = 'id'; - $tab[16]['name'] = __('Creation date', 'processmaker'); - $tab[16]['datatype'] = 'specific'; - //$tab[16]['searchtype'] = ['contains', 'equals', 'notequals']; - $tab[16]['massiveaction'] = false; - $tab[16]['nosearch'] = true; - $tab[16]['processmaker_cases'] = 'creation_date'; + $tab[] = [ + 'id' => '16', + 'table' => $this->getTable(), + 'field' => 'id', + 'name' => __('Creation date'), + 'datatype' => 'specific', + 'massiveaction' => false, + 'nosearch' => true, + 'processmaker_cases' => 'creation_date' + ]; - $tab[18]['table'] = self::getTable(); - $tab[18]['field'] = 'id'; - $tab[18]['name'] = __('Last update date', 'processmaker'); - $tab[18]['datatype'] = 'specific'; - // $tab[18]['searchtype'] = ['contains', 'equals', 'notequals']; - $tab[18]['massiveaction'] = false; - $tab[18]['nosearch'] = true; - $tab[18]['processmaker_cases'] = 'update_date'; + $tab[] = [ + 'id' => '18', + 'table' => $this->getTable(), + 'field' => 'id', + 'name' => __('Last update'), + 'datatype' => 'specific', + 'massiveaction' => false, + 'nosearch' => true, + 'processmaker_cases' => 'update_date' + ]; return $tab; } function showForm ($ID, $options = ['candel'=>false]) { - //global $DB, $CFG_GLPI, $LANG; + $options['colspan'] = 6; + $options['formtitle'] = sprintf( __('Case status is \'%s\'', 'processmaker'), self::getStatus($this->fields['case_status'])); - $options['candel'] = true; - - $this->initForm($ID, $options); $this->showFormHeader($options); - //echo ""; - //echo "".__("Name").""; - //echo ""; - //echo ""; + $process = new PluginProcessmakerProcess; + $process->getFromDB($this->fields['plugin_processmaker_processes_id']); - //echo ""; - //echo "".__("Active").""; - //Dropdown::showYesNo("is_active", $this->fields["is_active"]); - //echo ""; + if ($process->fields['maintenance']) { + PluginProcessmakerProcess::showUnderMaintenance($process->fields['name'], 'small'); + } + self::showCaseInfoTab($this); - //echo ""; - //echo "".__("External data").""; - //Dropdown::showYesNo("is_externaldata", $this->fields["is_externaldata"]); - //echo ""; + //echo '
' ; - //echo ""; - //echo "".__("Self").""; - //Dropdown::showYesNo("is_self", $this->fields["is_self"]); - //echo ""; - - //echo ""; - //echo "".__("Source task GUID").""; - ////PluginProcessmakerTaskCategory::dropdown(array('name' => 'plugin_processmaker_taskcategories_id_source', - //// 'display_emptychoice' => false, - //// 'value' => $this->fields['plugin_processmaker_taskcategories_id_source'])); - //echo ""; - //echo ""; - - //echo ""; - //echo "".__("Target task GUID").""; - ////PluginProcessmakerTaskCategory::dropdown(array('name' => 'plugin_processmaker_taskcategories_id_target', - //// 'display_emptychoice' => false, - //// 'value' => $this->fields['plugin_processmaker_taskcategories_id_target'])); - //echo ""; - //echo ""; - - //echo ""; - //echo "".__("Target process GUID").""; - ////Dropdown::show( 'PluginProcessmakerProcess', array('name' => 'plugin_processmaker_processes_id', - //// 'display_emptychoice' => true, - //// 'value' => $this->fields['plugin_processmaker_processes_id'], - //// 'condition' => 'is_active = 1')); - //echo ""; - //echo ""; - - //echo ""; - //echo "".__("Target dynaform GUID").""; - //echo ""; - //echo ""; - - //echo ""; - //echo "".__("Source condition").""; - ////echo ""; - //echo ""; - //echo ""; - - //echo ""; - //echo "".__("Claim target task").""; - //Dropdown::showYesNo("is_targettoclaim", $this->fields["is_targettoclaim"]); - //echo ""; - - //echo ""; - //echo "".__("External application JSON config").""; - //echo ""; - //echo ""; - - $this->showFormButtons($options ); + Html::closeForm(); + $options['candel'] = true; + $this->showFormButtons($options); + echo Html::scriptBlock(" + $('#tabsbody th').css('text-align', 'center'); + $('#tabsbody td').css('text-align', 'center'); + "); } @@ -1271,21 +1287,31 @@ class PluginProcessmakerCase extends CommonDBTM { */ function defineTabs($options = []) { - // $ong = array('empty' => $this->getTypeName(1)); + $process = new PluginProcessmakerProcess; + $process->getFromDB($this->fields['plugin_processmaker_processes_id']); + $ong = []; - //$this->addDefaultFormTab($ong); + if (self::isLayoutWithMain()) { + $this->addDefaultFormTab($ong); + } - $this->addStandardTab('PluginProcessmakerTask', $ong, $options); + if (!$process->fields['maintenance']) { + $this->addStandardTab('PluginProcessmakerTask', $ong, $options); + } - $this->addStandardTab(__CLASS__, $ong, $options); + if (!self::isLayoutWithMain()) { + $this->addStandardTab(__CLASS__, $ong, $options); + } - $this->addStandardTab('PluginProcessmakerCasemap', $ong, $options); + if (!$process->fields['maintenance']) { + $this->addStandardTab('PluginProcessmakerCasemap', $ong, $options); - $this->addStandardTab('PluginProcessmakerCasehistory', $ong, $options); + $this->addStandardTab('PluginProcessmakerCasehistory', $ong, $options); - $this->addStandardTab('PluginProcessmakerCasechangelog', $ong, $options); + $this->addStandardTab('PluginProcessmakerCasechangelog', $ong, $options); - $this->addStandardTab('PluginProcessmakerCasedynaform', $ong, $options); + $this->addStandardTab('PluginProcessmakerCasedynaform', $ong, $options); + } return $ong; } @@ -1311,7 +1337,9 @@ class PluginProcessmakerCase extends CommonDBTM { $ret = true; $dbu = new DbUtils; // then must delete any sub-processes (sub-cases) - foreach ($dbu->getAllDataFromTable(self::getTable(), "`plugin_processmaker_cases_id` = ".$this->getID()) as $row) { + $restrict = ["plugin_processmaker_cases_id" => $this->getID()]; + //foreach ($dbu->getAllDataFromTable(self::getTable(), "`plugin_processmaker_cases_id` = ".$this->getID()) as $row) { + foreach ($dbu->getAllDataFromTable(self::getTable(), $restrict) as $row) { $tmp = new self; $tmp->fields = $row; $ret &= $tmp->delete(['id' => $row['id']]); @@ -1332,4 +1360,5 @@ class PluginProcessmakerCase extends CommonDBTM { return $DB->query($query); } + } diff --git a/inc/casechangelog.class.php b/inc/casechangelog.class.php index 9d10ce7..34c73e9 100644 --- a/inc/casechangelog.class.php +++ b/inc/casechangelog.class.php @@ -10,13 +10,14 @@ */ class PluginProcessmakerCasechangelog extends CommonDBTM { - static function displayTabContentForItem(CommonGLPI $case, $tabnum=1, $withtemplate=0) { + static function displayTabContentForItem(CommonGLPI $case, $tabnum = 1, $withtemplate = 0) { global $CFG_GLPI, $PM_SOAP; $rand = rand(); $caseHistoryURL = $PM_SOAP->serverURL."/cases/ajaxListener?action=changeLogHistory&rand=$rand"; + $PM_SOAP->echoDomain(); echo ""; //?rand=$rand' $iframe = ""; - $PM_SOAP->initCaseAndShowTab(['APP_UID' => $case->fields['case_guid'], 'DEL_INDEX' => 1], $iframe, $rand) ; + $PM_SOAP->initCaseAndShowTab(['APP_UID' => $case->fields['case_guid'], 'DEL_INDEX' => 1], $iframe, $rand); } - function getTabNameForItem(CommonGLPI $case, $withtemplate = 0){ + function getTabNameForItem(CommonGLPI $case, $withtemplate = 0) { return __('Change log', 'processmaker'); } -} \ No newline at end of file +} diff --git a/inc/casedynaform.class.php b/inc/casedynaform.class.php index e6d85f7..29d5a24 100644 --- a/inc/casedynaform.class.php +++ b/inc/casedynaform.class.php @@ -19,6 +19,7 @@ class PluginProcessmakerCasedynaform extends CommonDBTM { $proj = new PluginProcessmakerProcess; $proj->getFromDB($case->fields['plugin_processmaker_processes_id']); + $PM_SOAP->echoDomain(); echo ""; //?rand=$rand' echo ""; $iframe = ""; - $PM_SOAP->initCaseAndShowTab(['APP_UID' => $case->fields['case_guid'], 'DEL_INDEX' => 1], $iframe, $rand) ; + $PM_SOAP->initCaseAndShowTab(['APP_UID' => $case->fields['case_guid'], 'DEL_INDEX' => 1], $iframe, $rand); } - function getTabNameForItem(CommonGLPI $case, $withtemplate = 0){ + function getTabNameForItem(CommonGLPI $case, $withtemplate = 0) { return __('History', 'processmaker'); } -} \ No newline at end of file +} diff --git a/inc/caselink.class.php b/inc/caselink.class.php index 00b341c..a7e011a 100644 --- a/inc/caselink.class.php +++ b/inc/caselink.class.php @@ -148,136 +148,127 @@ class PluginProcessmakerCaselink extends CommonDBTM { /** - * Summary of getSearchOptions + * Summary of rawSearchOptions * @return mixed */ - function getSearchOptions() { + function rawSearchOptions() { $tab = []; - $tab['common'] = __('ProcessMaker', 'processmaker'); + $tab[] = [ + 'id' => 'common', + 'name' => __('ProcessMaker', 'processmaker') + ]; - $tab[1]['table'] = $this->getTable(); - $tab[1]['field'] = 'name'; - $tab[1]['name'] = __('Name'); - $tab[1]['datatype'] = 'itemlink'; - $tab[1]['itemlink_type'] = $this->getType(); + $tab[] = [ + 'id' => '1', + 'table' => $this->getTable(), + 'field' => 'name', + 'name' => __('Name'), + 'datatype' => 'itemlink', + 'itemlink_type' => 'PluginProcessmakerCaselink', + 'massiveaction' => false + ]; - $tab[8]['table'] = $this->getTable(); - $tab[8]['field'] = 'is_active'; - $tab[8]['name'] = __('Active'); - $tab[8]['massiveaction'] = true; - $tab[8]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '8', + 'table' => $this->getTable(), + 'field' => 'is_active', + 'name' => __('Active'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; - $tab[9]['table'] = $this->getTable(); - $tab[9]['field'] = 'date_mod'; - $tab[9]['name'] = __('Last update'); - $tab[9]['massiveaction'] = false; - $tab[9]['datatype'] = 'datetime'; + $tab[] = [ + 'id' => '9', + 'table' => $this->getTable(), + 'field' => 'date_mod', + 'name' => __('Last update'), + 'massiveaction' => false, + 'datatype' => 'datetime' + ]; - $tab[10]['table'] = $this->getTable(); - $tab[10]['field'] = 'is_externaldata'; - $tab[10]['name'] = __('External data', 'processmaker'); - $tab[10]['massiveaction'] = false; - $tab[10]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '10', + 'table' => $this->getTable(), + 'field' => 'is_externaldata', + 'name' => __('External data', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'bool' + ]; - $tab[11]['table'] = $this->getTable(); - $tab[11]['field'] = 'is_self'; - $tab[11]['name'] = __('Self', 'processmaker'); - $tab[11]['massiveaction'] = false; - $tab[11]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '11', + 'table' => $this->getTable(), + 'field' => 'is_self', + 'name' => __('Self', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'bool' + ]; - $tab[12]['table'] = $this->getTable(); - $tab[12]['field'] = 'is_targettoclaim'; - $tab[12]['name'] = __('Claim target task', 'processmaker'); - $tab[12]['massiveaction'] = false; - $tab[12]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '12', + 'table' => $this->getTable(), + 'field' => 'is_targettoclaim', + 'name' => __('Claim target task', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'bool' + ]; - $tab[13]['table'] = $this->getTable(); - $tab[13]['field'] = 'externalapplication'; - $tab[13]['name'] = __('External application JSON config', 'processmaker'); - $tab[13]['massiveaction'] = false; - $tab[13]['datatype'] = 'text'; + $tab[] = [ + 'id' => '13', + 'table' => $this->getTable(), + 'field' => 'externalapplication', + 'name' => __('External application JSON config', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'text' + ]; - $tab[14]['table'] = $this->getTable(); - $tab[14]['field'] = 'sourcetask_guid'; - $tab[14]['name'] = __('Source task GUID', 'processmaker'); - $tab[14]['massiveaction'] = false; - $tab[14]['datatype'] = 'text'; + $tab[] = [ + 'id' => '14', + 'table' => $this->getTable(), + 'field' => 'sourcetask_guid', + 'name' => __('Source task GUID', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'text' + ]; - $tab[15]['table'] = $this->getTable(); - $tab[15]['field'] = 'targettask_guid'; - $tab[15]['name'] = __('Target task GUID', 'processmaker'); - $tab[15]['massiveaction'] = false; - $tab[15]['datatype'] = 'text'; + $tab[] = [ + 'id' => '15', + 'table' => $this->getTable(), + 'field' => 'targettask_guid', + 'name' => __('Target task GUID', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'text' + ]; - $tab[16]['table'] = $this->getTable(); - $tab[16]['field'] = 'targetdynaform_guid'; - $tab[16]['name'] = __('Target dynaform GUID', 'processmaker'); - $tab[16]['massiveaction'] = false; - $tab[16]['datatype'] = 'text'; + $tab[] = [ + 'id' => '16', + 'table' => $this->getTable(), + 'field' => 'targetdynaform_guid', + 'name' => __('Target dynaform GUID', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'text' + ]; - $tab[17]['table'] = $this->getTable(); - $tab[17]['field'] = 'targetprocess_guid'; - $tab[17]['name'] = __('Target process GUID', 'processmaker'); - $tab[17]['massiveaction'] = false; - $tab[17]['datatype'] = 'text'; + $tab[] = [ + 'id' => '17', + 'table' => $this->getTable(), + 'field' => 'targetprocess_guid', + 'name' => __('Target process GUID', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'text' + ]; - $tab[18]['table'] = $this->getTable(); - $tab[18]['field'] = 'sourcecondition'; - $tab[18]['name'] = __('Source condition', 'processmaker'); - $tab[18]['massiveaction'] = false; - $tab[18]['datatype'] = 'text'; - - //$tab[14]['table'] = 'glpi_taskcategories'; - //$tab[14]['field'] = 'completename'; //'plugin_processmaker_taskcategories_id_source'; - //$tab[14]['name'] = __('Source task'); - //$tab[14]['massiveaction'] = false; - //$tab[14]['datatype'] = 'dropdown'; - //$tab[14]['forcegroupby'] = true; - //$tab[14]['joinparams'] = - // [ - // 'beforejoin' => [ - // 'table' => 'glpi_plugin_processmaker_taskcategories', - // 'joinparams' => [ - // 'beforejoin' => [ - // 'table' => 'glpi_plugin_processmaker_caselinks' - // ] - // ] - // ] - // ]; + $tab[] = [ + 'id' => '18', + 'table' => $this->getTable(), + 'field' => 'sourcecondition', + 'name' => __('Source condition', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'text' + ]; return $tab; } - //static function getMenuContent() { - - // if (!Session::haveRight('entity', READ)) { - // return; - // } - - // $front_page = "/plugins/processmaker/front"; - // $menu = array(); - // //$menu['title'] = self::getMenuName(); - // //$menu['page'] = "$front_page/caselink.php"; - - // $itemtypes = array('PluginProcessmakerCaselink' => 'processmakercaselinks'); - - // foreach ($itemtypes as $itemtype => $option) { - // $menu['options'][$option]['title'] = $itemtype::getTypeName(Session::getPluralNumber()); - // switch( $itemtype ) { - // case 'PluginProcessmakerCaselink': - // $menu['options'][$option]['page'] = $itemtype::getSearchURL(false); - // $menu['options'][$option]['links']['search'] = $itemtype::getSearchURL(false); - // if ($itemtype::canCreate()) { - // $menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); - // } - // break ; - // default : - // $menu['options'][$option]['page'] = PluginProcessmakerCaselink::getSearchURL(false); - // break ; - // } - - // } - // return $menu; - //} } diff --git a/inc/caselinkaction.class.php b/inc/caselinkaction.class.php index bce380d..60f0eb8 100644 --- a/inc/caselinkaction.class.php +++ b/inc/caselinkaction.class.php @@ -9,4 +9,4 @@ * @author MoronO */ class PluginProcessmakerCaselinkaction extends CommonDBTM { -} \ No newline at end of file +} diff --git a/inc/casemap.class.php b/inc/casemap.class.php index 2b2c53a..4c268c0 100644 --- a/inc/casemap.class.php +++ b/inc/casemap.class.php @@ -10,7 +10,7 @@ */ class PluginProcessmakerCasemap extends CommonDBTM { - static function displayTabContentForItem(CommonGLPI $case, $tabnum=1, $withtemplate=0) { + static function displayTabContentForItem(CommonGLPI $case, $tabnum = 1, $withtemplate = 0) { global $CFG_GLPI, $PM_SOAP; $rand = rand(); @@ -26,6 +26,7 @@ class PluginProcessmakerCasemap extends CommonDBTM { "/cases/ajaxListener?action=processMap" )."&rand=$rand"; + $PM_SOAP->echoDomain(); echo ""; //?rand=$rand' $iframe = ""; - $PM_SOAP->initCaseAndShowTab(['APP_UID' => $case->fields['case_guid'], 'DEL_INDEX' => 1], $iframe, $rand) ; + $PM_SOAP->initCaseAndShowTab(['APP_UID' => $case->fields['case_guid'], 'DEL_INDEX' => 1], $iframe, $rand); } - function getTabNameForItem(CommonGLPI $case, $withtemplate = 0){ + function getTabNameForItem(CommonGLPI $case, $withtemplate = 0) { return __('Map', 'processmaker'); } -} \ No newline at end of file +} diff --git a/inc/config.class.php b/inc/config.class.php index 9520523..3ad759e 100644 --- a/inc/config.class.php +++ b/inc/config.class.php @@ -158,8 +158,9 @@ class PluginProcessmakerConfig extends CommonDBTM { echo ""; echo "".__('Server URL (must be in same domain than GLPI)', 'processmaker').""; echo ""; - echo ""; + echo "\n"; + echo ""; echo "".__('Common domain with GLPI', 'processmaker').""; echo "
".$config->fields['domain']."
"; @@ -315,24 +316,29 @@ class PluginProcessmakerConfig extends CommonDBTM { } else { echo "".__('Not connected'); } - echo "\n"; + + echo ""; + echo "" . __('Max cases per item (0=unlimited)', 'processmaker') . ""; + echo ""; + echo "\n"; + } else { echo ""; PluginProcessmakerProcessmaker::showUnderMaintenance(); echo ""; } - echo "".__('Maintenance').""; + echo "".__('Maintenance').""; - echo ""; - echo "".__('Maintenance mode').""; - Dropdown::showYesNo("maintenance", $config->fields['maintenance']); - echo ""; + echo ""; + echo "".__('Maintenance mode').""; + Dropdown::showYesNo("maintenance", $config->fields['maintenance']); + echo ""; - echo ""; + echo ""; - echo "".__('Processmaker system information', 'processmaker').""; + echo "".__('Processmaker system information', 'processmaker').""; if ($setup_ok) { $info = $PM_SOAP->systemInformation( ); echo ''.__('Version', 'processmaker').''.$info->version.''; @@ -347,7 +353,7 @@ class PluginProcessmakerConfig extends CommonDBTM { } else { echo ''.__('Version', 'processmaker').''.__('Not yet!', 'processmaker').''; } - $config->showFormButtons(['candel'=>false]); + $config->showFormButtons(['candel' => false]); return false; } diff --git a/inc/process.class.php b/inc/process.class.php index 8d8d3c6..ea2cbe3 100644 --- a/inc/process.class.php +++ b/inc/process.class.php @@ -44,6 +44,19 @@ class PluginProcessmakerProcess extends CommonDBTM { return false; } + + /** + * Get default values to search engine to override + **/ + static function getDefaultSearchRequest() { + + $search = ['sort' => 1, + 'order' => 'ASC']; + + return $search; + } + + /** * Summary of refreshTasks * will refresh (re-synch) all process task list @@ -93,7 +106,9 @@ class PluginProcessmakerProcess extends CommonDBTM { } $pmtask = new PluginProcessmakerTaskCategory; - $currentasksinprocess = $dbu->getAllDataFromTable($pmtask->getTable(), '`is_active` = 1 AND `plugin_processmaker_processes_id` = '.$this->getID()); + $restrict = ["is_active" => '1', 'plugin_processmaker_processes_id' => $this->getID()]; + //$currentasksinprocess = $dbu->getAllDataFromTable($pmtask->getTable(), '`is_active` = 1 AND `plugin_processmaker_processes_id` = '.$this->getID()); + $currentasksinprocess = $dbu->getAllDataFromTable($pmtask->getTable(), $restrict); $tasks=[]; foreach ($currentasksinprocess as $task) { $tasks[$task['pm_task_guid']] = $task; @@ -288,7 +303,9 @@ class PluginProcessmakerProcess extends CommonDBTM { $tmp->deleteByCriteria(['plugin_processmaker_processes_id' => $key]); // must delete any taskcategory and translations - $pmtaskcategories = $dbu->getAllDataFromTable( PluginProcessmakerTaskCategory::getTable(), "plugin_processmaker_processes_id = $key"); + $restrict = ["plugin_processmaker_processes_id" => $key]; + //$pmtaskcategories = $dbu->getAllDataFromTable( PluginProcessmakerTaskCategory::getTable(), "plugin_processmaker_processes_id = $key"); + $pmtaskcategories = $dbu->getAllDataFromTable( PluginProcessmakerTaskCategory::getTable(), $restrict ); foreach ($pmtaskcategories as $pmcat) { // delete taskcat $tmp = new TaskCategory; @@ -387,104 +404,162 @@ class PluginProcessmakerProcess extends CommonDBTM { /** - * Summary of getSearchOptions + * Summary of rawSearchOptions * @return mixed */ - function getSearchOptions() { + function rawSearchOptions() { $tab = []; - $tab['common'] = __('ProcessMaker', 'processmaker'); + $tab[] = [ + 'id' => 'common', + 'name' => __('ProcessMaker', 'processmaker') + ]; - $tab[1]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[1]['field'] = 'name'; - $tab[1]['name'] = __('Name'); - $tab[1]['datatype'] = 'itemlink'; - $tab[1]['itemlink_type'] = $this->getType(); + $tab[] = [ + 'id' => '1', + 'table' => $this->getTable(), + 'field' => 'name', + 'name' => __('Name'), + 'datatype' => 'itemlink', + 'itemlink_type' => 'PluginProcessmakerProcess', + 'massiveaction' => false + ]; - //$tab[7]['table'] = 'glpi_plugin_processmaker_processes'; - //$tab[7]['field'] = 'is_helpdeskvisible'; - //$tab[7]['name'] = $LANG['tracking'][39]; - //$tab[7]['massiveaction'] = true; - //$tab[7]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '8', + 'table' => $this->getTable(), + 'field' => 'is_active', + 'name' => __('Active'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; - $tab[8]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[8]['field'] = 'is_active'; - $tab[8]['name'] = __('Active'); - $tab[8]['massiveaction'] = true; - $tab[8]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '4', + 'table' => $this->getTable(), + 'field' => 'comment', + 'name' => __('Comments'), + 'massiveaction' => true, + 'datatype' => 'text' + ]; - $tab[4]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[4]['field'] = 'comment'; - $tab[4]['name'] = __('Comments'); - $tab[4]['massiveaction'] = true; - $tab[4]['datatype'] = 'text'; + $tab[] = [ + 'id' => '9', + 'table' => $this->getTable(), + 'field' => 'date_mod', + 'name' => __('Last update'), + 'massiveaction' => false, + 'datatype' => 'datetime' + ]; - $tab[9]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[9]['field'] = 'date_mod'; - $tab[9]['name'] = __('Last update'); - $tab[9]['massiveaction'] = false; - $tab[9]['datatype'] = 'datetime'; + $tab[] = [ + 'id' => '10', + 'table' => $this->getTable(), + 'field' => 'process_guid', + 'name' => __('Process GUID', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'text' + ]; - $tab[10]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[10]['field'] = 'process_guid'; - $tab[10]['name'] = __('Process GUID', 'processmaker'); - $tab[10]['massiveaction'] = false; - $tab[10]['datatype'] = 'text'; + $tab[] = [ + 'id' => '11', + 'table' => $this->getTable(), + 'field' => 'project_type', + 'name' => __('Process type', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'specific' + ]; - $tab[11]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[11]['field'] = 'project_type'; - $tab[11]['name'] = __('Process type', 'processmaker'); - $tab[11]['massiveaction'] = false; - $tab[11]['datatype'] = 'specific'; + $tab[] = [ + 'id' => '12', + 'table' => $this->getTable(), + 'field' => 'hide_case_num_title', + 'name' => __('Hide case num. & title', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; - $tab[12]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[12]['field'] = 'hide_case_num_title'; - $tab[12]['name'] = __('Hide case num. & title', 'processmaker'); - $tab[12]['massiveaction'] = true; - $tab[12]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '13', + 'table' => $this->getTable(), + 'field' => 'insert_task_comment', + 'name' => __('Insert Task Category', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; - $tab[13]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[13]['field'] = 'insert_task_comment'; - $tab[13]['name'] = __('Insert Task Category', 'processmaker'); - $tab[13]['massiveaction'] = true; - $tab[13]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '14', + 'table' => 'glpi_itilcategories', + 'field' => 'completename', + 'name' => __('Category'), + 'datatype' => 'dropdown', + 'massiveaction' => false + ]; - $tab[14]['table'] = 'glpi_itilcategories'; - $tab[14]['field'] = 'completename'; - $tab[14]['name'] = __('Category'); - $tab[14]['datatype'] = 'dropdown'; - $tab[14]['massiveaction'] = false; + $tab[] = [ + 'id' => '15', + 'table' => $this->getTable(), + 'field' => 'type', + 'name' => __('Ticket type (self-service)', 'processmaker'), + 'searchtype' => 'equals', + 'datatype' => 'specific', + 'massiveaction' => false + ]; - $tab[15]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[15]['field'] = 'type'; - $tab[15]['name'] = __('Ticket type (self-service)', 'processmaker'); - $tab[15]['searchtype'] = 'equals'; - $tab[15]['datatype'] = 'specific'; - $tab[15]['massiveaction'] = false; + $tab[] = [ + 'id' => '16', + 'table' => $this->getTable(), + 'field' => 'is_incident', + 'name' => __('Visible in Incident for Central interface', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; - $tab[16]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[16]['field'] = 'is_incident'; - $tab[16]['name'] = __('Visible in Incident for Central interface', 'processmaker'); - $tab[16]['massiveaction'] = true; - $tab[16]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '17', + 'table' => $this->getTable(), + 'field' => 'is_request', + 'name' => __('Visible in Request for Central interface', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; - $tab[17]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[17]['field'] = 'is_request'; - $tab[17]['name'] = __('Visible in Request for Central interface', 'processmaker'); - $tab[17]['massiveaction'] = true; - $tab[17]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '18', + 'table' => $this->getTable(), + 'field' => 'is_change', + 'name' => __('Visible in Change', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; - $tab[18]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[18]['field'] = 'is_change'; - $tab[18]['name'] = __('Visible in Change', 'processmaker'); - $tab[18]['massiveaction'] = true; - $tab[18]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '19', + 'table' => $this->getTable(), + 'field' => 'is_problem', + 'name' => __('Visible in Problem', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; - $tab[19]['table'] = 'glpi_plugin_processmaker_processes'; - $tab[19]['field'] = 'is_problem'; - $tab[19]['name'] = __('Visible in Problem', 'processmaker'); - $tab[19]['massiveaction'] = true; - $tab[19]['datatype'] = 'bool'; + $tab[] = [ + 'id' => '20', + 'table' => 'glpi_plugin_processmaker_processes', + 'field' => 'maintenance', + 'name' => __('Maintenance'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; + + $tab[] = [ + 'id' => '21', + 'table' => 'glpi_plugin_processmaker_processes', + 'field' => 'max_cases_per_item', + 'name' => __('Max cases per item (0=unlimited)', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'number' + ]; return $tab; } @@ -594,7 +669,7 @@ class PluginProcessmakerProcess extends CommonDBTM { echo ""; echo ""; - echo "".__("Active").""; + echo "".__('Active').""; Dropdown::showYesNo("is_active", $this->fields["is_active"]); echo ""; @@ -608,6 +683,11 @@ class PluginProcessmakerProcess extends CommonDBTM { Dropdown::showYesNo("insert_task_comment", $this->fields["insert_task_comment"]); echo ""; + echo ""; + echo "" . __('Max cases per item (0=unlimited)', 'processmaker') . ""; + echo ""; + echo "\n"; + echo ""; echo "".__('Visible in Incident for Central interface', 'processmaker').""; Dropdown::showYesNo("is_incident", $this->fields["is_incident"]); @@ -680,6 +760,15 @@ class PluginProcessmakerProcess extends CommonDBTM { Dropdown::showFromArray( 'project_type', self::getAllTypeArray(), [ 'value' => $this->fields["project_type"] ] ); echo ""; + echo ""; + echo "".__('Maintenance mode').""; + Dropdown::showYesNo("maintenance", $this->fields["maintenance"]); + if ($this->fields["maintenance"]) { + echo ""; + echo "Synchronize Task List"; + } + echo ""; + $this->showFormButtons($options); } @@ -801,5 +890,24 @@ class PluginProcessmakerProcess extends CommonDBTM { } + + /** + * Summary of underMaintenance + * Shows a nice(?) under maintenance message + */ + static function showUnderMaintenance($ptitle, $size = '') { + global $CFG_GLPI; + if ($size != '') { + $size .= '-'; + } + echo "
"; + + echo Html::image($CFG_GLPI['root_doc']."/plugins/processmaker/pics/{$size}under_maintenance.png"); + echo "

"; + echo sprintf(__('Process \'%s\' is under maintenance, please retry later, thank you.', 'processmaker'), $ptitle); + echo "

"; + echo "
"; + } + } diff --git a/inc/process_profile.class.php b/inc/process_profile.class.php index 25a4433..20990aa 100644 --- a/inc/process_profile.class.php +++ b/inc/process_profile.class.php @@ -170,9 +170,14 @@ class PluginProcessmakerProcess_Profile extends CommonDBTM */ function prepareInputForAdd($input) { $tmp = new self; - if ($tmp->getFromDBByQuery(" WHERE `plugin_processmaker_processes_id` = ".$input['plugin_processmaker_processes_id']." - AND `entities_id` = ".$input['entities_id']." - AND `profiles_id` = ".$input['profiles_id'])) { + $restrict=[ + 'WHERE' => [ + 'plugin_processmaker_processes_id' => $input['plugin_processmaker_processes_id'], + 'entities_id' => $input['entities_id'], + 'profiles_id' => $input['profiles_id'] + ], + ]; + if ($tmp->getFromDBByRequest($restrict)) { //// then update existing //$tmp->update(['id' => $tmp->getID(), // 'is_recursive' => $input['is_recursive']]); diff --git a/inc/processmaker.class.php b/inc/processmaker.class.php index 8777b24..732bb22 100644 --- a/inc/processmaker.class.php +++ b/inc/processmaker.class.php @@ -180,16 +180,22 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $this->taskWriter = $this->config->fields['users_id']; $this->pm_group_guid = $this->config->fields['pm_group_guid']; + //$cipher_list = openssl_get_cipher_methods(true); + $wsdl = $this->serverURL."/services/wsdl2"; $context['ssl'] = ['verify_peer_name' => $this->config->fields['ssl_verify'], // Verification of peer name 'verify_peer' => $this->config->fields['ssl_verify'], // Verification of SSL certificate used + //'ciphers' => 'RSA', ]; - $options = [ 'stream_context' => stream_context_create($context), - 'soap_version' => SOAP_1_2, - 'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP, - //'proxy_host' => 'localhost', - //'proxy_port' => 8888 + $options = ['stream_context' => stream_context_create($context), + 'soap_version' => SOAP_1_2, + 'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP, + 'keep_alive' => false, + //'trace' => true, + //'exceptions' => false, + //'proxy_host' => 'localhost', + //'proxy_port' => 8889 ]; $this->pmSoapClient = new SoapClient($wsdl, $options); @@ -246,7 +252,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $gusr = new User; if (is_numeric($admin_or_user)) { $gusr->getFromDB($admin_or_user); - } elseif ($admin_or_user !== false) { + } else if ($admin_or_user !== false) { $gusr->getFromDBbyName($admin_or_user); } else { $gusr->getFromDB(Session::getLoginUserID()); @@ -1440,18 +1446,35 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $caseInfo = $myProcessMaker->getCaseInfo( $parm->input['processmaker_caseguid'], $parm->input['processmaker_delindex']); $parm->input['name'] = $PM_DB->escape($caseInfo->caseName ); - $caseInitialDueDate = $myProcessMaker->getVariables( $parm->input['processmaker_caseguid'], [ 'GLPI_ITEM_TITLE', 'GLPI_ITEM_INITIAL_DUE_DATE' ]); - if (array_key_exists( 'GLPI_ITEM_INITIAL_DUE_DATE', $caseInitialDueDate )) { - $parm->input['time_to_resolve'] = $caseInitialDueDate[ 'GLPI_ITEM_INITIAL_DUE_DATE' ]." 23:59:59"; + $casegetvariables = ['GLPI_ITEM_TITLE', 'GLPI_ITEM_INITIAL_DUE_DATE', 'GLPI_ITEM_DUE_DATE']; + $caseresetvariables = []; + + $caseDueDate = $myProcessMaker->getVariables( $parm->input['processmaker_caseguid'], $casegetvariables); + if (array_key_exists('GLPI_ITEM_INITIAL_DUE_DATE', $caseDueDate)) { + $parm->input['time_to_resolve'] = $caseDueDate['GLPI_ITEM_INITIAL_DUE_DATE']; + $caseresetvariables['GLPI_ITEM_INITIAL_DUE_DATE'] = ''; } + if (array_key_exists( 'GLPI_ITEM_DUE_DATE', $caseDueDate )) { + $parm->input['time_to_resolve'] = $caseDueDate['GLPI_ITEM_DUE_DATE']; + $caseresetvariables['GLPI_ITEM_DUE_DATE'] = ''; + } + $re = '/^(?\'date\'[0-9]{4}-[0-1][0-9]-[0-3][0-9])( (?\'time\'[0-2][0-9]:[0-5][0-9]:[0-5][0-9]))*$/'; + if (preg_match($re, $parm->input['time_to_resolve'], $matches) && !array_key_exists('time', $matches)) { + $parm->input['time_to_resolve'] .= " 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_caseguid'], [ "GLPI_ITEM_TITLE" => ''] ); + if (array_key_exists( 'GLPI_ITEM_TITLE', $caseDueDate )) { + $txtItemTitle = $caseDueDate['GLPI_ITEM_TITLE']; + // reset item title case variable + $caseresetvariables['GLPI_ITEM_TITLE'] = ''; } $parm->input['name'] = $PM_DB->escape($txtItemTitle ); + if (count($caseresetvariables)) { + $resultSave = $myProcessMaker->sendVariables( $parm->input['processmaker_caseguid'], $caseresetvariables ); + } + $procDef = new PluginProcessmakerProcess; $procDef->getFromGUID( $caseInfo->processId ); if (isset($parm->input['type'])) { @@ -1465,6 +1488,12 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { } } + + /** + * Summary of plugin_item_add_processmaker + * @param mixed $parm + * @return void + */ public static function plugin_item_add_processmaker($parm) { global $DB, $GLOBALS, $PM_SOAP; @@ -1493,74 +1522,12 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { // before routing, send items_id and itemtype // as this information was not available at case creation - $myCase->sendVariables( [ "GLPI_TICKET_ID" => $items_id ] ); + $myCase->sendVariables( [ "GLPI_TICKET_ID" => $items_id, + "GLPI_ITEM_ID" => $items_id, + "GLPI_ITEM_TYPE" => $itemtype, + ] ); - // route case - $pmRouteCaseResponse = $PM_SOAP->routeCase($case_guid, $parm->input['processmaker_delindex'] ); - - // gets new case status - $caseInfo = $myCase->getCaseInfo();//$parm->input['processmaker_delindex']); - // now manage tasks associated with item - // create new tasks - if (property_exists( $pmRouteCaseResponse, 'routing' )) { - // now tries to get some variables to setup content for new task and to append text to solved task - $txtForTasks = $myCase->getVariables( [ "GLPI_ITEM_APPEND_TO_TASK", - "GLPI_ITEM_SET_STATUS", - "GLPI_TICKET_FOLLOWUP_CONTENT", - "GLPI_TICKET_FOLLOWUP_IS_PRIVATE", - "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID" ] ); - $itemSetStatus = ''; - if (array_key_exists( 'GLPI_ITEM_SET_STATUS', $txtForTasks )) { - $itemSetStatus = $txtForTasks[ 'GLPI_ITEM_SET_STATUS' ]; - } - if (array_key_exists( 'GLPI_ITEM_APPEND_TO_TASK', $txtForTasks )) { - $txtToAppendToTask = $txtForTasks[ 'GLPI_ITEM_APPEND_TO_TASK' ]; - } else { - $txtToAppendToTask = ''; - } - $createFollowup = false; // by default - if (array_key_exists( 'GLPI_TICKET_FOLLOWUP_CONTENT', $txtForTasks ) && $txtForTasks[ 'GLPI_TICKET_FOLLOWUP_CONTENT' ] != '') { - $createFollowup = true; - } - - // reset those variables - $resultSave = $myCase->sendVariables( [ "GLPI_ITEM_APPEND_TO_TASK" => '', - "GLPI_ITEM_SET_STATUS" => '', - "GLPI_TICKET_FOLLOWUP_CONTENT" => '', - "GLPI_TICKET_FOLLOWUP_IS_PRIVATE" => '', - "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID" => '' ] ); - - // routing has been done, then solve 1st task - $PM_SOAP->solveTask($myCase->getID(), $parm->input['processmaker_delindex'], [ 'txtToAppend' => $txtToAppendToTask, 'notif' => false] ); - - // create a followup if requested - if ($createFollowup && $itemtype == 'Ticket') { - $PM_SOAP->addTicketFollowup( $items_id, $txtForTasks ); - } - - // and create GLPI tasks for the newly created PM tasks. - foreach ($pmRouteCaseResponse->routing as $route) { - $PM_SOAP->addTask( $myCase->getID(), - $myCase->fields['itemtype'], - $myCase->fields['items_id'], - $caseInfo, - $route->delIndex, - PluginProcessmakerUser::getGLPIUserId( $route->userId ), - 0, - $route->taskId, - $route->delThread ); - } - - if ($itemSetStatus != '') { - $PM_SOAP->setItemStatus($myCase->fields['itemtype'], $myCase->fields['items_id'], $itemSetStatus ); - } - } - - // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED - $myCase->update( ['id' => $myCase->getID(), - 'case_status' => $caseInfo->caseStatus, - 'name' => $caseInfo->caseName - ]); + $PM_SOAP->derivateCase($myCase, ['DEL_INDEX' => $parm->input['processmaker_delindex']]); } else {//if( array_key_exists('_head', $parm->input) ) { // this ticket have been created via email receiver. $ptnProcessToStart = "/##TicketProcess:\s*#([0-9a-f]{32})\s*##/i"; @@ -1657,13 +1624,17 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { */ public function addTask($cases_id, $itemtype, $items_id, $caseInfo, $delIndex, $techId, $groupId, $pmTaskId, $delThread, $options = []) { global $DB, $PM_DB, $_SESSION; + $dbu = new DbUtils; + $default_options = [ 'txtTaskContent' => '', 'start_date' => '', 'end_date' => '', + 'reminder' => '', 'notif' => true ]; + foreach ($default_options as $key => $opt) { if (!isset($options[$key])) { $options[$key] = $opt; @@ -1710,7 +1681,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $input['users_id'] = $this->taskWriter; // manage groups - if ($techId == 0) { // then we must look-up DB to get the pseudo-group that will be assigned to the task + if ($techId == 0) { // then we must look-up DB to get the group that will be assigned to the task $groupname=''; if ($groupId == 0) { $query = "SELECT CONTENT.CON_VALUE FROM TASK_USER @@ -1766,13 +1737,21 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $input['groups_id_tech'] = $groups_id_tech; } + if ($options['reminder'] != '' && $techId) { + $input['_planningrecall'] = ['before_time' => $options['reminder'], + 'itemtype' => get_class($glpi_task), + 'items_id' => '', + 'users_id' => $techId, + 'field' => 'begin']; + } + $donotif = self::saveNotification(false); // do not send notification yet as the PluginProcessmakerTask is not yet added to DB $glpi_task->add( Toolbox::addslashes_deep( $input ) ); self::restoreNotification($donotif); // to prevent error message for overlapping planning - if (isset($_SESSION["MESSAGE_AFTER_REDIRECT"][ERROR])) { - unset($_SESSION["MESSAGE_AFTER_REDIRECT"][ERROR]); + if (isset($_SESSION["MESSAGE_AFTER_REDIRECT"][WARNING])) { + unset($_SESSION["MESSAGE_AFTER_REDIRECT"][WARNING]); } if ($glpi_task->getId() > 0) { @@ -1892,6 +1871,21 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { } + /** + * Summary of setItemDuedate + * @param mixed $itemtype + * @param mixed $itemId + * @param mixed $duedate + */ + public function setItemDuedate($itemtype, $itemId, $duedate) { + $dbu = new DbUtils; + $item = $dbu->getItemForItemtype( $itemtype ); + if ($item->getFromDB( $itemId )) { + $item->update( ['id' => $itemId, 'time_to_resolve' => $duedate] ); + } + } + + /** * Summary of setItemSolution * @param mixed $itemType @@ -2384,25 +2378,12 @@ 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 array $request: is the $_REQUEST server array * //@param string $cookie: is the $_SERVER['HTTP_COOKIE'] string * @return mixed: returns false if request failed, otherwise, returns true */ public function saveForm($request) { - //, $cookie ) { - //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); - // } - //} $loggable = false; $request = stripcslashes_deep( $request ); @@ -2411,7 +2392,6 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { //to be able to trace network traffic with a local proxy // curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1 ); // curl_setopt($ch, CURLOPT_PROXY, "localhost:8888"); - // curl_setopt($ch, CURLOPT_PROXY, "fry07689.fr.ray.group:8889"); //curl_setopt($ch, CURLINFO_HEADER_OUT, 1); //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); @@ -2423,7 +2403,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->config->fields['ssl_verify']); //curl_setopt($ch, CURLOPT_HEADERFUNCTION, "HandleHeaderLine"); - // to stock cookies in memory + // to store cookies in memory // ( replace HandleHeaderLine function ) curl_setopt($ch, CURLOPT_COOKIEFILE, ""); @@ -2441,24 +2421,24 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { // check if any files are in the $_FILES global array // and add them to the curl POST $fileForm = $_FILES['form']['name']; - if( !empty($fileForm[array_keys($fileForm)[0]][1][array_keys($fileForm[array_keys($fileForm)[0]][1])[0]]) ){ + if (!empty($fileForm[array_keys($fileForm)[0]][1][array_keys($fileForm[array_keys($fileForm)[0]][1])[0]])) { foreach ($_FILES['form']['name'] as $key => $file) { if (is_array($file)) { // it's a grid which contains documents foreach ($file as $row => $col) { - foreach($col as $control => $filename) { - $cfile = new CURLFile($_FILES['form']['tmp_name'][$key][$row][$control], $_FILES['form']['type'][$key][$row][$control],$_FILES['form']['name'][$key][$row][$control]); + foreach ($col as $control => $filename) { + $cfile = new CURLFile($_FILES['form']['tmp_name'][$key][$row][$control], $_FILES['form']['type'][$key][$row][$control], $_FILES['form']['name'][$key][$row][$control]); $data["form[$key][$row][$control]"] = $cfile; } } } else { - $cfile = new CURLFile($_FILES['form']['tmp_name'][$key], $_FILES['form']['type'][$key],$_FILES['form']['name'][$key]); + $cfile = new CURLFile($_FILES['form']['tmp_name'][$key], $_FILES['form']['type'][$key], $_FILES['form']['name'][$key]); $data["form[$key]"] = $cfile; } } } // to get all cookies in one variable - $cookies = curl_getinfo($ch, CURLINFO_COOKIELIST); + //$cookies = curl_getinfo($ch, CURLINFO_COOKIELIST); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Expect:"]); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // inject POST values // add agent and referer params @@ -2477,10 +2457,6 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { } return ($response ? true : false); - - //$n = preg_match("/HTTP\/1.1 302 /", $response, $matches); - - //return ($n < 1 ? false : true) ; } /** @@ -2548,14 +2524,21 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { public static function plugin_item_get_data_processmaker($item) { global $_SESSION, $CFG_GLPI; if (isset( $item->data ) && isset( $item->data['tasks'] )) { + $pmtask = new PluginProcessmakerTask($pmtask_itemtype); foreach ($item->data['tasks'] as &$task) { $pmtask_itemtype = $item->obj->getType().'Task'; $pmtask_items_id = $task['##task.id##']; // for each task, we must check if it is in our task table // and if yes, then process the content - $pmtask = new PluginProcessmakerTask($pmtask_itemtype); - if ($pmtask->getFromDBByQuery("WHERE itemtype = '$pmtask_itemtype' AND items_id = $pmtask_items_id")) { + $restrict=[ + 'WHERE' => [ + 'itemtype' => $pmtask_itemtype, + 'items_id' => $pmtask_items_id + ], + ]; + //if ($pmtask->getFromDBByQuery("WHERE itemtype = '$pmtask_itemtype' AND items_id = $pmtask_items_id")) { + if ($pmtask->getFromDBByRequest($restrict)) { if (!in_array("tasks", $item->html_tags)) { $item->html_tags[] = "tasks"; // to force GLPI to keep the below HTML tags, otherwise it will apply a Html::entities_deep() to the task.description @@ -2564,7 +2547,13 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $task['##task.description##'] = str_replace( '##processmaker.taskcomment##', $task['##task.categorycomment##'], $task['##task.description##'] ); $task['##task.description##'] = Html::nl2br_deep($task['##task.description##']); - $pmtask->getFromDBByQuery("WHERE itemtype = '$pmtask_itemtype' AND items_id = $pmtask_items_id"); + //$restrict=[ + // 'WHERE' => [ + // 'itemtype' => $pmtask_itemtype, + // 'items_id' => $pmtask_items_id + // ], + // ]; + //$pmtask->getFromDBByRequest($restrict); //$caseurl = urldecode($CFG_GLPI["url_base"]."/index.php?redirect=PluginProcessmakerCase_".$pmtask->fields['plugin_processmaker_cases_id']); $caseurl = $CFG_GLPI["url_base"]."/index.php?redirect=".urlencode("/plugins/processmaker/front/case.form.php?id=".$pmtask->fields['plugin_processmaker_cases_id']); @@ -2598,7 +2587,8 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { 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##processmakercase.url##", $loc_comment, $item->datas['content']); + $item->datas['content'] = $loc_completename."\n\n".str_replace( "##processmaker.taskcomment##", $loc_comment, $item->datas['content']); + $item->datas['content'] = str_replace( "##processmakercase.url##", '', $item->datas['content']); } // restore default translations if (isset( $trans )) { @@ -2642,15 +2632,15 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { /** * Summary of startNewCase * @param mixed $processes_id integer: GLPI process id - * @param mixed $itemType string: item type 'Ticket', 'Change' or 'Problem' + * @param mixed $itemtype string: item type 'Ticket', 'Change' or 'Problem' * @param mixed $items_id integer: id to thte item * @param mixed $users_id integer: GLPI user id * @return mixed */ - public function startNewCase($processes_id, $itemType, $items_id, $users_id = null) { + public function startNewCase($processes_id, $itemtype, $items_id, $users_id = null) { global $DB, $CFG_GLPI; - $requesters = PluginProcessmakerProcessmaker::getItemUsers( $itemType, $items_id, CommonITILActor::REQUESTER); // 1 for requesters + $requesters = PluginProcessmakerProcessmaker::getItemUsers( $itemtype, $items_id, CommonITILActor::REQUESTER); // 1 for requesters if (!key_exists( 0, $requesters )) { $requesters[0]['glpi_id'] = 0; $requesters[0]['pm_id'] = 0; @@ -2664,67 +2654,72 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { //} // get item info to retreive title, description and duedate - $locItem = new $itemType; // $_POST['itemtype'] ; //Ticket(); - $locItem->getFromDB( $items_id ); // $_POST['id'] ) ; + $item = new $itemtype; + $item->getFromDB( $items_id ); - if ($locItem->countUsers(CommonITILActor::ASSIGN) == 0 - || !$locItem->isUser(CommonITILActor::ASSIGN, $users_id) ) { - $locItem->update( [ 'id' => $items_id, '_itil_assign' => [ '_type' => 'user', 'users_id' => $users_id ] ] ); + if ($item->countUsers(CommonITILActor::ASSIGN) == 0 + || !$item->isUser(CommonITILActor::ASSIGN, $users_id) ) { + $item->update( [ 'id' => $items_id, '_itil_assign' => [ '_type' => 'user', 'users_id' => $users_id ] ] ); } - if (!isset($locItem->fields['time_to_resolve']) || $locItem->fields['time_to_resolve'] == null) { - $locItem->fields['time_to_resolve'] = ""; + if (!isset($item->fields['time_to_resolve']) || $item->fields['time_to_resolve'] == null) { + $item->fields['time_to_resolve'] = ""; } $resultCase = $this->newCase( $processes_id, - ['GLPI_ITEM_CAN_BE_SOLVED' => 0, - 'GLPI_TICKET_ID' => $items_id, - 'GLPI_ITEM_ID' => $items_id, - 'GLPI_ITEM_TYPE' => $itemType, - 'GLPI_TICKET_REQUESTER_GLPI_ID' => $requesters[0]['glpi_id'], - 'GLPI_ITEM_REQUESTER_GLPI_ID' => $requesters[0]['glpi_id'], - 'GLPI_TICKET_REQUESTER_PM_ID' => $requesters[0]['pm_id'], - 'GLPI_ITEM_REQUESTER_PM_ID' => $requesters[0]['pm_id'], - 'GLPI_TICKET_TITLE' => $locItem->fields['name'], - 'GLPI_ITEM_TITLE' => $locItem->fields['name'], - 'GLPI_TICKET_DESCRIPTION' => $locItem->fields['content'], - 'GLPI_ITEM_DESCRIPTION' => $locItem->fields['content'], - 'GLPI_TICKET_DUE_DATE' => $locItem->fields['time_to_resolve'], - 'GLPI_ITEM_OPENING_DATE' => $locItem->fields['date'], - 'GLPI_ITEM_DUE_DATE' => $locItem->fields['time_to_resolve'], - 'GLPI_ITEM_ITIL_CATEGORY_ID' => $locItem->fields['itilcategories_id'], - 'GLPI_TICKET_URGENCY' => $locItem->fields['urgency'], - 'GLPI_ITEM_URGENCY' => $locItem->fields['urgency'], - 'GLPI_ITEM_IMPACT' => $locItem->fields['impact'], - 'GLPI_ITEM_PRIORITY' => $locItem->fields['priority'], - 'GLPI_TICKET_GLOBAL_VALIDATION' => $locItem->fields['global_validation'] , - 'GLPI_Ticket_TYPE' => $locItem->fields['type'] , - 'GLPI_TICKET_STATUS' => $locItem->fields['status'] , - 'GLPI_TICKET_TECHNICIAN_GLPI_ID' => $users_id, - 'GLPI_ITEM_TECHNICIAN_GLPI_ID' => $users_id, - 'GLPI_TICKET_TECHNICIAN_PM_ID' => PluginProcessmakerUser::getPMUserId( $users_id ), - 'GLPI_ITEM_TECHNICIAN_PM_ID' => PluginProcessmakerUser::getPMUserId( $users_id ), - 'GLPI_URL' => $CFG_GLPI['url_base'] - ] ); + ['GLPI_ITEM_CAN_BE_SOLVED' => 0, + 'GLPI_TICKET_ID' => $items_id, + 'GLPI_ITEM_ID' => $items_id, + 'GLPI_ITEM_TYPE' => $itemtype, + 'GLPI_ITEM_STATUS' => $item->fields['status'], + 'GLPI_TICKET_REQUESTER_GLPI_ID' => $requesters[0]['glpi_id'], + 'GLPI_ITEM_REQUESTER_GLPI_ID' => $requesters[0]['glpi_id'], + 'GLPI_TICKET_REQUESTER_PM_ID' => $requesters[0]['pm_id'], + 'GLPI_ITEM_REQUESTER_PM_ID' => $requesters[0]['pm_id'], + 'GLPI_TICKET_TITLE' => $item->fields['name'], + 'GLPI_ITEM_TITLE' => $item->fields['name'], + 'GLPI_TICKET_DESCRIPTION' => $item->fields['content'], + 'GLPI_ITEM_DESCRIPTION' => $item->fields['content'], + 'GLPI_ITEM_OPENING_DATE' => $item->fields['date'], + 'GLPI_TICKET_DUE_DATE' => $item->fields['time_to_resolve'], + 'GLPI_ITEM_DUE_DATE' => $item->fields['time_to_resolve'], + 'GLPI_ITEM_ITIL_CATEGORY_ID' => $item->fields['itilcategories_id'], + 'GLPI_TICKET_URGENCY' => $item->fields['urgency'], + 'GLPI_ITEM_URGENCY' => $item->fields['urgency'], + 'GLPI_ITEM_IMPACT' => $item->fields['impact'], + 'GLPI_ITEM_PRIORITY' => $item->fields['priority'], + // Specific to Tickets and Changes + // GLPI_ITEM_GLOBAL_VALIDATION will be '' when Problem, else it will be the global_validation field + 'GLPI_TICKET_GLOBAL_VALIDATION' => $itemtype == 'Problem' ? '' : $item->fields['global_validation'], + 'GLPI_ITEM_GLOBAL_VALIDATION' => $itemtype == 'Problem' ? '' : $item->fields['global_validation'], + 'GLPI_TICKET_TECHNICIAN_GLPI_ID' => $users_id, + 'GLPI_ITEM_TECHNICIAN_GLPI_ID' => $users_id, + 'GLPI_TICKET_TECHNICIAN_PM_ID' => PluginProcessmakerUser::getPMUserId( $users_id ), + 'GLPI_ITEM_TECHNICIAN_PM_ID' => PluginProcessmakerUser::getPMUserId( $users_id ), + 'GLPI_URL' => $CFG_GLPI['url_base'], + // Specific to Tickets + // GLPI_TICKET_TYPE will contains 1 (= incident) or 2 (= request), or '' if itemtype is not Ticket + 'GLPI_TICKET_TYPE' => $itemtype == 'Ticket' ? $item->fields['type'] : '' + ]); if ($resultCase->status_code === 0) { $caseInfo = $this->getCaseInfo( $resultCase->caseId ); // save info to DB $locCase = new PluginProcessmakerCase; - $locCase->add( ['id' => $resultCase->caseNumber, - 'itemtype' => $itemType, - 'items_id' => $items_id, - 'case_guid' => $resultCase->caseId, - 'case_status' => $caseInfo->caseStatus, - 'name' => $caseInfo->caseName, - 'entities_id' => $locItem->fields['entities_id'], + $locCase->add( ['id' => $resultCase->caseNumber, + 'itemtype' => $itemtype, + 'items_id' => $items_id, + 'case_guid' => $resultCase->caseId, + 'case_status' => $caseInfo->caseStatus, + 'name' => $caseInfo->caseName, + 'entities_id' => $item->fields['entities_id'], 'plugin_processmaker_processes_id' => $processes_id, - 'plugin_processmaker_cases_id' => 0 + 'plugin_processmaker_cases_id' => 0 ], [], true ); - $this->add1stTask($locCase->getID(), $itemType, $items_id, $caseInfo, ['userId' => $users_id] ); + $this->add1stTask($locCase->getID(), $itemtype, $items_id, $caseInfo, ['userId' => $users_id] ); } return $resultCase; @@ -2750,64 +2745,13 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $item->getFromDB($items_id); // save the dynaform variables into the current case - $resultSave = $this->saveForm( $request ); + if (isset($request['UID']) && isset($request['APP_UID']) && isset($request['__DynaformName__'])) { + $resultSave = $this->saveForm( $request ); + } // now derivate the case !!! $pmRouteCaseResponse = $this->routeCase($myCase->fields['case_guid'], $request['DEL_INDEX']); - //if (property_exists($pmRouteCaseResponse, 'routing')) { - // // must check if case has started a sub-process - // // we may have several new cases for this case - // // must check if all child cases are existing in GLPI - // $locTaskCat = new PluginProcessmakerTaskCategory; - // foreach($pmRouteCaseResponse->routing as $route) { - // if ($locTaskCat->getFromGUID($route->taskId) && $locTaskCat->fields['is_subprocess']) { - // // look for APP_UID - // foreach($PM_DB->request("SELECT APP_UID FROM SUB_APPLICATION WHERE APP_PARENT='{$myCase->fields['case_guid']}' AND DEL_INDEX_PARENT={$route->delIndex} AND DEL_THREAD_PARENT={$route->delThread} AND SA_STATUS='ACTIVE'") as $subCase) { - // // normally only one case for this delIndex and delThread - // // now need to get the PRO_UID - // $sub_caseInfo = self::getCaseInfo($subCase['APP_UID']); - - // $locProc = new PluginProcessmakerProcess; - // $locProc->getFromGUID($sub_caseInfo->processId); - // $locCase = new PluginProcessmakerCase; - // $locCase->add(['id' => $sub_caseInfo->caseNumber, - // 'case_guid'=> $sub_caseInfo->caseId, - // 'itemtype' => $itemtype, - // 'items_id' => $items_id, - // 'name' => $sub_caseInfo->caseName, - // 'entities_id' => $item->fields['entities_id'], - // 'case_status' => $sub_caseInfo->caseStatus, - // 'plugin_processmaker_processes_id' => $locProc->getID(), - // 'plugin_processmaker_cases_id' => $myCase->getID()]); - - // // then create associated task - // if (property_exists( $sub_caseInfo, 'currentUsers' )) { - // foreach ($sub_caseInfo->currentUsers as $sub_route) { - // $this->addTask($locCase->getID(), $itemtype, - // $items_id, - // $sub_caseInfo, - // $sub_route->delIndex, - // PluginProcessmakerUser::getGLPIUserId($sub_route->userId), - // 0, - // $sub_route->taskId, - // $sub_route->delThread, - // [] - // //array( 'txtTaskContent' => $txtTaskContent, - // // 'start_date' => $taskStartDate, - // // 'end_date' => $taskEndDate) - // ); - - // } - // } - - // } - - // } - // } - - //} - $casevariables = ["GLPI_ITEM_TASK_CONTENT", "GLPI_ITEM_APPEND_TO_TASK", "GLPI_NEXT_GROUP_TO_BE_ASSIGNED", @@ -2817,13 +2761,17 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID", "GLPI_ITEM_TASK_ENDDATE", "GLPI_ITEM_TASK_STARTDATE", + "GLPI_ITEM_TASK_REMINDER", "GLPI_ITEM_SOLVED_TASK_ENDDATE", "GLPI_ITEM_SOLVED_TASK_STARTDATE", "GLPI_ITEM_SOLVED_TASK_SETINFO", "GLPI_ITEM_SET_STATUS", + "GLPI_ITEM_STATUS", "GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID", "GLPI_ITEM_SET_SOLUTION_TYPE_ID", - "GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION" + "GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION", + "GLPI_ITEM_INITIAL_DUE_DATE", + "GLPI_ITEM_DUE_DATE" ]; // now tries to get some variables to setup content for new task and to append text to solved task @@ -2833,6 +2781,9 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { if (array_key_exists( 'GLPI_ITEM_SET_STATUS', $casevariablevalues )) { $itemSetStatus = $casevariablevalues[ 'GLPI_ITEM_SET_STATUS' ]; } + if (array_key_exists( 'GLPI_ITEM_STATUS', $casevariablevalues )) { + $itemSetStatus = $casevariablevalues[ 'GLPI_ITEM_STATUS' ]; + } $txtItemTitle = ''; if (array_key_exists( 'GLPI_ITEM_TITLE', $casevariablevalues )) { @@ -2867,6 +2818,11 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { } } + $taskReminder = ''; + if (array_key_exists( 'GLPI_ITEM_TASK_REMINDER', $casevariablevalues )) { + $taskReminder = $casevariablevalues[ 'GLPI_ITEM_TASK_REMINDER' ]; + } + $solvedTaskStartDate = ''; $solvedTaskEndDate = ''; if (array_key_exists( 'GLPI_ITEM_SOLVED_TASK_ENDDATE', $casevariablevalues )) { @@ -2892,6 +2848,18 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $createFollowup = true; } + $item_duedate = ''; + if (array_key_exists('GLPI_ITEM_INITIAL_DUE_DATE', $casevariablevalues)) { + $item_duedate = $casevariablevalues['GLPI_ITEM_INITIAL_DUE_DATE']; + } + if (array_key_exists( 'GLPI_ITEM_DUE_DATE', $casevariablevalues )) { + $item_duedate = $casevariablevalues['GLPI_ITEM_DUE_DATE']; + } + $re = '/^(?\'date\'[0-9]{4}-[0-1][0-9]-[0-3][0-9])( (?\'time\'[0-2][0-9]:[0-5][0-9]:[0-5][0-9]))*$/'; + if (preg_match($re, $item_duedate, $matches) && !array_key_exists('time', $matches)) { + $item_duedate .= " 23:59:59"; + } + // reset those variables $resetcasevariables = []; foreach ($casevariables as $val) { @@ -2923,8 +2891,9 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $this->setItemTitle($itemtype, $items_id, $txtItemTitle); } - if ($itemSetStatus != '') { - $this->setItemStatus($itemtype, $items_id, $itemSetStatus ); + if ($item_duedate != '') { + // we are going to change the due date (time to resolve) of current GLPI Item + $this->setItemDuedate($itemtype, $items_id, $item_duedate); } if (array_key_exists( 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID', $casevariablevalues ) @@ -2934,6 +2903,10 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $this->setItemSolution($itemtype, $items_id, $casevariablevalues); } + if ($itemSetStatus != '') { + $this->setItemStatus($itemtype, $items_id, $itemSetStatus ); + } + // get the new case info $caseInfo = $myCase->getCaseInfo($request['DEL_INDEX']); // not sure that it should passed this @@ -2981,8 +2954,9 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $sub_route->taskId, $sub_route->delThread, [ 'txtTaskContent' => $txtTaskContent, - 'start_date' => $taskStartDate, - 'end_date' => $taskEndDate] + 'start_date' => $taskStartDate, + 'end_date' => $taskEndDate, + 'reminder' => $taskReminder] ); // if end date was specified, then must change due date of the PM task @@ -3005,6 +2979,7 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { 'GLPI_TICKET_ID' => $items_id, 'GLPI_ITEM_ID' => $items_id, 'GLPI_ITEM_TYPE' => $itemtype, + 'GLPI_ITEM_STATUS' => $item->fields['status'], 'GLPI_TICKET_REQUESTER_GLPI_ID' => $requesters[0]['glpi_id'], 'GLPI_ITEM_REQUESTER_GLPI_ID' => $requesters[0]['glpi_id'], 'GLPI_TICKET_REQUESTER_PM_ID' => $requesters[0]['pm_id'], @@ -3013,22 +2988,26 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { 'GLPI_ITEM_TITLE' => $item->fields['name'], 'GLPI_TICKET_DESCRIPTION' => $item->fields['content'], 'GLPI_ITEM_DESCRIPTION' => $item->fields['content'], - 'GLPI_TICKET_DUE_DATE' => $item->fields['time_to_resolve'], 'GLPI_ITEM_OPENING_DATE' => $item->fields['date'], + 'GLPI_TICKET_DUE_DATE' => $item->fields['time_to_resolve'], 'GLPI_ITEM_DUE_DATE' => $item->fields['time_to_resolve'], 'GLPI_ITEM_ITIL_CATEGORY_ID' => $item->fields['itilcategories_id'], 'GLPI_TICKET_URGENCY' => $item->fields['urgency'], 'GLPI_ITEM_URGENCY' => $item->fields['urgency'], 'GLPI_ITEM_IMPACT' => $item->fields['impact'], 'GLPI_ITEM_PRIORITY' => $item->fields['priority'], - 'GLPI_TICKET_GLOBAL_VALIDATION' => $item->fields['global_validation'] , - 'GLPI_Ticket_TYPE' => $locItem->fields['type'] , - 'GLPI_TICKET_STATUS' => $locItem->fields['status'] , + // Specific to Tickets and Changes + // GLPI_ITEM_GLOBAL_VALIDATION will be '' when Problem, else it will be the global_validation field + 'GLPI_TICKET_GLOBAL_VALIDATION' => $itemtype == 'Problem' ? '' : $item->fields['global_validation'], + 'GLPI_ITEM_GLOBAL_VALIDATION' => $itemtype == 'Problem' ? '' : $item->fields['global_validation'], 'GLPI_TICKET_TECHNICIAN_GLPI_ID' => $users_id, 'GLPI_ITEM_TECHNICIAN_GLPI_ID' => $users_id, 'GLPI_TICKET_TECHNICIAN_PM_ID' => PluginProcessmakerUser::getPMUserId( $users_id ), 'GLPI_ITEM_TECHNICIAN_PM_ID' => PluginProcessmakerUser::getPMUserId( $users_id ), - 'GLPI_URL' => $CFG_GLPI['url_base'] + 'GLPI_URL' => $CFG_GLPI['url_base'], + // Specific to Tickets + // GLPI_TICKET_TYPE will contains 1 (= incident) or 2 (= request) + 'GLPI_TICKET_TYPE' => $itemtype == 'Ticket' ? $item->fields['type'] : '' ]; $subCase->sendVariables($glpi_variables); @@ -3047,8 +3026,9 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $route->taskId, $route->delThread, [ 'txtTaskContent' => $txtTaskContent, - 'start_date' => $taskStartDate, - 'end_date' => $taskEndDate] + 'start_date' => $taskStartDate, + 'end_date' => $taskEndDate, + 'reminder' => $taskReminder] ); // if end date was specified, then must change due date of the PM task if ($taskEndDate != '') { @@ -3072,9 +3052,17 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { // must check if $open_task is not is_subprocess and is not already existing in the item $locTaskCat = new PluginProcessmakerTaskCategory; $locTask = new PluginProcessmakerTask(); + + $locTaskRestrict=[ + 'WHERE' => [ + 'plugin_processmaker_cases_id' => $parentCase->getID(), + 'plugin_processmaker_taskcategories_id' => $locTaskCat->getID(), + 'del_index' => $open_task->delIndex + ], + ]; if ($locTaskCat->getFromGUID($open_task->taskId) && !$locTaskCat->fields['is_subprocess'] - && !$locTask->getFromDBByQuery("WHERE `plugin_processmaker_cases_id`={$parentCase->getID()} AND `plugin_processmaker_taskcategories_id`={$locTaskCat->getID()} AND `del_index`={$open_task->delIndex}")) { + && !$locTask->getFromDBByRequest($locTaskRestrict)) { $this->addTask($parentCase->getID(), $itemtype, $items_id, $parentCaseInfo, @@ -3084,8 +3072,9 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { $open_task->taskId, $open_task->delThread, [ 'txtTaskContent' => $txtTaskContent, - 'start_date' => $taskStartDate, - 'end_date' => $taskEndDate] + 'start_date' => $taskStartDate, + 'end_date' => $taskEndDate, + 'reminder' => $taskReminder] ); // if end date was specified, then must change due date of the PM task @@ -3215,8 +3204,32 @@ class PluginProcessmakerProcessmaker extends CommonDBTM { echo "
"; echo Html::image($CFG_GLPI['root_doc'].'/plugins/processmaker/pics/under_maintenance.png'); echo "

"; - __('ProcessMaker plugin is under maintenance, please retry later, thank you.', 'processmaker'); + echo __('ProcessMaker plugin is under maintenance, please retry later, thank you.', 'processmaker'); echo "

"; echo "
"; } + + + /** + * Summary of echoDomain + */ + function echoDomain() { + if (isset($this->config->fields['domain']) && $this->config->fields['domain'] != '') { + $script = " + (function() { + var id = 'commonDomainGlpiPmScript_Wjd4uWisWHLt9I'; + //debugger; + if ($('#' + id).length == 0) { + //debugger; + var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0]; + g.type = 'text/javascript'; + g.id = id; + g.text = 'try { document.domain = \'".$this->config->fields['domain']."\'; } catch(ev) { /*console.log(ev);*/ }'; + s.parentNode.insertBefore(g, s); + } + })();"; + + echo Html::scriptBlock($script); + } + } } diff --git a/inc/selfservicedraft.class.php b/inc/selfservicedraft.class.php index 705d4bc..df45378 100644 --- a/inc/selfservicedraft.class.php +++ b/inc/selfservicedraft.class.php @@ -10,4 +10,4 @@ */ class PluginProcessmakerSelfservicedraft extends CommonDBTM { -} \ No newline at end of file +} diff --git a/inc/task.class.php b/inc/task.class.php index c6e02d6..fe843f8 100644 --- a/inc/task.class.php +++ b/inc/task.class.php @@ -41,7 +41,13 @@ class PluginProcessmakerTask extends CommonITILTask function getFromDB($items_id) { global $DB; - if ($this->getFromDBByQuery(" WHERE itemtype='".$this->itemtype."' AND items_id=$items_id;" )) { + //if ($this->getFromDBByQuery(" WHERE itemtype='".$this->itemtype."' AND items_id=$items_id;" )) { + if ($this->getFromDBByRequest([ + 'WHERE' => [ + 'itemtype' => $this->itemtype, + 'items_id' => $items_id + ], + ])) { $task = new $this->itemtype; if ($task->getFromDB( $items_id )) { // then we should add our own fields @@ -306,7 +312,11 @@ class PluginProcessmakerTask extends CommonITILTask $rand = rand(); // get infos for the current task - $task = $dbu->getAllDataFromTable('glpi_plugin_processmaker_tasks', "id = $tabnum"); + $restrict = [ + "id" => $tabnum + ]; + //$task = $dbu->getAllDataFromTable('glpi_plugin_processmaker_tasks', "id = $tabnum"); + $task = $dbu->getAllDataFromTable('glpi_plugin_processmaker_tasks', $restrict); // shows the re-assign form $caseInfo = $case->getCaseInfo(); @@ -347,6 +357,7 @@ class PluginProcessmakerTask extends CommonITILTask } } + $PM_SOAP->echoDomain(); echo ""; $csrf = Session::getNewCSRFToken(); diff --git a/inc/taskcategory.class.php b/inc/taskcategory.class.php index d0952e1..d915b52 100644 --- a/inc/taskcategory.class.php +++ b/inc/taskcategory.class.php @@ -86,11 +86,11 @@ class PluginProcessmakerTaskCategory extends CommonDBTM return true; } - /** - * Print a good title for task categories tab - * add button for re-synchro of taskcategory list (only if rigths are w) - * @return nothing (display) - **/ + /** + * Print a good title for task categories tab + * add button for re-synchro of taskcategory list (only if rigths are w) + * @return nothing (display) + **/ static function title(CommonGLPI $item) { global $CFG_GLPI; @@ -99,26 +99,22 @@ class PluginProcessmakerTaskCategory extends CommonDBTM if (Session::haveRight('plugin_processmaker_config', UPDATE)) { $buttons["process.form.php?refreshtask=1&id=".$item->getID()] = $title; - Html::displayTitle($CFG_GLPI["root_doc"] . "/plugins/processmaker/pics/gears.png", $title, "", - $buttons); + $pic = $CFG_GLPI["root_doc"] . "/plugins/processmaker/pics/gears.png"; + if ($item->fields['maintenance']) { + $pic = $CFG_GLPI["root_doc"] . "/plugins/processmaker/pics/verysmall-under_maintenance.png"; + } + Html::displayTitle($pic, $title, "", $buttons); } } - //function getLinkItemFromExternalID($extId) { - // if( $this->getFromDBbyExternalID( $extId ) ) { - // $taskcat = new TaskCategory ; - // return $taskcat->getFromDB( $this->fields['items_id'] ) ; - // } - //} - - /** - * Retrieve a TaskCat from the database using its external id (unique index): pm_task_guid - * - * @param $task_guid string externalid - * - * @return true if succeed else false - **/ + /** + * Retrieve a TaskCat from the database using its external id (unique index): pm_task_guid + * + * @param $task_guid string externalid + * + * @return true if succeed else false + **/ function getFromGUID($task_guid) { global $DB; diff --git a/inc/user.class.php b/inc/user.class.php index 9d3a007..72bee97 100644 --- a/inc/user.class.php +++ b/inc/user.class.php @@ -178,9 +178,14 @@ class PluginProcessmakerUser extends CommonDBTM { */ public static function getGLPIUserId($pmUserId) { $obj = new self; - if ($obj->getFromDBByQuery("WHERE `pm_users_id` = '$pmUserId'")) { + if ($obj->getFromDBByRequest([ + 'WHERE' => [ + 'pm_users_id' => $pmUserId + ], + ])) { return $obj->fields['id']; } + return 0; } diff --git a/install/install.php b/install/install.php index ec0b43d..b1e9143 100644 --- a/install/install.php +++ b/install/install.php @@ -4,27 +4,7 @@ function processmaker_install() { global $DB; // installation from scratch - include_once(GLPI_ROOT."/plugins/processmaker/setup.php"); - $info = plugin_version_processmaker(); - switch ($info['version']) { - case '3.3.0' : - $version = '3.3.0'; - break; - case '3.3.1' : - case '3.3.2' : - case '3.3.3' : - case '3.3.4' : - case '3.3.5' : - case '3.3.6' : - case '3.3.7' : - $version = '3.3.1'; - break; - case '3.3.8' : - default : - $version = '3.3.8'; - break; - } - $DB->runFile(GLPI_ROOT . "/plugins/processmaker/install/mysql/$version-empty.sql"); + $DB->runFile(GLPI_ROOT . "/plugins/processmaker/install/mysql/processmaker-empty.sql"); // add configuration singleton $query = "INSERT INTO `glpi_plugin_processmaker_configs` (`id`) VALUES (1);"; diff --git a/install/mysql/3.2.8-empty.sql b/install/mysql/3.2.8-empty.sql deleted file mode 100644 index 6a217a1..0000000 --- a/install/mysql/3.2.8-empty.sql +++ /dev/null @@ -1,167 +0,0 @@ -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET NAMES utf8 */; -/*!50503 SET NAMES utf8mb4 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; - --- Dumping structure for table glpi.glpi_plugin_processmaker_caselinkactions -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_caselinkactions` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_caselinks_id` int(11) DEFAULT NULL, - `name` varchar(255) NOT NULL, - `value` text, - PRIMARY KEY (`id`), - UNIQUE KEY `caselinks_id_name` (`plugin_processmaker_caselinks_id`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_caselinks -CREATE TABLE IF NOT EXISTS `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) DEFAULT NULL, - `targettask_guid` varchar(32) DEFAULT NULL, - `targetprocess_guid` varchar(32) DEFAULT NULL, - `targetdynaform_guid` varchar(32) DEFAULT NULL, - `sourcecondition` text, - `is_targettoclaim` tinyint(1) NOT NULL DEFAULT '0', - `externalapplication` text, - `date_mod` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `is_active` (`is_active`), - KEY `is_externaldata` (`is_externaldata`), - KEY `is_self` (`is_self`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_cases -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_cases` ( - `id` varchar(32) NOT NULL, - `items_id` int(11) NOT NULL, - `itemtype` varchar(10) NOT NULL DEFAULT 'Ticket', - `case_num` int(11) NOT NULL, - `case_status` varchar(20) NOT NULL DEFAULT 'DRAFT', - `processes_id` int(11) DEFAULT NULL, - UNIQUE KEY `items` (`itemtype`,`items_id`), - KEY `case_status` (`case_status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_configs -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_configs` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL DEFAULT 'ProcessMaker', - `pm_server_URL` varchar(250) NOT NULL DEFAULT 'http://localhost/', - `pm_workspace` varchar(50) NOT NULL DEFAULT 'workflow', - `pm_admin_user` varchar(255) DEFAULT NULL, - `pm_admin_passwd` varchar(255) DEFAULT NULL, - `pm_theme` varchar(50) NOT NULL DEFAULT 'glpi_classic', - `date_mod` timestamp NULL DEFAULT NULL, - `taskcategories_id` int(11) DEFAULT NULL, - `users_id` int(11) DEFAULT NULL, - `pm_group_guid` varchar(32) DEFAULT NULL, - `comment` text, - `pm_dbserver_name` varchar(255) DEFAULT 'localhost', - `pm_dbname` varchar(50) DEFAULT 'wf_workflow', - `pm_dbserver_user` varchar(255) DEFAULT NULL, - `pm_dbserver_passwd` varchar(255) DEFAULT NULL, - `domain` varchar(50) DEFAULT '', - `maintenance` tinyint(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_crontaskactions -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_crontaskactions` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_caselinks_id` int(11) DEFAULT NULL, - `itemtype` varchar(100) NOT NULL, - `items_id` int(11) NOT NULL DEFAULT '0', - `users_id` int(11) NOT NULL DEFAULT '0', - `is_targettoclaim` tinyint(1) NOT NULL DEFAULT '0', - `postdata` mediumtext, - `logs_out` mediumtext, - `state` int(11) NOT NULL, - `date_mod` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_processes -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_processes` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `process_guid` varchar(32) NOT NULL, - `name` varchar(255) NOT NULL, - `is_active` tinyint(1) NOT NULL DEFAULT '0', - `hide_case_num_title` tinyint(1) NOT NULL DEFAULT '0', - `insert_task_comment` tinyint(1) NOT NULL DEFAULT '0', - `comment` text, - `taskcategories_id` int(11) DEFAULT NULL, - `itilcategories_id` int(11) NOT NULL DEFAULT '0', - `type` int(11) NOT NULL DEFAULT '1' COMMENT 'Only used for Tickets', - `date_mod` timestamp NULL DEFAULT NULL, - `project_type` varchar(50) NOT NULL DEFAULT 'classic', - PRIMARY KEY (`id`), - UNIQUE KEY `process_guid` (`process_guid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_processes_profiles -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_processes_profiles` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `processes_id` int(11) NOT NULL DEFAULT '0', - `profiles_id` int(11) NOT NULL DEFAULT '0', - `entities_id` int(11) NOT NULL DEFAULT '0', - `is_recursive` tinyint(1) NOT NULL DEFAULT '1', - PRIMARY KEY (`id`), - KEY `entities_id` (`entities_id`), - KEY `profiles_id` (`profiles_id`), - KEY `processes_id` (`processes_id`), - KEY `is_recursive` (`is_recursive`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_taskcategories -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_taskcategories` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `processes_id` int(11) NOT NULL, - `pm_task_guid` varchar(32) NOT NULL, - `taskcategories_id` int(11) NOT NULL, - `start` bit(1) NOT NULL DEFAULT b'0', - `is_active` tinyint(1) NOT NULL DEFAULT '1', - PRIMARY KEY (`id`), - UNIQUE KEY `pm_task_guid` (`pm_task_guid`), - UNIQUE KEY `items` (`taskcategories_id`), - KEY `processes_id` (`processes_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_tasks -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_tasks` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `items_id` int(11) NOT NULL, - `itemtype` varchar(32) NOT NULL, - `case_id` varchar(32) NOT NULL, - `del_index` int(11) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `case_id` (`case_id`,`del_index`), - UNIQUE KEY `items` (`itemtype`,`items_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_users -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_users` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `pm_users_id` varchar(32) NOT NULL, - `password` varchar(32) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `pm_users_id` (`pm_users_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; -/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/install/mysql/3.2.9-empty.sql b/install/mysql/3.2.9-empty.sql deleted file mode 100644 index 3ee30cd..0000000 --- a/install/mysql/3.2.9-empty.sql +++ /dev/null @@ -1,168 +0,0 @@ -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET NAMES utf8 */; -/*!50503 SET NAMES utf8mb4 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; - --- Dumping structure for table glpi.glpi_plugin_processmaker_caselinkactions -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_caselinkactions` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_caselinks_id` int(11) DEFAULT NULL, - `name` varchar(255) NOT NULL, - `value` text, - PRIMARY KEY (`id`), - UNIQUE KEY `caselinks_id_name` (`plugin_processmaker_caselinks_id`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_caselinks -CREATE TABLE IF NOT EXISTS `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) DEFAULT NULL, - `targettask_guid` varchar(32) DEFAULT NULL, - `targetprocess_guid` varchar(32) DEFAULT NULL, - `targetdynaform_guid` varchar(32) DEFAULT NULL, - `sourcecondition` text, - `is_targettoclaim` tinyint(1) NOT NULL DEFAULT '0', - `externalapplication` text, - `date_mod` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `is_active` (`is_active`), - KEY `is_externaldata` (`is_externaldata`), - KEY `is_self` (`is_self`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_cases -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_cases` ( - `id` varchar(32) NOT NULL, - `items_id` int(11) NOT NULL, - `itemtype` varchar(10) NOT NULL DEFAULT 'Ticket', - `case_num` int(11) NOT NULL, - `case_status` varchar(20) NOT NULL DEFAULT 'DRAFT', - `processes_id` int(11) DEFAULT NULL, - UNIQUE KEY `items` (`itemtype`,`items_id`), - KEY `case_status` (`case_status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_configs -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_configs` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL DEFAULT 'ProcessMaker', - `pm_server_URL` varchar(250) NOT NULL DEFAULT 'http://localhost/', - `pm_workspace` varchar(50) NOT NULL DEFAULT 'workflow', - `pm_admin_user` varchar(255) DEFAULT NULL, - `pm_admin_passwd` varchar(255) DEFAULT NULL, - `pm_theme` varchar(50) NOT NULL DEFAULT 'glpi_classic', - `date_mod` timestamp NULL DEFAULT NULL, - `taskcategories_id` int(11) DEFAULT NULL, - `users_id` int(11) DEFAULT NULL, - `pm_group_guid` varchar(32) DEFAULT NULL, - `comment` text, - `pm_dbserver_name` varchar(255) DEFAULT 'localhost', - `pm_dbname` varchar(50) DEFAULT 'wf_workflow', - `pm_dbserver_user` varchar(255) DEFAULT NULL, - `pm_dbserver_passwd` varchar(255) DEFAULT NULL, - `domain` varchar(50) DEFAULT '', - `maintenance` tinyint(1) NOT NULL DEFAULT '0', - `db_version` varchar(10) NOT NULL DEFAULT '3.2.9', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_crontaskactions -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_crontaskactions` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_caselinks_id` int(11) DEFAULT NULL, - `itemtype` varchar(100) NOT NULL, - `items_id` int(11) NOT NULL DEFAULT '0', - `users_id` int(11) NOT NULL DEFAULT '0', - `is_targettoclaim` tinyint(1) NOT NULL DEFAULT '0', - `postdata` mediumtext, - `logs_out` mediumtext, - `state` int(11) NOT NULL, - `date_mod` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_processes -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_processes` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `process_guid` varchar(32) NOT NULL, - `name` varchar(255) NOT NULL, - `is_active` tinyint(1) NOT NULL DEFAULT '0', - `hide_case_num_title` tinyint(1) NOT NULL DEFAULT '0', - `insert_task_comment` tinyint(1) NOT NULL DEFAULT '0', - `comment` text, - `taskcategories_id` int(11) DEFAULT NULL, - `itilcategories_id` int(11) NOT NULL DEFAULT '0', - `type` int(11) NOT NULL DEFAULT '1' COMMENT 'Only used for Tickets', - `date_mod` timestamp NULL DEFAULT NULL, - `project_type` varchar(50) NOT NULL DEFAULT 'classic', - PRIMARY KEY (`id`), - UNIQUE KEY `process_guid` (`process_guid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_processes_profiles -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_processes_profiles` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `processes_id` int(11) NOT NULL DEFAULT '0', - `profiles_id` int(11) NOT NULL DEFAULT '0', - `entities_id` int(11) NOT NULL DEFAULT '0', - `is_recursive` tinyint(1) NOT NULL DEFAULT '1', - PRIMARY KEY (`id`), - KEY `entities_id` (`entities_id`), - KEY `profiles_id` (`profiles_id`), - KEY `processes_id` (`processes_id`), - KEY `is_recursive` (`is_recursive`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_taskcategories -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_taskcategories` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `processes_id` int(11) NOT NULL, - `pm_task_guid` varchar(32) NOT NULL, - `taskcategories_id` int(11) NOT NULL, - `start` bit(1) NOT NULL DEFAULT b'0', - `is_active` tinyint(1) NOT NULL DEFAULT '1', - PRIMARY KEY (`id`), - UNIQUE KEY `pm_task_guid` (`pm_task_guid`), - UNIQUE KEY `items` (`taskcategories_id`), - KEY `processes_id` (`processes_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_tasks -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_tasks` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `items_id` int(11) NOT NULL, - `itemtype` varchar(32) NOT NULL, - `case_id` varchar(32) NOT NULL, - `del_index` int(11) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `case_id` (`case_id`,`del_index`), - UNIQUE KEY `items` (`itemtype`,`items_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_users -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_users` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `pm_users_id` varchar(32) NOT NULL, - `password` varchar(32) DEFAULT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `pm_users_id` (`pm_users_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; -/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/install/mysql/3.3.0-empty.sql b/install/mysql/3.3.0-empty.sql deleted file mode 100644 index 3049ca9..0000000 --- a/install/mysql/3.3.0-empty.sql +++ /dev/null @@ -1,179 +0,0 @@ -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET NAMES utf8 */; -/*!50503 SET NAMES utf8mb4 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; - --- Dumping structure for table glpi.glpi_plugin_processmaker_caselinkactions -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_caselinkactions` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_caselinks_id` int(11) DEFAULT NULL, - `name` varchar(255) NOT NULL, - `value` text, - PRIMARY KEY (`id`), - UNIQUE KEY `caselinks_id_name` (`plugin_processmaker_caselinks_id`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_caselinks -CREATE TABLE IF NOT EXISTS `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) DEFAULT NULL, - `targettask_guid` varchar(32) DEFAULT NULL, - `targetprocess_guid` varchar(32) DEFAULT NULL, - `targetdynaform_guid` varchar(32) DEFAULT NULL, - `sourcecondition` text, - `is_targettoclaim` tinyint(1) NOT NULL DEFAULT '0', - `externalapplication` text, - `date_mod` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `is_active` (`is_active`), - KEY `is_externaldata` (`is_externaldata`), - KEY `is_self` (`is_self`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_cases -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_cases` ( - `id` INT(11) NOT NULL, - `itemtype` VARCHAR(10) NOT NULL DEFAULT 'Ticket', - `items_id` INT(11) NOT NULL, - `entities_id` INT(11) NOT NULL DEFAULT '0', - `name` MEDIUMTEXT NOT NULL DEFAULT '', - `case_guid` VARCHAR(32) NOT NULL, - `case_status` VARCHAR(20) NOT NULL DEFAULT 'DRAFT', - `plugin_processmaker_processes_id` INT(11) NULL DEFAULT NULL, - `plugin_processmaker_cases_id` INT(11) NULL DEFAULT NULL, - INDEX `items` (`itemtype`, `items_id`), - INDEX `case_status` (`case_status`), - PRIMARY KEY (`id`), - UNIQUE INDEX `case_guid` (`case_guid`), - INDEX `plugin_processmaker_processes_id` (`plugin_processmaker_processes_id`), - INDEX `plugin_processmaker_cases_id` (`plugin_processmaker_cases_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_configs -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_configs` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL DEFAULT 'ProcessMaker', - `pm_server_URL` varchar(250) NOT NULL DEFAULT 'http://localhost/', - `pm_workspace` varchar(50) NOT NULL DEFAULT 'workflow', - `pm_admin_user` varchar(255) DEFAULT NULL, - `pm_admin_passwd` varchar(255) DEFAULT NULL, - `pm_theme` varchar(50) NOT NULL DEFAULT 'glpi_classic', - `date_mod` timestamp NULL DEFAULT NULL, - `taskcategories_id` int(11) DEFAULT NULL, - `users_id` int(11) DEFAULT NULL, - `pm_group_guid` varchar(32) DEFAULT NULL, - `comment` text, - `pm_dbserver_name` varchar(255) DEFAULT 'localhost', - `pm_dbname` varchar(50) DEFAULT 'wf_workflow', - `pm_dbserver_user` varchar(255) DEFAULT NULL, - `pm_dbserver_passwd` varchar(255) DEFAULT NULL, - `domain` varchar(50) DEFAULT '', - `maintenance` tinyint(1) NOT NULL DEFAULT '0', - `db_version` varchar(10) NOT NULL DEFAULT '3.3.0', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_crontaskactions -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_crontaskactions` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_caselinks_id` int(11) DEFAULT NULL, - `plugin_processmaker_cases_id` int(11) DEFAULT '0', - `users_id` int(11) NOT NULL DEFAULT '0', - `is_targettoclaim` tinyint(1) NOT NULL DEFAULT '0', - `postdata` mediumtext, - `logs_out` mediumtext, - `state` int(11) NOT NULL, - `date_mod` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_processes -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_processes` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `process_guid` varchar(32) NOT NULL, - `name` varchar(255) NOT NULL, - `is_active` tinyint(1) NOT NULL DEFAULT '0', - `hide_case_num_title` tinyint(1) NOT NULL DEFAULT '0', - `insert_task_comment` tinyint(1) NOT NULL DEFAULT '0', - `comment` text, - `taskcategories_id` int(11) DEFAULT NULL, - `itilcategories_id` int(11) NOT NULL DEFAULT '0', - `type` int(11) NOT NULL DEFAULT '1' COMMENT 'Only used for Tickets', - `date_mod` timestamp NULL DEFAULT NULL, - `project_type` varchar(50) NOT NULL DEFAULT 'classic', - PRIMARY KEY (`id`), - UNIQUE KEY `process_guid` (`process_guid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_processes_profiles -CREATE TABLE `glpi_plugin_processmaker_processes_profiles` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_processes_id` int(11) NOT NULL, - `profiles_id` int(11) NOT NULL, - `entities_id` int(11) NOT NULL, - `is_recursive` tinyint(1) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE INDEX `plugin_processmaker_processes_id_profiles_id_entities_id` (`plugin_processmaker_processes_id`, `profiles_id`, `entities_id`), - KEY `entities_id` (`entities_id`), - KEY `profiles_id` (`profiles_id`), - KEY `plugin_processmaker_processes_id` (`plugin_processmaker_processes_id`), - KEY `is_recursive` (`is_recursive`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_taskcategories -CREATE TABLE `glpi_plugin_processmaker_taskcategories` ( - `id` INT(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_processes_id` INT(11) NOT NULL, - `pm_task_guid` VARCHAR(32) NOT NULL, - `taskcategories_id` INT(11) NOT NULL, - `is_start` TINYINT(1) NOT NULL DEFAULT '0', - `is_active` TINYINT(1) NOT NULL DEFAULT '1', - `is_subprocess` TINYINT(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`), - UNIQUE INDEX `pm_task_guid` (`pm_task_guid`), - UNIQUE INDEX `items` (`taskcategories_id`), - INDEX `plugin_processmaker_processes_id` (`plugin_processmaker_processes_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_tasks -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_tasks` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `items_id` int(11) NOT NULL, - `itemtype` varchar(32) NOT NULL, - `plugin_processmaker_cases_id` int(11) NOT NULL, - `plugin_processmaker_taskcategories_id` int(11) NOT NULL, - `del_index` int(11) NOT NULL, - `del_thread` INT(11) NOT NULL, - `del_thread_status` varchar(32) NOT NULL DEFAULT 'OPEN', - PRIMARY KEY (`id`), - UNIQUE KEY `tasks` (`plugin_processmaker_cases_id`,`del_index`), - UNIQUE KEY `items` (`itemtype`,`items_id`), - KEY `del_thread_status` (`del_thread_status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_users -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_users` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `pm_users_id` varchar(32) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `pm_users_id` (`pm_users_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; -/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/install/mysql/3.3.1-empty.sql b/install/mysql/3.3.1-empty.sql deleted file mode 100644 index cb7d897..0000000 --- a/install/mysql/3.3.1-empty.sql +++ /dev/null @@ -1,186 +0,0 @@ -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET NAMES utf8 */; -/*!50503 SET NAMES utf8mb4 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; - --- Dumping structure for table glpi.glpi_plugin_processmaker_caselinkactions -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_caselinkactions` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_caselinks_id` int(11) DEFAULT NULL, - `name` varchar(255) NOT NULL, - `value` text, - PRIMARY KEY (`id`), - UNIQUE KEY `caselinks_id_name` (`plugin_processmaker_caselinks_id`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_caselinks -CREATE TABLE IF NOT EXISTS `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) DEFAULT NULL, - `targettask_guid` varchar(32) DEFAULT NULL, - `targetprocess_guid` varchar(32) DEFAULT NULL, - `targetdynaform_guid` varchar(32) DEFAULT NULL, - `sourcecondition` text, - `is_targettoclaim` tinyint(1) NOT NULL DEFAULT '0', - `is_targettoreassign` TINYINT(1) NOT NULL DEFAULT '0', - `is_targettoimpersonate` TINYINT(1) NOT NULL DEFAULT '0', - `externalapplication` TEXT NULL, - `is_synchronous` TINYINT(1) NOT NULL DEFAULT '0', - `date_mod` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `is_active` (`is_active`), - KEY `is_externaldata` (`is_externaldata`), - KEY `is_self` (`is_self`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_cases -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_cases` ( - `id` INT(11) NOT NULL, - `itemtype` VARCHAR(10) NOT NULL DEFAULT 'Ticket', - `items_id` INT(11) NOT NULL, - `entities_id` INT(11) NOT NULL DEFAULT '0', - `name` MEDIUMTEXT NOT NULL DEFAULT '', - `case_guid` VARCHAR(32) NOT NULL, - `case_status` VARCHAR(20) NOT NULL DEFAULT 'DRAFT', - `plugin_processmaker_processes_id` INT(11) NULL DEFAULT NULL, - `plugin_processmaker_cases_id` INT(11) NULL DEFAULT NULL, - INDEX `items` (`itemtype`, `items_id`), - INDEX `case_status` (`case_status`), - PRIMARY KEY (`id`), - UNIQUE INDEX `case_guid` (`case_guid`), - INDEX `plugin_processmaker_processes_id` (`plugin_processmaker_processes_id`), - INDEX `plugin_processmaker_cases_id` (`plugin_processmaker_cases_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_configs -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_configs` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL DEFAULT 'ProcessMaker', - `pm_server_URL` varchar(250) NOT NULL DEFAULT 'http://localhost/', - `pm_workspace` varchar(50) NOT NULL DEFAULT 'workflow', - `pm_admin_user` varchar(255) DEFAULT NULL, - `pm_admin_passwd` varchar(255) DEFAULT NULL, - `pm_theme` varchar(50) NOT NULL DEFAULT 'glpi_classic', - `date_mod` timestamp NULL DEFAULT NULL, - `taskcategories_id` int(11) DEFAULT NULL, - `users_id` int(11) DEFAULT NULL, - `pm_group_guid` varchar(32) DEFAULT NULL, - `comment` text, - `pm_dbserver_name` varchar(255) DEFAULT 'localhost', - `pm_dbname` varchar(50) DEFAULT 'wf_workflow', - `pm_dbserver_user` varchar(255) DEFAULT NULL, - `pm_dbserver_passwd` varchar(255) DEFAULT NULL, - `domain` varchar(50) DEFAULT '', - `maintenance` tinyint(1) NOT NULL DEFAULT '0', - `db_version` varchar(10) NOT NULL DEFAULT '3.3.0', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_crontaskactions -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_crontaskactions` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_caselinks_id` int(11) DEFAULT NULL, - `plugin_processmaker_cases_id` int(11) DEFAULT '0', - `users_id` int(11) NOT NULL DEFAULT '0', - `is_targettoclaim` tinyint(1) NOT NULL DEFAULT '0', - `postdata` mediumtext, - `logs_out` mediumtext, - `state` int(11) NOT NULL, - `date_mod` timestamp NULL DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_processes -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_processes` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `process_guid` varchar(32) NOT NULL, - `name` varchar(255) NOT NULL, - `is_active` tinyint(1) NOT NULL DEFAULT '0', - `hide_case_num_title` tinyint(1) NOT NULL DEFAULT '0', - `insert_task_comment` tinyint(1) NOT NULL DEFAULT '0', - `comment` text, - `taskcategories_id` int(11) DEFAULT NULL, - `itilcategories_id` int(11) NOT NULL DEFAULT '0', - `type` int(11) NOT NULL DEFAULT '1' COMMENT 'Only used for self-service Tickets', - `date_mod` timestamp NULL DEFAULT NULL, - `project_type` varchar(50) NOT NULL DEFAULT 'classic', - `is_change` tinyint(1) NOT NULL DEFAULT '0', - `is_problem` tinyint(1) NOT NULL DEFAULT '0', - `is_incident` tinyint(1) NOT NULL DEFAULT '0', - `is_request` tinyint(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`), - UNIQUE KEY `process_guid` (`process_guid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_processes_profiles -CREATE TABLE `glpi_plugin_processmaker_processes_profiles` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_processes_id` int(11) NOT NULL, - `profiles_id` int(11) NOT NULL, - `entities_id` int(11) NOT NULL, - `is_recursive` tinyint(1) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE INDEX `plugin_processmaker_processes_id_profiles_id_entities_id` (`plugin_processmaker_processes_id`, `profiles_id`, `entities_id`), - KEY `entities_id` (`entities_id`), - KEY `profiles_id` (`profiles_id`), - KEY `plugin_processmaker_processes_id` (`plugin_processmaker_processes_id`), - KEY `is_recursive` (`is_recursive`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_taskcategories -CREATE TABLE `glpi_plugin_processmaker_taskcategories` ( - `id` INT(11) NOT NULL AUTO_INCREMENT, - `plugin_processmaker_processes_id` INT(11) NOT NULL, - `pm_task_guid` VARCHAR(32) NOT NULL, - `taskcategories_id` INT(11) NOT NULL, - `is_start` TINYINT(1) NOT NULL DEFAULT '0', - `is_active` TINYINT(1) NOT NULL DEFAULT '1', - `is_subprocess` TINYINT(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`), - UNIQUE INDEX `pm_task_guid` (`pm_task_guid`), - UNIQUE INDEX `items` (`taskcategories_id`), - INDEX `plugin_processmaker_processes_id` (`plugin_processmaker_processes_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_tasks -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_tasks` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `items_id` int(11) NOT NULL, - `itemtype` varchar(32) NOT NULL, - `plugin_processmaker_cases_id` int(11) NOT NULL, - `plugin_processmaker_taskcategories_id` int(11) NOT NULL, - `del_index` int(11) NOT NULL, - `del_thread` INT(11) NOT NULL, - `del_thread_status` varchar(32) NOT NULL DEFAULT 'OPEN', - PRIMARY KEY (`id`), - UNIQUE KEY `tasks` (`plugin_processmaker_cases_id`,`del_index`), - UNIQUE KEY `items` (`itemtype`,`items_id`), - KEY `del_thread_status` (`del_thread_status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Dumping structure for table glpi.glpi_plugin_processmaker_users -CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_users` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `pm_users_id` varchar(32) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `pm_users_id` (`pm_users_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; -/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/install/mysql/3.3.8-empty.sql b/install/mysql/processmaker-empty.sql similarity index 96% rename from install/mysql/3.3.8-empty.sql rename to install/mysql/processmaker-empty.sql index a5be338..3ad90bb 100644 --- a/install/mysql/3.3.8-empty.sql +++ b/install/mysql/processmaker-empty.sql @@ -64,7 +64,7 @@ CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_cases` ( CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_configs` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT 'ProcessMaker', - `pm_server_URL` varchar(250) NOT NULL DEFAULT 'http://localhost/', + `pm_server_URL` varchar(250) NOT NULL DEFAULT 'http://itsm-pm.acme.com/', `pm_workspace` varchar(50) NOT NULL DEFAULT 'workflow', `pm_admin_user` varchar(255) DEFAULT NULL, `pm_admin_passwd` varchar(255) DEFAULT NULL, @@ -81,7 +81,8 @@ CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_configs` ( `domain` varchar(50) DEFAULT '', `maintenance` tinyint(1) NOT NULL DEFAULT '0', `ssl_verify` tinyint(1) NOT NULL DEFAULT '0', - `db_version` varchar(10) NOT NULL DEFAULT '3.3.8', + `db_version` varchar(10) NOT NULL DEFAULT '3.4.9', + `max_cases_per_item` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -119,6 +120,8 @@ CREATE TABLE IF NOT EXISTS `glpi_plugin_processmaker_processes` ( `is_problem` tinyint(1) NOT NULL DEFAULT '0', `is_incident` tinyint(1) NOT NULL DEFAULT '0', `is_request` tinyint(1) NOT NULL DEFAULT '0', + `maintenance` TINYINT(1) NOT NULL DEFAULT '0', + `max_cases_per_item` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `process_guid` (`process_guid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/install/update.php b/install/update.php index 06f713a..febe0e5 100644 --- a/install/update.php +++ b/install/update.php @@ -11,6 +11,9 @@ function processmaker_update() { include_once(GLPI_ROOT."/plugins/processmaker/inc/config.class.php"); $config = PluginProcessmakerConfig::getInstance(); $current_version = $config->fields['db_version']; + if (empty($current_version)) { + $current_version = '2.4.1'; + } } switch ($current_version) { @@ -37,6 +40,10 @@ function processmaker_update() { // will upgrade 3.3.1 to 3.3.8 include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_3_1_to_3_3_8.php"); $new_version = update_3_3_1_to_3_3_8(); + case '3.3.8' : + // will upgrade 3.3.8 to 3.4.9 + include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_3_8_to_3_4_9.php"); + $new_version = update_3_3_8_to_3_4_9(); } if (isset($new_version)) { diff --git a/install/update_3_3_1_to_3_3_8.php b/install/update_3_3_1_to_3_3_8.php index ebac746..1a4e4f7 100644 --- a/install/update_3_3_1_to_3_3_8.php +++ b/install/update_3_3_1_to_3_3_8.php @@ -1,6 +1,6 @@ fieldExists("glpi_plugin_processmaker_configs", "max_cases_per_item" )) { + $query = "ALTER TABLE `glpi_plugin_processmaker_configs` + ADD COLUMN `max_cases_per_item` INT(11) NOT NULL DEFAULT '0' AFTER `db_version`;"; + + $DB->query($query) or die("error adding max_cases_per_item to glpi_plugin_processmaker_configs table" . $DB->error()); + } + + // Alter table glpi_plugin_processmaker_processes + if (!$DB->fieldExists("glpi_plugin_processmaker_processes", "maintenance" )) { + $query = "ALTER TABLE `glpi_plugin_processmaker_processes` + ADD COLUMN `maintenance` TINYINT(1) NOT NULL DEFAULT '0' AFTER `is_request`;"; + + $DB->query($query) or die("error adding maintenance to glpi_plugin_processmaker_processes table" . $DB->error()); + } + // Alter table glpi_plugin_processmaker_processes + if (!$DB->fieldExists("glpi_plugin_processmaker_processes", "max_cases_per_item" )) { + $query = "ALTER TABLE `glpi_plugin_processmaker_processes` + ADD COLUMN `max_cases_per_item` INT(11) NOT NULL DEFAULT '0' AFTER `maintenance`;"; + + $DB->query($query) or die("error adding max_cases_per_item to glpi_plugin_processmaker_processes table" . $DB->error()); + } + + return '3.4.9'; +} \ No newline at end of file diff --git a/install/update_to_3_2_8.php b/install/update_to_3_2_8.php index 47f48df..d9784b3 100644 --- a/install/update_to_3_2_8.php +++ b/install/update_to_3_2_8.php @@ -71,7 +71,7 @@ function update_to_3_2_8() { } } - if (!$DB->fieldExists('glpi_plugin_processmaker_users', 'password')) { + if (!$DB->fieldExists('glpi_plugin_processmaker_users', 'password') && !$DB->fieldExists('glpi_plugin_processmaker_users', 'id')) { $query = "ALTER TABLE `glpi_plugin_processmaker_users` ADD COLUMN `id` INT NOT NULL AUTO_INCREMENT FIRST, ADD COLUMN `password` VARCHAR(32) NULL DEFAULT NULL AFTER `pm_users_id`, diff --git a/js/cases.helpdesk.js b/js/cases.helpdesk.js index b846e59..fb1c062 100644 --- a/js/cases.helpdesk.js +++ b/js/cases.helpdesk.js @@ -21,7 +21,7 @@ function onClickContinue(obj) { // hide the iFrame caseIFrame.style.visibility = 'hidden'; - // trigger a click on the 'add' button of the ticket + // trigger a click on the 'add' button of the ticket submitButton.click(); } @@ -59,17 +59,17 @@ function onLoadFrame( evt, caseId, delIndex, caseNumber, processName ) { if (caseIFrame != undefined && contentDocument) { var buttonContinue = contentDocument.getElementById('form[btnGLPISendRequest]'); var linkList = contentDocument.getElementsByTagName('a'); - + if (!bButtonContinue && buttonContinue != undefined && linkList != undefined && linkList.length > 0) { bButtonContinue = true; //window.clearInterval(caseTimer); // to be sure that it will be done only one time // change action for the attached form and add some parameters //debugger; bGLPIHideElement(linkList, 'href', 'cases_Step?TYPE=ASSIGN_TASK&UID=-1&POSITION=10000&ACTION=ASSIGN'); - + oldHandler = buttonContinue.onclick; buttonContinue.onclick = onClickContinue; - + submitButton = $("input[name='add'][type=submit]")[0]; submitButton.insertAdjacentHTML('beforebegin', ""); submitButton.insertAdjacentHTML('beforebegin', ""); @@ -116,4 +116,4 @@ function redimTaskFrame(taskFrame) { taskFrame.height = newHeight; } catch (e) { } -} \ No newline at end of file +} diff --git a/js/central.js b/js/central.js index 593e425..c907753 100644 --- a/js/central.js +++ b/js/central.js @@ -2,18 +2,17 @@ $(document).ajaxComplete(function (event, jqXHR, ajaxOptions) { //debugger; var pattern = /##processmaker.*(##|...)/g; - + $('tr.tab_bg_2 td a').each(function (index) { - + var textToChange = $(this).text(); var matches = textToChange.match(pattern); if (matches) { textToChange = textToChange.replace(pattern, ''); - if (!textToChange.trim().length>0) - { + if (!textToChange.trim().length>0) { var title = $(this).parent().prev().text(); textToChange = title; - } + } $(this).text(textToChange); } }); diff --git a/js/domain.js.php b/js/domain.js.php deleted file mode 100644 index 3d10868..0000000 --- a/js/domain.js.php +++ /dev/null @@ -1,19 +0,0 @@ -isActivated('processmaker')) { - $config = PluginProcessmakerConfig::getInstance(); - if (isset($config->fields['domain']) && $config->fields['domain'] != '') { - echo " - //debugger; - var d = document, - g = d.createElement('script'), - s = d.getElementsByTagName('script')[0]; - g.type = 'text/javascript'; - g.text = 'try { document.domain = \'".$config->fields['domain']."\'; } catch(ev) { /*console.log(ev);*/ }'; - s.parentNode.insertBefore(g, s); - "; - } -} \ No newline at end of file diff --git a/js/helpdesk.public.js.php b/js/helpdesk.public.js.php index c93b8d4..6d2bd5d 100644 --- a/js/helpdesk.public.js.php +++ b/js/helpdesk.public.js.php @@ -14,7 +14,7 @@ if (!defined('GLPI_ROOT')) { $config = PluginProcessmakerConfig::getInstance(); if (!$config->fields['maintenance']) { - echo "$(function () { + echo "$(function () { // look if name='helpdeskform' is present. If yes replace the form.location var ahrefTI = '".$CFG_GLPI["root_doc"]."/plugins/processmaker/front/tracking.injector.php'; var formLink = $(\"form[name='helpdeskform']\")[0]; diff --git a/js/planning.js b/js/planning.js index a0c8be9..b82153a 100644 --- a/js/planning.js +++ b/js/planning.js @@ -6,4 +6,4 @@ } $('input[type="checkbox"][value="PluginProcessmakerTask"]').parents('li').first().hide(); }); -}); \ No newline at end of file +}); diff --git a/pics/small-under_maintenance.png b/pics/small-under_maintenance.png new file mode 100644 index 0000000000000000000000000000000000000000..0f4749a61541aa8dfafb363311299657e993def5 GIT binary patch literal 39576 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

-3^P!SlJb!VJ%j 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 M07*qoM6N<$f^)-*y#N3J literal 0 HcmV?d00001 diff --git a/pics/verysmall-under_maintenance.png b/pics/verysmall-under_maintenance.png new file mode 100644 index 0000000000000000000000000000000000000000..b65974958c815979985a540901564fd5bdf5772f GIT binary patch literal 13147 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 Bczgf= literal 0 HcmV?d00001 diff --git a/processmaker.xml b/processmaker.xml index 8f4d30c..898d1eb 100644 --- a/processmaker.xml +++ b/processmaker.xml @@ -6,15 +6,15 @@ https://raw.githubusercontent.com/tomolimo/processmaker/master/processmaker.png - Ce plugin fournit la possibilité d'intégrer un processus (workflow) aux objets ITIL (Tickets, Changements et Problèmes). + Ce plugin fournit la possibilité d'intégrer un processus (workflow) aux objets ITIL (Tickets, Changements et Problèmes). This plugin provides a process (workflow) management linked to ITIL objects (Tickets, Changes and Problems). - Tento zásuvný modul poskytuje správu procesů (pracovní postup) napojený na požadavky. - + Tento zásuvný modul poskytuje správu procesů (pracovní postup) napojený na požadavky. + This plugin is dedicated to provide process (workflows) management linked to ITIL objects (Tickets, Changes and Problems). This goal is achieved using a customized ProcessMaker server (URL: https://github.com/tomolimo/processmaker-server). ProcessMaker provides BPMN Process design and execution. This plugin is the glue between GLPI and ProcessMaker. - Ce plugin est dédié à la gestion de processus (workflows) liés aux objets ITIL (Tickets, Changements et Problèmes). Ce but est atteint par l'utilisation d'un serveur ProcessMaker customisé (URL: https://github.com/tomolimo/processmaker-server). ProcessMaker fournit un outil graphique de création de processus BPMN et permet l'exécution de ceux-ci. Ce plugin sert de glue entre GLPI et ProcessMaker. - Tento zásuvný modul je věnován poskytnutí správy procesu (pracovní postup), napojeného na požadavky. Tohoto cíle je dosaženo použitím ProcessMaker (URL: https://github.com/tomolimo/processmaker-server). ProcessMaker poskytne návrh procesu a vykonání pracovního postupu. Tento zásuvný modul je můstkem mezi GLPI a ProcessMaker. - + Ce plugin est dédié à la gestion de processus (workflows) liés aux objets ITIL (Tickets, Changements et Problèmes). Ce but est atteint par l'utilisation d'un serveur ProcessMaker customisé (URL: https://github.com/tomolimo/processmaker-server). ProcessMaker fournit un outil graphique de création de processus BPMN et permet l'exécution de ceux-ci. Ce plugin sert de glue entre GLPI et ProcessMaker. + Tento zásuvný modul je věnován poskytnutí správy procesu (pracovní postup), napojeného na požadavky. Tohoto cíle je dosaženo použitím ProcessMaker (URL: https://github.com/tomolimo/processmaker-server). ProcessMaker poskytne návrh procesu a vykonání pracovního postupu. Tento zásuvný modul je můstkem mezi GLPI a ProcessMaker. + https://github.com/tomolimo/processmaker https://github.com/tomolimo/processmaker/releases @@ -28,10 +28,14 @@ 3.3.8 9.1 - - 3.4.5 - 9.2 - + + 3.4.9 + 9.2 + + + 3.5.1 + 9.3 + en_gb @@ -44,22 +48,15 @@ Processus BPMN 2.0 Workflow - Helpdesk - Ticket + Helpdesk + Ticket Processes BPMN 2.0 Helpdesk - Workflows - Ticket + Workflows + Ticket - - Procesy - BPMN 2.0 - Službapodpory - Pracovnípostupy - Požadavek - - + \ No newline at end of file diff --git a/setup.php b/setup.php index f894ae2..16f2a77 100644 --- a/setup.php +++ b/setup.php @@ -2,7 +2,7 @@ // used for case cancellation define("CANCEL", 256); -define('PROCESSMAKER_VERSION', '3.4.5'); +define('PROCESSMAKER_VERSION', '3.5.1'); // Init the hooks of the plugins -Needed function plugin_init_processmaker() { @@ -11,7 +11,6 @@ function plugin_init_processmaker() { $PLUGIN_HOOKS['csrf_compliant']['processmaker'] = true; $objects = ['Ticket', 'Change', 'Problem']; - // $objects = ['Ticket']; Plugin::registerClass('PluginProcessmakerProcessmaker'); @@ -33,11 +32,6 @@ function plugin_init_processmaker() { $PLUGIN_HOOKS['pre_show_item']['processmaker'] = ['PluginProcessmakerProcessmaker', 'pre_show_item_processmaker']; - //$PLUGIN_HOOKS['pre_item_form']['processmaker'] - // = array('PluginProcessmakerProcessmaker', 'pre_item_form_processmakerticket'); - //$PLUGIN_HOOKS['post_item_form']['processmaker'] - // = array('PluginProcessmakerProcessmaker', 'post_item_form_processmakerticket'); - $PLUGIN_HOOKS['pre_show_tab']['processmaker'] = ['PluginProcessmakerProcessmaker', 'pre_show_tab_processmaker']; $PLUGIN_HOOKS['post_show_tab']['processmaker'] @@ -45,8 +39,13 @@ function plugin_init_processmaker() { // Display a menu entry ? if (Session::haveRightsOr('plugin_processmaker_config', [READ, UPDATE])) { - // tools and helpdesk - $PLUGIN_HOOKS['menu_toadd']['processmaker'] = ['tools' => 'PluginProcessmakerMenu', 'helpdesk' => 'PluginProcessmakerCase']; + // tools + $PLUGIN_HOOKS['menu_toadd']['processmaker']['tools'] = 'PluginProcessmakerMenu'; + } + + if (Session::haveRightsOr('plugin_processmaker_case', [READ, UPDATE])) { + // helpdesk + $PLUGIN_HOOKS['menu_toadd']['processmaker']['helpdesk'] = 'PluginProcessmakerCase'; } Plugin::registerClass('PluginProcessmakerProcess', [ 'massiveaction_nodelete_types' => true] ); @@ -83,43 +82,27 @@ function plugin_init_processmaker() { $hooks = []; foreach ($objects as $obj) { - $hooks["PluginPdf'.$obj.'Task"] = ['PluginProcessmakerProcessmaker', 'plugin_item_get_pdfdata_processmaker']; + $hooks["PluginPdf".$obj."Task"] = ['PluginProcessmakerProcessmaker', 'plugin_item_get_pdfdata_processmaker']; } $PLUGIN_HOOKS['item_get_pdfdatas']['processmaker'] = $hooks; - //$hooks = []; - //foreach($objects as $obj){ - // $hooks[$obj.'_User'] = 'plugin_pre_item_purge_processmaker'; - //} - //$PLUGIN_HOOKS['pre_item_purge']['processmaker'] = $hooks; - - //$hooks = []; - //foreach($objects as $obj){ - // $hooks[$obj.'_User'] = 'plugin_item_purge_processmaker'; - //} - //$PLUGIN_HOOKS['item_purge']['processmaker'] = $hooks; - $plugin = new Plugin(); if ($plugin->isActivated('processmaker') && Session::getLoginUserID() ) { - + $url = explode("/", $_SERVER['PHP_SELF']); $pageName = explode("?", array_pop($url)); switch ($pageName[0]) { case "tracking.injector.php": case "helpdesk.public.php": - $PLUGIN_HOOKS['add_javascript']['processmaker'][] = "js/helpdesk.public.js.php"; + $PLUGIN_HOOKS['add_javascript']['processmaker'] = ["js/helpdesk.public.js.php"]; break; case "planning.php": - $PLUGIN_HOOKS['add_javascript']['processmaker'][] = "js/planning.js"; + $PLUGIN_HOOKS['add_javascript']['processmaker'] = ["js/planning.js"]; break; case "central.php": - $PLUGIN_HOOKS['add_javascript']['processmaker'][] = "js/central.js"; - break; - case "case.form.php": - case "processmaker.helpdesk.form.php" : - $PLUGIN_HOOKS['add_javascript']['processmaker'] = ["js/domain.js.php"]; - break; + $PLUGIN_HOOKS['add_javascript']['processmaker'] = ["js/central.js"]; + break; } } @@ -145,17 +128,17 @@ function plugin_version_processmaker() { 'homepage' => 'https://github.com/tomolimo/processmaker', 'requirements' => [ 'glpi' => [ - 'min' => '9.2', - 'max' => '9.2.99' + 'min' => '9.3', + 'max' => '9.4' ], - ] + ] ]; } // Optional : check prerequisites before install : may print errors or add to message after redirect function plugin_processmaker_check_prerequisites() { - if (version_compare(GLPI_VERSION, '9.2', 'lt') || version_compare(GLPI_VERSION, '9.3', 'ge')) { - echo "This plugin requires GLPI >= 9.2 and < 9.3"; + if (version_compare(GLPI_VERSION, '9.3', 'lt') || version_compare(GLPI_VERSION, '9.4', 'ge')) { + echo "This plugin requires GLPI >= 9.3 and < 9.4"; return false; }