From 93424d51abf7257210358748a8e95096847be1c5 Mon Sep 17 00:00:00 2001 From: Tomolimo Date: Thu, 18 Mar 2021 10:01:49 +0100 Subject: [PATCH] GLPI 9.5 compliance Set version to 4.0.0 --- .gitattributes | 17 - .gitignore | 216 - README.md | 28 +- ajax/dropdownTicketCategories.php | 40 + ajax/dropdownUsers.php | 244 +- ajax/task_users.php | 285 +- front/case.php | 38 +- front/processmaker.helpdesk.form.php | 544 +- hook.php | 960 ++-- inc/case.class.php | 3272 ++++++------ inc/config.class.php | 775 ++- inc/db.class.php | 52 +- inc/glpikey.class.php | 48 + inc/menu.class.php | 117 +- inc/process.class.php | 1944 +++---- inc/process_profile.class.php | 423 +- inc/processmaker.class.php | 7125 +++++++++++++------------- inc/task.class.php | 1059 ++-- inc/taskcategory.class.php | 770 +-- inc/user.class.php | 685 ++- install/mysql/processmaker-empty.sql | 378 +- install/update.php | 124 +- install/update_3_4_10_to_4_0_0.php | 14 + locales/cs_CZ.mo | Bin 8750 -> 10094 bytes locales/cs_CZ.po | 363 +- locales/en_GB.mo | Bin 9080 -> 13391 bytes locales/en_GB.po | 635 ++- locales/fr_FR.mo | Bin 14622 -> 14759 bytes locales/fr_FR.po | 458 +- locales/source.po | 684 +-- pics/processmaker-mid.png | Bin 0 -> 2873 bytes pics/processmaker-tiny.png | Bin 0 -> 1417 bytes pics/processmaker-xxs.png | Bin 0 -> 783 bytes pics/processmaker.png | Bin 0 -> 4828 bytes processmaker.xml | 134 +- setup.php | 343 +- 36 files changed, 11047 insertions(+), 10728 deletions(-) delete mode 100644 .gitattributes delete mode 100644 .gitignore create mode 100644 ajax/dropdownTicketCategories.php create mode 100644 inc/glpikey.class.php create mode 100644 install/update_3_4_10_to_4_0_0.php create mode 100644 pics/processmaker-mid.png create mode 100644 pics/processmaker-tiny.png create mode 100644 pics/processmaker-xxs.png create mode 100644 pics/processmaker.png diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index bdb0cab..0000000 --- a/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f91ff2b..0000000 --- a/.gitignore +++ /dev/null @@ -1,216 +0,0 @@ -################# -## Eclipse -################# - -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - - -################# -## Visual Studio -################# - -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results - -[Dd]ebug/ -[Rr]elease/ -x64/ -build/ -[Bb]in/ -[Oo]bj/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.log -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -*.ncrunch* -.*crunch*.local.xml - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml -*.publishproj - -# NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line -#packages/ - -# Windows Azure Build Output -csx -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -*.pfx -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf - -############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap -.DS_Store - - -############# -## Python -############# - -*.py[cod] - -# Packages -*.egg -*.egg-info -dist/ -build/ -eggs/ -parts/ -var/ -sdist/ -develop-eggs/ -.installed.cfg - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox - -#Translations -*.mo - -#Mr Developer -.mr.developer.cfg diff --git a/README.md b/README.md index 643387d..1d91284 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ -# ProcessMaker plugin - -GLPI plugin that provides an interface with a customized ProcessMaker server (https://github.com/tomolimo/processmaker-server). - -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.x (https://github.com/tomolimo/processmaker-server/releases/tag/3.3.0-RE-1.5) - -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) - -version 3.6.x is compatible with GLPI 9.4 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 - -An IRC channel is available: #processmaker-glpi on https://webchat.freenode.net/ +# ProcessMaker plugin + +GLPI plugin that provides an interface with a customized ProcessMaker server (https://github.com/tomolimo/processmaker-server). + +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.x (https://github.com/tomolimo/processmaker-server/releases/tag/3.3.0-RE-1.5) + +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) + +version 3.6.x is compatible with GLPI 9.4 and needs ProcessMaker 3.3.0-RE-1.x (https://github.com/tomolimo/processmaker-server/releases/latest) + +version 4.0.0 is compatible with GLPI 9.5 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 + +An IRC channel is available: #processmaker-glpi on https://webchat.freenode.net/ diff --git a/ajax/dropdownTicketCategories.php b/ajax/dropdownTicketCategories.php new file mode 100644 index 0000000..47d824a --- /dev/null +++ b/ajax/dropdownTicketCategories.php @@ -0,0 +1,40 @@ +getFromDB($_POST['value']); + +if ($_POST["type"]) { + switch ($_POST['type']) { + case Ticket::INCIDENT_TYPE : + $opt['condition']['is_incident'] = '1'; + if ($currentcateg->getField('is_incident') == 1) { + $opt['value'] = $_POST['value']; + } + break; + + case Ticket::DEMAND_TYPE: + $opt['condition']['is_request'] = '1'; + if ($currentcateg->getField('is_request') == 1) { + $opt['value'] = $_POST['value']; + } + break; + } +} + +ITILCategory::dropdown($opt); diff --git a/ajax/dropdownUsers.php b/ajax/dropdownUsers.php index 896f169..b1bcf77 100644 --- a/ajax/dropdownUsers.php +++ b/ajax/dropdownUsers.php @@ -1,126 +1,118 @@ -request([ - 'SELECT' => 'glpi_users.*', - 'FROM' => 'glpi_users', - 'WHERE' => [ - 'glpi_users.id' => $one_item - ] - ]); - //$query = "SELECT DISTINCT `glpi_users`.* - // FROM `glpi_users` - // WHERE `glpi_users`.`id` = '$one_item';"; - //$result = $DB->query($query); -} -$users = []; - -// Count real items returned -$count = 0; -//if ($DB->numrows($result)) { -// while ($data = $DB->fetch_assoc($result)) { -//if ($res->numrows()) { - foreach ($res as $data) { - $users[$data["id"]] = $dbu->formatUserName($data["id"], $data["name"], $data["realname"], - $data["firstname"]); - $logins[$data["id"]] = $data["name"]; - } -//} - - -$datas = []; - -// Display first if empty search -if ($_REQUEST['page'] == 1 && empty($_REQUEST['searchText'])) { - if (($one_item < 0) || ($one_item == 0)) { - if ($_REQUEST['all'] == 0) { - array_push($datas, ['id' => 0, - 'text' => Dropdown::EMPTY_VALUE]); - } else if ($_REQUEST['all'] == 1) { - array_push($datas, ['id' => 0, - 'text' => __('All')]); - } - } -} - -if (count($users)) { - foreach ($users as $ID => $output) { - $title = sprintf('%1$s - %2$s', $output, $logins[$ID]); - - array_push($datas, ['id' => $ID, - 'text' => $output, - 'title' => $title]); - $count++; - } -} - - -if (($one_item >= 0) - && isset($datas[0])) { - echo json_encode($datas[0]); -} else { - $ret['results'] = $datas; - $ret['count'] = $count; - echo json_encode($ret); -} - +request([ + 'FIELDS' => 'glpi_users.*', + 'DISTINCT' => true, + 'FROM' => 'glpi_users', + 'WHERE' => [ + 'glpi_users.id' => $one_item + ] + ]); +} +$users = []; + +// Count real items returned +$count = 0; +foreach ($res as $data) { + $users[$data["id"]] = $dbu->formatUserName($data["id"], $data["name"], $data["realname"], + $data["firstname"], 0); + $logins[$data["id"]] = $data["name"]; +} + + +$datas = []; + +// Display first if empty search +if ($_REQUEST['page'] == 1 && empty($_REQUEST['searchText'])) { + if (($one_item < 0) || ($one_item == 0)) { + if ($_REQUEST['all'] == 0) { + array_push($datas, ['id' => 0, + 'text' => Dropdown::EMPTY_VALUE]); + } else if ($_REQUEST['all'] == 1) { + array_push($datas, ['id' => 0, + 'text' => __('All')]); + } + } +} + +if (count($users)) { + foreach ($users as $ID => $output) { + $title = sprintf('%1$s - %2$s', $output, $logins[$ID]); + + array_push($datas, ['id' => $ID, + 'text' => $output, + 'title' => $title]); + $count++; + } +} + + +if (($one_item >= 0) + && isset($datas[0])) { + echo json_encode($datas[0]); +} else { + $ret['results'] = $datas; + $ret['count'] = $count; + echo json_encode($ret); +} + diff --git a/ajax/task_users.php b/ajax/task_users.php index e6b9393..8768b9b 100644 --- a/ajax/task_users.php +++ b/ajax/task_users.php @@ -1,137 +1,148 @@ -". - "". - "". - "". - "". - "". - "". - "". - ""; - -$PM_SOAP = new PluginProcessmakerProcessmaker; // not used in this context, just here to define the type of $PM_SOAP -$PM_DB = new PluginProcessmakerDB; -$rand = rand(); - -echo "
"; -echo __('Re-assign task to', 'processmaker')." "; -echo ""; -echo ""; -echo $commoninputs; - -$can_unclaim = false; // by default -$query = "SELECT TAS_GROUP_VARIABLE FROM TASK WHERE TAS_UID='".$_REQUEST['taskGuid']."' AND TAS_ASSIGN_TYPE='SELF_SERVICE';"; -$res = $PM_DB->query($query); -if ($PM_DB->numrows($res) > 0) { - $can_unclaim = true; -} - -PluginProcessmakerUser::dropdown( ['name' => 'users_id_recipient', - 'value' => $_REQUEST['users_id'], - 'used' => $_REQUEST['used'], - 'entity' => 0, //$item->fields["entities_id"], // not used, as any user can be assigned to any tasks - 'entity_sons' => false, // not used, as any user can be assigned to any tasks - 'right' => 'all', - 'rand' => $rand, - 'width' => '', - 'specific_tags' => ['taskGuid' => $_REQUEST['taskGuid']] - ]); - -echo "  "; -echo ""; -echo ""; - -echo HTML::scriptBlock(" - $(function () { - // Dialog helpers - // Create the dialog with \"Re-assign\" button - function showCommentDlg(title, content, alttext) { - - var dlgContents = { - title: title, - modal: true, - width: 'auto', - height: 'auto', - resizable: false, - close: function (event, ui) { - $(this).dialog('destroy').remove(); - }, - buttons: [{ - text: alttext, - id: 'submit$rand', - disabled: 'disabled', - click: function() { - $('#processmaker_form_task$rand-".$_REQUEST['delIndex']." input[name=comment]').val($('#comment$rand').val()); - //$('#processmaker_form_task$rand-".$_REQUEST['delIndex']."').submit(); - $('input[name=reassign').click(); - $('#submit$rand').button('disable'); - } - }], - show: true, - hide: true - } - $('
').appendTo($('#processmaker_form_task$rand-".$_REQUEST['delIndex']."')); - var locDlg = $('#reassign$rand').html(content + '

Input at least 10 words in English to justify.').dialog(dlgContents); - $('#comment$rand').focus(); - $('#comment$rand').on('keydown keyup', function(e) { - if ($('#comment$rand').val().split(/\W+/).length > 10) { - $('#submit$rand').button('enable'); - } else { - $('#submit$rand').button('disable'); - } - }); - - return locDlg; - }; - - $('input[name=reassign$rand]').click(function (e) { - e.preventDefault(); - if ($('input[name=users_id]').val() == $('input[name=users_id_recipient]').val()) { - // task is already assigned to this user - alert('".__('Task is already assigned to this user or group!', 'processmaker')."', '".__('Re-assign task', 'processmaker')."'); - } else if ($('input[name=users_id_recipient]').val() == 0) { - // un-claim - if (".($can_unclaim ? 1 : 0)." && $('input[name=users_id]').val() != 0) { - showCommentDlg('".__('Un-claim task', 'processmaker')."', - '".__('Please input reason to un-claim
(task will be re-assigned to former group):', 'processmaker')."', - '".__('Un-claim', 'processmaker')."'); - } else { - // task can't be unclaim because it isn't SELF_SERVICE - alert('".__('Can\\\'t un-assign Task!', 'processmaker')."', '".__('Un-claim task', 'processmaker')."'); - } - } else { - showCommentDlg('".__('Re-assign task', 'processmaker')."', - '".__('Please input reason to re-assign:', 'processmaker')."', - '".__('Re-assign', 'processmaker')."'); - } - return false; - }); - }) - "); - - -if (Session::getLoginUserID() != $_REQUEST['users_id']) { - echo "  "; - echo ""; -} - -Html::closeForm(true); +". + "". + "". + "". + "". + "". + "". + "". + ""; + +$PM_SOAP = new PluginProcessmakerProcessmaker; +$PM_DB = new PluginProcessmakerDB; +$rand = rand(); + +echo ""; +echo __('Re-assign task to', 'processmaker')." "; +echo ""; +echo ""; +echo $commoninputs; + +$can_unclaim = false; // by default +$grp = false; +$query = "SELECT TAS_GROUP_VARIABLE FROM TASK WHERE TAS_UID='".$_REQUEST['taskGuid']."' AND TAS_ASSIGN_TYPE='SELF_SERVICE';"; +$res = $PM_DB->query($query); +if ($PM_DB->numrows($res) > 0 && $row = $PM_DB->fetch_assoc($res)) { + $can_unclaim = true; + if ($row['TAS_GROUP_VARIABLE'] != '') { + //self-service value based assignment + $PM_SOAP->login(true); // needs to be logged in to be able to call SOAP + $grp = $PM_SOAP->getGLPIGroupIdForSelfServiceTask($_REQUEST['caseGuid'], $_REQUEST['taskGuid']); + } +} + +PluginProcessmakerUser::dropdown( ['name' => 'users_id_recipient', + 'value' => $_REQUEST['users_id'], + 'used' => $_REQUEST['used'], + 'entity' => 0, //$item->fields["entities_id"], // not used, as any user can be assigned to any tasks + 'entity_sons' => false, // not used, as any user can be assigned to any tasks + 'right' => 'all', + 'all' => ($can_unclaim ? 0 : -1), + 'rand' => $rand, + 'width' => '', + 'specific_tags' => ['taskGuid' => $_REQUEST['taskGuid'], 'grpGuid' => ($grp !== false ? $grp['uid'] : 0)] + ]); + +echo "  "; +echo ""; +echo ""; + +echo HTML::scriptBlock(" + $(function () { + // Dialog helpers + // Create the dialog with \"Re-assign\" button + function showCommentDlg(title, content, alttext) { + + var dlgContents = { + title: title, + modal: true, + width: 'auto', + height: 'auto', + resizable: false, + close: function (event, ui) { + $(this).dialog('destroy').remove(); + }, + buttons: [{ + text: alttext, + id: 'submit$rand', + disabled: 'disabled', + click: function() { + $('#processmaker_form_task$rand-".$_REQUEST['delIndex']." input[name=comment]').val($('#comment$rand').val()); + //$('#processmaker_form_task$rand-".$_REQUEST['delIndex']."').submit(); + $('input[name=reassign').click(); + $('#submit$rand').button('disable'); + } + }], + show: true, + hide: true + } + $('
').appendTo($('#processmaker_form_task$rand-".$_REQUEST['delIndex']."')); + var locDlg = $('#reassign$rand').html(content + '

".addslashes(__('Input at least 10 words in English to justify.','processmaker'))."').dialog(dlgContents); + $('#comment$rand').focus(); + $('#comment$rand').on('keydown keyup', function(e) { + if ($('#comment$rand').val().split(/\W+/).length > 10) { + $('#submit$rand').button('enable'); + } else { + $('#submit$rand').button('disable'); + } + }); + + return locDlg; + }; + + $('input[name=reassign$rand]').click(function (e) { + e.preventDefault(); + if ($('input[name=users_id]').val() == $('input[name=users_id_recipient]').val()) { + // task is already assigned to this user + if ($('input[name=users_id]').val() == 0) { + alert('".addslashes(__('Task is already un-assigned!', 'processmaker'))."', '".addslashes(__('Re-assign task', 'processmaker'))."'); + } else { + alert('".addslashes(__('Task is already assigned to this user!', 'processmaker'))."', '".addslashes(__('Re-assign task', 'processmaker'))."'); + } + } else if ($('input[name=users_id_recipient]').val() == 0) { + // un-claim + if (".($can_unclaim ? 1 : 0)." && $('input[name=users_id]').val() != 0) { + showCommentDlg('".addslashes(__('Un-claim task', 'processmaker'))."', + '".addslashes(__('Please input reason to un-claim
(task will be re-assigned to former group):', 'processmaker'))."', + '".addslashes(__('Un-claim', 'processmaker'))."'); + } else { + // task can't be unclaim because it isn't SELF_SERVICE + alert('".addslashes(__("Can't un-assign task!", 'processmaker'))."', '".addslashes(__('Un-claim task', 'processmaker'))."'); + } + } else { + showCommentDlg('".addslashes(__('Re-assign task', 'processmaker'))."', + '".addslashes(__('Please input reason to re-assign:', 'processmaker'))."', + '".addslashes(__('Re-assign', 'processmaker'))."'); + } + return false; + }); + }) + "); + + +if (Session::getLoginUserID() != $_REQUEST['users_id']) { + echo "  "; + echo ""; +} + +Html::closeForm(true); diff --git a/front/case.php b/front/case.php index 45bb2ac..36b3ff0 100644 --- a/front/case.php +++ b/front/case.php @@ -1,19 +1,19 @@ -config->fields['maintenance']) { - if (Session::haveRightsOr("plugin_processmaker_case", [READ, UPDATE])) { - - Search::show('PluginProcessmakerCase'); - } else { - Html::displayRightError(); - } -} else { - PluginProcessmakerProcessmaker::showUnderMaintenance(); -} - -Html::footer(); - +config->fields['maintenance']) { + if (Session::haveRightsOr("plugin_processmaker_case", [READ, DELETE, CANCEL, ADHOC_REASSIGN])) { + + Search::show('PluginProcessmakerCase'); + } else { + Html::displayRightError(); + } +} else { + PluginProcessmakerProcessmaker::showUnderMaintenance(); +} + +Html::footer(); + diff --git a/front/processmaker.helpdesk.form.php b/front/processmaker.helpdesk.form.php index 599bcb3..28c4ea8 100644 --- a/front/processmaker.helpdesk.form.php +++ b/front/processmaker.helpdesk.form.php @@ -1,273 +1,271 @@ -"; - echo "
"; - echo ""; - - echo ""; - - echo "
".__('Process - Case', 'processmaker')."
"; - echo __('Select the process you want to add', 'processmaker'); - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - PluginProcessmakerProcess::dropdown( [ 'value' => 0, 'entity' => $_SESSION['glpiactive_entity'], 'name' => 'plugin_processmaker_processes_id' ]); - echo ""; - echo ""; - echo "
"; - Html::closeForm(); - - return true; -} - - -/** - * Summary of processMakerShowCase - * @param mixed $ID - * @param mixed $from_helpdesk - */ -function processMakerShowCase($ID, $from_helpdesk) { - global $CFG_GLPI, $PM_SOAP; - - $caseInfo = $PM_SOAP->getCaseInfo( $_REQUEST['case_guid'] ); - if ($caseInfo->status_code == 0) { - // case is created - // Must show it... - - $rand = rand(); - - $PM_SOAP->echoDomain(); - echo ""; - - $tkt = new Ticket; - - // as showFormHelpdesk uses $_POST, we must set it - $_POST = $_REQUEST; - - // must be using bare text - $save_rich_text = $CFG_GLPI["use_rich_text"]; - $CFG_GLPI["use_rich_text"] = false; - - // to get the HTML code for the helpdesk form - $saved_ob_level = ob_get_level(); - ob_start(); - - $tkt->showFormHelpdesk($ID); - - $buffer = ob_get_clean(); - - $CFG_GLPI["use_rich_text"] = $save_rich_text; - - // 9.1 only: hack to fix an issue with the initEditorSystem which calls scriptStart without calling scriptEnd - if (ob_get_level() > $saved_ob_level) { - $buffer = ob_get_clean().$buffer; - } - - //echo $buffer; - //return; - - // to change this HTML code - $dom = new DOMDocument(); - - // will convert '&' to '&', '<' to '<' and '>' to '>' - $buffer = htmlspecialchars($buffer, ENT_NOQUOTES); - // will restore '<' to '<' and '>' to '>' - // so that only the already escaped entites will get the double encoding - // will also change end of bold into a local identifier - $endOfBold = 'end_of_bold'.rand(); - $buffer = str_replace(['<', '>', ''], ['<', '>', $endOfBold], $buffer); - - // will convert any UTF-8 char that can't be expressed in ASCII into an HTML entity - $buffer = mb_convert_encoding($buffer, 'HTML-ENTITIES'); - - $dom->loadHTML($buffer, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); - $xpath = new DOMXPath($dom); - - // hide some fields - $list = [ 'name', 'type', 'locations_id', 'itilcategories_id', 'items_id', 'add' ]; - $xpath_str = '//*[@name="'.implode( '"]/ancestor::tr[1] | //*[@name="', $list ).'"]/ancestor::tr[1]'; - $res = $xpath->query($xpath_str); - foreach ($res as $elt) { - $elt->setAttribute( 'style', 'display:none;'); - } - - // add an input for processguid in the form - $res = $xpath->query('//form[@name="helpdeskform"]'); - $input = $res->item(0)->appendChild(new DOMElement('input')); - $input->setAttribute('name', 'processmaker_process_guid'); - $input->setAttribute('type', 'hidden'); - $input->setAttribute('value', $caseInfo->processId); - - // add an input for processid in the form - $input = $res->item(0)->appendChild(new DOMElement('input')); - $input->setAttribute('name', 'processmaker_processes_id'); - $input->setAttribute('type', 'hidden'); - $input->setAttribute('value', $_REQUEST['processes_id']); - - // special case for content textarea which is in the same tr than the file upload - $res = $xpath->query('//*[@name="content"]/ancestor::div[1] | //*[@name="content"]/ancestor::tr[1]/td[1]'); - foreach ($res as $elt) { - $elt->setAttribute( 'style', 'display:none;'); - } - - $res = $xpath->query('//*[@name="content"]/ancestor::td[1]'); - foreach ($res as $elt) { - // there should be only one td - $elt->setAttribute( 'colspan', '2'); - } - - $res = $xpath->query('//*[@name="content"]/ancestor::tr[1]'); - //$res = $xpath->query('//*[@name="add"]/ancestor::tr[@class="tab_bg_1"]/preceding-sibling::tr[1]'); - $table = $xpath->query('//*[@name="add"]/ancestor::table[1]'); - - $tr = $table->item(0)->insertBefore(new DOMElement('tr'), $res->item(0)); - //$tr = $table->item(0)->appendChild(new DOMElement('tr')); - - $td = $tr->appendChild(new DOMElement('td')); - $td->setAttribute('colspan', '2'); - - $iframe = $td->appendChild(new DOMElement('iframe')); - - $pmCaseUser = $caseInfo->currentUsers[0]; // by default - $paramsURL = "DEL_INDEX={$pmCaseUser->delIndex}&action={$caseInfo->caseStatus}"; - - $iframe->setAttribute('id', 'caseiframe' ); - $iframe->setAttribute('onload', "onLoadFrame( event, '{$caseInfo->caseId}', {$pmCaseUser->delIndex}, {$caseInfo->caseNumber}, '{$caseInfo->processName}') ;" ); - $iframe->setAttribute('width', '100%' ); - $iframe->setAttribute('style', 'border:none;' ); - $iframe->setAttribute('src', "{$PM_SOAP->serverURL}/cases/cases_Open?sid={$PM_SOAP->getPMSessionID()}&APP_UID={$caseInfo->caseId}&{$paramsURL}&rand=$rand&glpi_domain={$PM_SOAP->config->fields['domain']}" ); - - // set the width and the title of the first table th - $th = $xpath->query('//*[@name="add"]/ancestor::table[1]/*/th[1]'); - $th->item(0)->setAttribute('width', '30%'); - $th->item(0)->nodeValue = $caseInfo->processName; - - $buffer = $dom->saveHTML(); - - // revert back - $buffer = str_replace($endOfBold, '', $buffer); - - // will revert back any char converted above - $buffer = mb_convert_encoding($buffer, 'UTF-8', 'HTML-ENTITIES'); - echo $buffer; - } - -} - - -function in_array_recursive($needle, $haystack) { - - $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack)); - - foreach ($it AS $element) { - if ($element == $needle) { - return true; - } - } - - return false; -} - - -// Change profile system -if (isset($_POST['newprofile'])) { - if (isset($_SESSION["glpiprofiles"][$_POST['newprofile']])) { - Session::changeProfile($_POST['newprofile']); - - if ($_SESSION["glpiactiveprofile"]["interface"] == "central") { - Html::redirect($CFG_GLPI['root_doc']."/front/central.php"); - } else { - Html::redirect($_SERVER['PHP_SELF']); - } - - } else { - Html::redirect(preg_replace("/entities_id=.*/", "", $_SERVER['HTTP_REFERER'])); - } -} - -// Manage entity change -if (isset($_GET["active_entity"])) { - if (!isset($_GET["is_recursive"])) { - $_GET["is_recursive"] = 0; - } - if (Session::changeActiveEntities($_GET["active_entity"], $_GET["is_recursive"])) { - if ($_GET["active_entity"] == $_SESSION["glpiactive_entity"]) { - Html::redirect(preg_replace("/entities_id.*/", "", $_SERVER['HTTP_REFERER'])); - } - } -} - -// Redirect management -if (isset($_GET["redirect"])) { - Toolbox::manageRedirect($_GET["redirect"]); -} - -// redirect if no create ticket right -if (!Session::haveRight('ticket', CREATE) - && !Session::haveRight('reminder_public', READ) - && !Session::haveRight("rssfeed_public", READ)) { - - if (Session::haveRight('followup', ITILFollowup::SEEPUBLIC) //TicketFollowup::SEEPUBLIC - || Session::haveRight('task', TicketTask::SEEPUBLIC) - || Session::haveRightsOr('ticketvalidation', [TicketValidation::VALIDATEREQUEST, - TicketValidation::VALIDATEINCIDENT])) { - Html::redirect($CFG_GLPI['root_doc']."/front/ticket.php"); - - } else if (Session::haveRight('reservation', ReservationItem::RESERVEANITEM)) { - Html::redirect($CFG_GLPI['root_doc']."/front/reservationitem.php"); - - } else if (Session::haveRight('knowbase', KnowbaseItem::READFAQ)) { - Html::redirect($CFG_GLPI['root_doc']."/front/helpdesk.faq.php"); - } -} - -Session::checkHelpdeskAccess(); - -Html::helpHeader(__('New ticket'), $_SERVER['PHP_SELF'], $_SESSION["glpiname"]); - - -if (isset($_REQUEST['case_guid'])) { - $res = $DB->request( - 'glpi_plugin_processmaker_cases', [ - 'case_guid'=>$_REQUEST['case_guid'] - ]); - $query = "SELECT * FROM glpi_plugin_processmaker_cases WHERE case_guid='".$_REQUEST['case_guid']."'"; - //$res = $DB->query( $query ); - //if ($DB->numrows( $res )) { // a ticket already exists for this case, then show new cases - if ($res->numrows()) { // a ticket already exists for this case, then show new cases - processMakerShowProcessList(Session::getLoginUserID(), 1); - } else { - // before showing the case, we must check the rights for this user to view it, if entity has been changed in the meanwhile - // and must check if entity of the ticket is in the tree of authorized entities for current profile - $processList = PluginProcessmakerProcessmaker::getProcessesWithCategoryAndProfile( $_REQUEST["itilcategories_id"], $_REQUEST["type"], $_SESSION['glpiactiveprofile']['id'], $_REQUEST['entities_id'] ); - if (in_array( $_REQUEST['entities_id'], $_SESSION['glpiactiveentities']) && in_array_recursive( $_REQUEST['processes_id'], $processList )) { - processMakerShowCase(Session::getLoginUserID(), 1); - } else { - Html::redirect($CFG_GLPI["root_doc"]."/front/helpdesk.public.php?create_ticket=1"); - } - - } -} else { - processMakerShowProcessList(Session::getLoginUserID(), 1); -} - -Html::helpFooter(); - +"; + echo "
"; + echo ""; + + echo ""; + + echo "
".__('Process - Case', 'processmaker')."
"; + echo __('Select the process you want to add', 'processmaker'); + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + PluginProcessmakerProcess::dropdown( [ 'value' => 0, 'entity' => $_SESSION['glpiactive_entity'], 'name' => 'plugin_processmaker_processes_id' ]); + echo ""; + echo ""; + echo "
"; + Html::closeForm(); + + return true; +} + + +/** + * Summary of processMakerShowCase + * @param mixed $users_id + * @param mixed $from_helpdesk + */ +function processMakerShowCase($users_id, $from_helpdesk) { + global $CFG_GLPI, $PM_SOAP; + + $caseInfo = $PM_SOAP->getCaseInfo( $_REQUEST['case_guid'] ); + if ($caseInfo->status_code == 0) { + // case is created + // Must show it... + + $rand = rand(); + + $PM_SOAP->echoDomain(); + echo ""; + + $tkt = new Ticket; + + // as showFormHelpdesk uses $_POST, we must set it + $_POST = $_REQUEST; + + //// must be using bare text + //$save_rich_text = $CFG_GLPI["use_rich_text"]; + //$CFG_GLPI["use_rich_text"] = false; + + // to get the HTML code for the helpdesk form + $saved_ob_level = ob_get_level(); + ob_start(); + + $tkt->showFormHelpdesk($users_id); + + $buffer = ob_get_clean(); + + //$CFG_GLPI["use_rich_text"] = $save_rich_text; + + // 9.1 only: hack to fix an issue with the initEditorSystem which calls scriptStart without calling scriptEnd + if (ob_get_level() > $saved_ob_level) { + $buffer = ob_get_clean().$buffer; + } + + //echo $buffer; + //return; + + // to change this HTML code + $dom = new DOMDocument(); + + // will convert '&' to '&', '<' to '<' and '>' to '>' + $buffer = htmlspecialchars($buffer, ENT_NOQUOTES); + // will restore '<' to '<' and '>' to '>' + // so that only the already escaped entites will get the double encoding + // will also change end of bold into a local identifier + $endOfBold = 'end_of_bold'.rand(); + $endOfSpan = 'end_of_span'.rand(); + $buffer = str_replace(['<', '>', '', ''], ['<', '>', $endOfBold, $endOfSpan], $buffer); + + // will convert any UTF-8 char that can't be expressed in ASCII into an HTML entity + $buffer = mb_convert_encoding($buffer, 'HTML-ENTITIES'); + + $dom->loadHTML($buffer, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); + $xpath = new DOMXPath($dom); + + // hide some fields + $list = [ 'name', 'type', 'locations_id', 'itilcategories_id', 'items_id', 'add' ]; + $xpath_str = '//*[@name="'.implode( '"]/ancestor::tr[1] | //*[@name="', $list ).'"]/ancestor::tr[1]'; + $res = $xpath->query($xpath_str); + foreach ($res as $elt) { + $elt->setAttribute( 'style', 'display:none;'); + } + + // add an input for processguid in the form + $res = $xpath->query('//form[@name="helpdeskform"]'); + $input = $res->item(0)->appendChild(new DOMElement('input')); + $input->setAttribute('name', 'processmaker_process_guid'); + $input->setAttribute('type', 'hidden'); + $input->setAttribute('value', $caseInfo->processId); + + // add an input for processid in the form + $input = $res->item(0)->appendChild(new DOMElement('input')); + $input->setAttribute('name', 'processmaker_processes_id'); + $input->setAttribute('type', 'hidden'); + $input->setAttribute('value', $_REQUEST['processes_id']); + + // special case for content textarea which is in the same tr than the file upload + $res = $xpath->query('//*[@name="content"]/ancestor::div[1] | //*[@name="content"]/ancestor::tr[1]/td[1]'); + foreach ($res as $elt) { + $elt->setAttribute( 'style', 'display:none;'); + } + + $res = $xpath->query('//*[@name="content"]/ancestor::td[1]'); + foreach ($res as $elt) { + // there should be only one td + $elt->setAttribute( 'colspan', '2'); + } + + $res = $xpath->query('//*[@name="content"]/ancestor::tr[1]'); + //$res = $xpath->query('//*[@name="add"]/ancestor::tr[@class="tab_bg_1"]/preceding-sibling::tr[1]'); + $table = $xpath->query('//*[@name="add"]/ancestor::table[1]'); + + $tr = $table->item(0)->insertBefore(new DOMElement('tr'), $res->item(0)); + //$tr = $table->item(0)->appendChild(new DOMElement('tr')); + + $td = $tr->appendChild(new DOMElement('td')); + $td->setAttribute('colspan', '2'); + + $iframe = $td->appendChild(new DOMElement('iframe')); + + $pmCaseUser = $caseInfo->currentUsers[0]; // by default + $paramsURL = "DEL_INDEX={$pmCaseUser->delIndex}&action={$caseInfo->caseStatus}"; + + $iframe->setAttribute('id', 'caseiframe' ); + $iframe->setAttribute('onload', "onLoadFrame( event, '{$caseInfo->caseId}', {$pmCaseUser->delIndex}, {$caseInfo->caseNumber}, '{$caseInfo->processName}') ;" ); + $iframe->setAttribute('width', '100%' ); + $iframe->setAttribute('style', 'border:none;' ); + $iframe->setAttribute('src', "{$PM_SOAP->serverURL}/cases/cases_Open?sid={$PM_SOAP->getPMSessionID()}&APP_UID={$caseInfo->caseId}&{$paramsURL}&rand=$rand&glpi_domain={$PM_SOAP->config->fields['domain']}" ); + + // set the width and the title of the first table th + $th = $xpath->query('//*[@name="add"]/ancestor::table[1]/*/th[1]'); + $th->item(0)->setAttribute('width', '30%'); + $th->item(0)->nodeValue = $caseInfo->processName; + + $buffer = $dom->saveHTML(); + + // revert back and + $buffer = str_replace([$endOfSpan, $endOfBold], ['', ''], $buffer); + + // will revert back any char converted above + $buffer = mb_convert_encoding($buffer, 'UTF-8', 'HTML-ENTITIES'); + echo $buffer; + } + +} + + +function in_array_recursive($needle, $haystack) { + + $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($haystack)); + + foreach ($it AS $element) { + if ($element == $needle) { + return true; + } + } + + return false; +} + + +// Change profile system +if (isset($_POST['newprofile'])) { + if (isset($_SESSION["glpiprofiles"][$_POST['newprofile']])) { + Session::changeProfile($_POST['newprofile']); + + if ($_SESSION["glpiactiveprofile"]["interface"] == "central") { + Html::redirect($CFG_GLPI['root_doc']."/front/central.php"); + } else { + Html::redirect($_SERVER['PHP_SELF']); + } + + } else { + Html::redirect(preg_replace("/entities_id=.*/", "", $_SERVER['HTTP_REFERER'])); + } +} + +// Manage entity change +if (isset($_GET["active_entity"])) { + if (!isset($_GET["is_recursive"])) { + $_GET["is_recursive"] = 0; + } + if (Session::changeActiveEntities($_GET["active_entity"], $_GET["is_recursive"])) { + if ($_GET["active_entity"] == $_SESSION["glpiactive_entity"]) { + Html::redirect(preg_replace("/entities_id.*/", "", $_SERVER['HTTP_REFERER'])); + } + } +} + +// Redirect management +if (isset($_GET["redirect"])) { + Toolbox::manageRedirect($_GET["redirect"]); +} + +// redirect if no create ticket right +if (!Session::haveRight('ticket', CREATE) + && !Session::haveRight('reminder_public', READ) + && !Session::haveRight("rssfeed_public", READ)) { + + if (Session::haveRight('followup', ITILFollowup::SEEPUBLIC) //TicketFollowup::SEEPUBLIC + || Session::haveRight('task', TicketTask::SEEPUBLIC) + || Session::haveRightsOr('ticketvalidation', [TicketValidation::VALIDATEREQUEST, + TicketValidation::VALIDATEINCIDENT])) { + Html::redirect($CFG_GLPI['root_doc']."/front/ticket.php"); + + } else if (Session::haveRight('reservation', ReservationItem::RESERVEANITEM)) { + Html::redirect($CFG_GLPI['root_doc']."/front/reservationitem.php"); + + } else if (Session::haveRight('knowbase', KnowbaseItem::READFAQ)) { + Html::redirect($CFG_GLPI['root_doc']."/front/helpdesk.faq.php"); + } +} + +Session::checkHelpdeskAccess(); + +Html::helpHeader(__('New ticket'), $_SERVER['PHP_SELF'], $_SESSION["glpiname"]); + + +if (isset($_REQUEST['case_guid'])) { + $res = $DB->request('glpi_plugin_processmaker_cases', ['case_guid' => $_REQUEST['case_guid']]); + //$query = "SELECT * FROM glpi_plugin_processmaker_cases WHERE case_guid='".$_REQUEST['case_guid']."'"; + //$res = $DB->query( $query ); + //if ($DB->numrows( $res )) { // a ticket already exists for this case, then show new cases + if ($res->numrows()) { // a ticket already exists for this case, then show new cases + processMakerShowProcessList(Session::getLoginUserID(), 1); + } else { + // before showing the case, we must check the rights for this user to view it, if entity has been changed in the meanwhile + // and must check if entity of the ticket is in the tree of authorized entities for current profile + $processList = PluginProcessmakerProcessmaker::getProcessesWithCategoryAndProfile( $_REQUEST["itilcategories_id"], $_REQUEST["type"], $_SESSION['glpiactiveprofile']['id'], $_REQUEST['entities_id'] ); + if (in_array( $_REQUEST['entities_id'], $_SESSION['glpiactiveentities']) && in_array_recursive( $_REQUEST['processes_id'], $processList )) { + processMakerShowCase(Session::getLoginUserID(), 1); + } else { + Html::redirect($CFG_GLPI["root_doc"]."/front/helpdesk.public.php?create_ticket=1"); + } + + } +} else { + processMakerShowProcessList(Session::getLoginUserID(), 1); +} + +Html::helpFooter(); + diff --git a/hook.php b/hook.php index 459ccf8..4a1f2aa 100644 --- a/hook.php +++ b/hook.php @@ -1,474 +1,486 @@ - __('Synchronize Task List', 'processmaker')]; - } - break; - case 'PluginProcessmakerProcess_Profile' : - if (plugin_processmaker_haveRight('config', UPDATE)) { - return ['purge' => __('Delete permanently')]; - } - break; - //case 'PluginProcessmakerCase' : - // if (plugin_processmaker_haveRight("case", DELETE)) { - // return array('purge' => __('Delete permanently')); - // } - //break; - } - return []; -} - - -/** - * Summary of plugin_processmaker_install - * Creates tables and initializes tasks, "GLPI Requesters" group - * and so on - * @return true or die! - */ -function plugin_processmaker_install() { - global $DB; - if (!$DB->tableExists("glpi_plugin_processmaker_cases")) { - // new installation - include_once(GLPI_ROOT."/plugins/processmaker/install/install.php"); - processmaker_install(); - - } else { - // upgrade installation - include_once(GLPI_ROOT."/plugins/processmaker/install/update.php"); - processmaker_update(); - } - - // To be called for each task managed by the plugin - // task in class - CronTask::Register('PluginProcessmakerProcessmaker', 'pmusers', DAY_TIMESTAMP, [ 'state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL]); - CronTask::Register('PluginProcessmakerProcessmaker', 'pmorphancases', DAY_TIMESTAMP, ['param' => 10, 'state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL]); - CronTask::Register('PluginProcessmakerProcessmaker', 'pmtaskactions', MINUTE_TIMESTAMP, ['state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL]); - - // required because autoload doesn't work for unactive plugin' - include_once(GLPI_ROOT."/plugins/processmaker/inc/profile.class.php"); - PluginProcessmakerProfile::createAdminAccess($_SESSION['glpiactiveprofile']['id']); - - return true; -} - -function plugin_processmaker_uninstall() { - - CronTask::Unregister('PluginProcessmakerProcessmaker'); - - return true; -} - - -function plugin_processmaker_getAddSearchOptions($itemtype) { - - $sopt = []; - // TODO add Change and Problem + other fields to the search - if ($itemtype == 'Ticket') { - $sopt[10001]['table'] = 'glpi_plugin_processmaker_cases'; - $sopt[10001]['field'] = 'case_status'; - //$sopt[1001]['linkfield'] = 'id'; - $sopt[10001]['massiveaction'] = false; - $sopt[10001]['name'] = __('Case', 'processmaker').' - '.__('Status', 'processmaker'); - $sopt[10001]['datatype'] = 'text'; - $sopt[10001]['forcegroupby'] = true; - //$sopt[10001]['searchtype'] = 'equals'; - - //$sopt[1001]['itemlink_type'] = 'PluginProcessmakerTicketcase'; - - //$sopt[1001]['table'] = 'glpi_plugin_processmaker_ticketcase'; - //$sopt[1001]['field'] = 'case_status'; - //$sopt[1001]['massiveaction'] = false; - //$sopt[1001]['name'] = 'Case - Status'; - //$sopt[1001]['forcegroupby'] = true; - //$sopt[1001]['datatype'] = 'itemlink'; - // $sopt[1001]['itemlink_type'] = 'PluginProcessmakerProcessmaker'; - //$sopt[1001]['joinparams'] = array('beforejoin' - // => array('table' => 'glpi_plugin_processmaker_ticketcase', - // 'linkfield' => 'ticket_id')); - - //$sopt[1001]['joinparams']['jointype'] = "itemtype_id"; - //$sopt[1001]['pfields_type'] = ; - } - return $sopt; -} - -function plugin_processmaker_addLeftJoin($type, $ref_table, $new_table, $linkfield, &$already_link_tables) { - - switch ($type) { - - case 'Ticket': - switch ($new_table) { - - case "glpi_plugin_processmaker_cases" : - $out= " LEFT JOIN `glpi_plugin_processmaker_cases` - ON (`$ref_table`.`id` = `glpi_plugin_processmaker_cases`.`items_id` AND `glpi_plugin_processmaker_cases`.`itemtype` like 'Ticket') "; - return $out; - - } - - return ""; - - } - - return ""; -} - -/** - * Summary of plugin_pre_item_update_processmaker - * @param CommonITILObject $parm is an object - * @return void - */ -function plugin_pre_item_update_processmaker(CommonITILObject $parm) { - global $DB;//, $PM_SOAP; - - if (isset($_SESSION['glpiname'])) { // && $parm->getType() == 'Ticket') { - $locVar = [ ]; - foreach ($parm->input as $key => $val) { - 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; - break; - case 'date' : - $locVar[ 'GLPI_ITEM_OPENING_DATE' ] = $val; - break; - case 'time_to_resolve' : - $locVar[ 'GLPI_TICKET_DUE_DATE' ] = $val; - $locVar[ 'GLPI_ITEM_DUE_DATE' ] = $val; - break; - case 'urgency' : - $locVar[ 'GLPI_TICKET_URGENCY' ] = $val; - $locVar[ 'GLPI_ITEM_URGENCY' ] = $val; - break; - case 'impact' : - $locVar[ 'GLPI_ITEM_IMPACT' ] = $val; - break; - case 'priority' : - $locVar[ 'GLPI_ITEM_PRIORITY' ] = $val; - break; - } - } - - $itemId = $parm->getID(); - $itemType = $parm->getType(); - - $locCase = new PluginProcessmakerCase; - foreach (PluginProcessmakerCase::getIDsFromItem($itemType, $itemId ) as $cases_id) { - $locCase->getFromDB($cases_id); - $locCase->sendVariables($locVar); - - // if entities_id of item has been changed, then must update case - if (isset($parm->input['entities_id']) && $parm->input['entities_id'] != $parm->fields['entities_id']) { - $locCase->update(['id' => $cases_id, 'entities_id' => $parm->input['entities_id']]); - } - } - } - -} - -/** - * Summary of plugin_item_update_processmaker_satisfaction - * inject satisfaction survey into case - * @param mixed $parm is the object - */ -function plugin_item_update_processmaker_satisfaction($parm) { - global $PM_SOAP; - if (Session::isCron()) { // Task cron log with user admin - $PM_SOAP->login(true); - } - $cases = PluginProcessmakerCase::getIDsFromItem('Ticket', $parm->fields['tickets_id']); - foreach ($cases as $cases_id) { - $locCase = new PluginProcessmakerCase; - if ($locCase->getFromDB($cases_id)) { - // case is existing for this item - $locCase->sendVariables( ['GLPI_SATISFACTION_QUALITY' => $parm->fields['satisfaction']] ); - } - } -} - - -/** - * Summary of plugin_item_update_processmaker_user - * When a user login is changed, then must change it in the PM tables - * @param User $param is the user being changed - */ -function plugin_item_update_processmaker_user(User $param) { - // Must test if user login has been changed - // if yes, must change the login in the PM tables: - // USERS and RBAC_USERS, othewise the link in the processmaker_users table will be invalid - if (in_array('name', $param->updates)) { - // check if user is in the processmaker_user table - $pm_user = PluginProcessmakerUser::getPMUserId($param->getID()); - if ($pm_user) { - // must update the user in PM tables - global $PM_SOAP; - if ($param->fields['is_active'] == 0 || $param->fields['is_deleted'] == 1) { - $status = "INACTIVE"; - } else { - $status = "ACTIVE"; - } - $PM_SOAP->login(true); - $pmResult = $PM_SOAP->updateUser( $pm_user, $param->fields['name'], $param->fields['firstname'], $param->fields['realname'], $status ); - } - } -} - - -function plugin_processmaker_post_init() { - global $PM_DB, $PM_SOAP; - if (!isset($PM_DB)) { - $PM_DB = new PluginProcessmakerDB; - } - if (!isset($PM_SOAP)) { - $PM_SOAP = new PluginProcessmakerProcessmaker; - // and default login is current running user if any - if (Session::getLoginUserID()) { - $PM_SOAP->login(); - } - } -} - - -function plugin_processmaker_giveItem($itemtype, $ID, $data, $num) { - - return; -} - -function plugin_processmaker_change_profile() { - if ($_SESSION['glpiactiveprofile']['interface'] == "helpdesk") { - // must add the rights for simplified interface - $_SESSION['glpiactiveprofile']['plugin_processmaker_case'] = READ; - } -} - -/** - * Summary of plugin_item_add_update_processmaker_tasks - * @param mixed $parm - */ -function plugin_item_update_processmaker_tasks($parm) { - global $DB, $CFG_GLPI, $PM_SOAP; - - $pmTaskCat = new PluginProcessmakerTaskCategory; - if ($pmTaskCat->getFromDBbyCategory( $parm->fields['taskcategories_id'] ) - && in_array( 'state', $parm->updates ) - && $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() ); - - $pmTask = new PluginProcessmakerTask($parm->getType()); - $pmTask->getFromDB($parm->fields['id']); - - $locCase = new PluginProcessmakerCase; - $locCase->getFromDB($pmTask->fields['plugin_processmaker_cases_id']); - $srccase_guid = $locCase->fields['case_guid']; - - //$msg = Toolbox::backtrace(false); - //$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 - $casevariables = []; - - $matches = []; - if (preg_match_all( "/@@(\w+)/u", $targetTask['sourcecondition'], $matches )) { - $casevariables = $matches[1]; - } - - $targetTask['targetactions'] = []; // empty array by default - foreach ($DB->request( 'glpi_plugin_processmaker_caselinkactions', 'plugin_processmaker_caselinks_id = '.$targetTask['id']) as $actionvalue) { - $targetTask['targetactions'][$actionvalue['name']] = $actionvalue['value']; - if (preg_match_all( "/@@(\w+)/u", $actionvalue['value'], $matches )) { - $casevariables = array_merge( $casevariables, $matches[1] ); - } - } - $externalapplication = false; // by default - if ($targetTask['is_externaldata'] && isset($targetTask['externalapplication'])) { - // must read some values - $externalapplication = json_decode( $targetTask['externalapplication'], true ); - // must be of the form - // {"method":"POST","url":"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 - foreach ($externalapplication['params'] as $paramname => $variable) { - if (preg_match_all( "/@@(\w+)/u", $variable, $matches )) { - $casevariables = array_merge( $casevariables, $matches[1] ); - } - } - } - - // ask for those case variables - //$PM_SOAP = new PluginProcessmakerProcessmaker(); - //$PM_SOAP->login( ); - // now tries to get the variables to check condition - $infoForTasks = $locCase->getVariables($casevariables); - foreach ($infoForTasks as $casevar => $varval) { - $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'] ); - - $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 - - $postdata = []; - foreach ($targetTask['targetactions'] as $action => $actionvalue) { - $postdata['form'][$action] = eval( "return ".str_replace( array_keys($infoForTasks), $infoForTasks, $actionvalue)." ;" ); - } - $postdata['UID'] = $targetTask['targetdynaform_guid']; - $postdata['__DynaformName__'] = $targetTask['targetprocess_guid']."_".$targetTask['targetdynaform_guid']; - $postdata['__notValidateThisFields__'] = '[]'; - $postdata['DynaformRequiredFields'] = '[]'; - $postdata['form']['btnGLPISendRequest'] = 'submit'; - - $externalapplicationparams = []; - if ($externalapplication) { - // must call curl - foreach ($externalapplication['params'] as $paramname => $variable) { - $externalapplicationparams[$paramname] = eval( "return ".str_replace( array_keys($infoForTasks), $infoForTasks, $variable)." ;" ); - } - $externalapplicationparams['callback'] = $CFG_GLPI["url_base"]."/plugins/processmaker/ajax/asynchronousdatas.php"; - $ch = curl_init(); - $externalapplication['url'] = eval( "return '".str_replace( array_keys($infoForTasks), $infoForTasks, $externalapplication['url'])."' ;" ); // '??? - curl_setopt($ch, CURLOPT_URL, $externalapplication['url'] ); - if (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 - if ($task->guid == $targetTask['targettask_guid']) { - break; - } - } - $PM_SOAP->login(); - - $postdata['APP_UID'] = $srccase_guid; - $postdata['DEL_INDEX'] = $task->delegate; - - //need to get the 'ProcessMaker' user - $pmconfig = $PM_SOAP->config; //PluginProcessmakerConfig::getInstance(); - - $cronaction = new PluginProcessmakerCrontaskaction; - $cronaction->add( [ 'plugin_processmaker_caselinks_id' => $targetTask['id'], - 'plugin_processmaker_cases_id' => $locCase->getID(), - //'itemtype' => $itemtype, - //'items_id' => $parm->fields['tickets_id'], - 'users_id' => $pmconfig->fields['users_id'], - 'is_targettoclaim' => $targetTask['is_targettoclaim'], - 'state' => ($targetTask['is_externaldata'] ? PluginProcessmakerCrontaskaction::WAITING_DATA : PluginProcessmakerCrontaskaction::DATA_READY), - 'postdata' => json_encode( $postdata, JSON_HEX_APOS | JSON_HEX_QUOT), - 'logs_out' => json_encode( $externalapplicationparams, JSON_HEX_APOS | JSON_HEX_QUOT) - ], - null, - false); - - if ($externalapplication) { - // must call external application in order to get the needed data asynchroneously - // must be of the form - // {"url":"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_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); - - if (isset($externalapplication['ssl_verify'])) { - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $externalapplication['ssl_verify']); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $externalapplication['ssl_verify']); - } - - if (isset($externalapplication['proxy'])) { - curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1 ) ; - curl_setopt($ch, CURLOPT_PROXY, $externalapplication['proxy']); - } - - $response = curl_exec ($ch); - if ($response === false) { - //throw new Exception(curl_error($ch), curl_errno($ch)); - Toolbox::logDebug( curl_error($ch).":".curl_errno($ch) ); - } - - curl_close ($ch); - } - // } - } 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 - JOIN glpi_plugin_processmaker_taskcategories ON glpi_plugin_processmaker_taskcategories.taskcategories_id=glpi_tickettasks.taskcategories_id - JOIN glpi_plugin_processmaker_cases ON glpi_plugin_processmaker_cases.processes_id=glpi_plugin_processmaker_taskcategories.processes_id - RIGHT JOIN glpi_plugin_processmaker_tasks ON glpi_plugin_processmaker_tasks.items_id=glpi_tickettasks.id AND glpi_plugin_processmaker_tasks.case_id=glpi_plugin_processmaker_cases.id - WHERE glpi_plugin_processmaker_taskcategories.pm_task_guid = '".$targetTask['targettask_guid']."' AND glpi_tickettasks.state = 1 AND glpi_tickettasks.tickets_id=".$tlink['tickets_id']; - foreach ($DB->request($query) as $case) { - // must be only one row - - $postdata['APP_UID'] = $case['id']; - $postdata['DEL_INDEX'] = $case['del_index']; - - $cronaction = new PluginProcessmakerCrontaskaction; - $cronaction->add( [ 'plugin_processmaker_caselinks_id' => $targetTask['id'], - 'plugin_processmaker_cases_id' => $locCase->getID(), - //'itemtype' => $itemtype, - //'items_id' => $parm->fields['tickets_id'], - 'users_id' => Session::getLoginUserID(), - 'is_targettoclaim' => $targetTask['is_targettoclaim'], - 'state' => ($targetTask['is_externaldata'] ? PluginProcessmakerCrontaskaction::WAITING_DATA : PluginProcessmakerCrontaskaction::DATA_READY), - 'postdata' => json_encode( $postdata, JSON_HEX_APOS | JSON_HEX_QUOT), - 'logs_out' => json_encode( $externalapplicationparams, JSON_HEX_APOS | JSON_HEX_QUOT) - ], - null, - false); - } - } - } - } - - if ($targetTask['is_synchronous']) { - // must call PluginProcessmakerProcessmaker::cronPMTaskActions() - PluginProcessmakerProcessmaker::cronPMTaskActions(); - } - } - - } - - //$msg .= "================\n"; - //Toolbox::logInFile("processmaker", $msg); - - } -} + __('Synchronize Task List', 'processmaker')]; + } + break; + case 'PluginProcessmakerProcess_Profile' : + if (plugin_processmaker_haveRight('config', UPDATE)) { + return ['purge' => __('Delete permanently')]; + } + break; + //case 'PluginProcessmakerCase' : + // if (plugin_processmaker_haveRight("case", DELETE)) { + // return array('purge' => __('Delete permanently')); + // } + //break; + } + return []; +} + + +/** + * Summary of plugin_processmaker_install + * Creates tables and initializes tasks, "GLPI Requesters" group + * and so on + * @return true or die! + */ +function plugin_processmaker_install() { + global $DB; + if (!$DB->tableExists("glpi_plugin_processmaker_cases")) { + // new installation + include_once(GLPI_ROOT."/plugins/processmaker/install/install.php"); + processmaker_install(); + + } else { + // upgrade installation + include_once(GLPI_ROOT."/plugins/processmaker/install/update.php"); + processmaker_update(); + } + + // To be called for each task managed by the plugin + // task in class + CronTask::Register('PluginProcessmakerProcessmaker', 'pmusers', DAY_TIMESTAMP, [ 'state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL]); + CronTask::Register('PluginProcessmakerProcessmaker', 'pmorphancases', DAY_TIMESTAMP, ['param' => 10, 'state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL]); + CronTask::Register('PluginProcessmakerProcessmaker', 'pmtaskactions', MINUTE_TIMESTAMP, ['state' => CronTask::STATE_DISABLE, 'mode' => CronTask::MODE_EXTERNAL]); + + // required because autoload doesn't work for unactive plugin' + include_once(GLPI_ROOT."/plugins/processmaker/inc/profile.class.php"); + PluginProcessmakerProfile::createAdminAccess($_SESSION['glpiactiveprofile']['id']); + + return true; +} + +function plugin_processmaker_uninstall() { + + CronTask::Unregister('PluginProcessmakerProcessmaker'); + + return true; +} + + +function plugin_processmaker_getAddSearchOptions($itemtype) { + + $sopt = []; + // TODO add Change and Problem + other fields to the search + if ($itemtype == 'Ticket') { + $sopt[10001]['table'] = 'glpi_plugin_processmaker_cases'; + $sopt[10001]['field'] = 'case_status'; + //$sopt[1001]['linkfield'] = 'id'; + $sopt[10001]['massiveaction'] = false; + $sopt[10001]['name'] = __('Case', 'processmaker').' - '.__('Status', 'processmaker'); + $sopt[10001]['datatype'] = 'text'; + $sopt[10001]['forcegroupby'] = true; + //$sopt[10001]['searchtype'] = 'equals'; + + //$sopt[1001]['itemlink_type'] = 'PluginProcessmakerTicketcase'; + + //$sopt[1001]['table'] = 'glpi_plugin_processmaker_ticketcase'; + //$sopt[1001]['field'] = 'case_status'; + //$sopt[1001]['massiveaction'] = false; + //$sopt[1001]['name'] = 'Case - Status'; + //$sopt[1001]['forcegroupby'] = true; + //$sopt[1001]['datatype'] = 'itemlink'; + // $sopt[1001]['itemlink_type'] = 'PluginProcessmakerProcessmaker'; + //$sopt[1001]['joinparams'] = array('beforejoin' + // => array('table' => 'glpi_plugin_processmaker_ticketcase', + // 'linkfield' => 'ticket_id')); + + //$sopt[1001]['joinparams']['jointype'] = "itemtype_id"; + //$sopt[1001]['pfields_type'] = ; + } + return $sopt; +} + +function plugin_processmaker_addLeftJoin($type, $ref_table, $new_table, $linkfield, &$already_link_tables) { + + switch ($type) { + + case 'Ticket': + switch ($new_table) { + + case "glpi_plugin_processmaker_cases" : + $out= " LEFT JOIN `glpi_plugin_processmaker_cases` + ON (`$ref_table`.`id` = `glpi_plugin_processmaker_cases`.`items_id` AND `glpi_plugin_processmaker_cases`.`itemtype` like 'Ticket') "; + return $out; + + } + + return ""; + + } + + return ""; +} + +/** + * Summary of plugin_pre_item_update_processmaker + * @param CommonITILObject $parm is an object + * @return void + */ +function plugin_pre_item_update_processmaker(CommonITILObject $parm) { + //global $DB;//, $PM_SOAP; + + // look at previous status + if (isset($parm->input['status']) + && $parm->input['status'] == CommonITILObject::SOLVED + && !in_array($parm->fields['status'], [CommonITILObject::SOLVED, CommonITILObject::CLOSED]) + && !PluginProcessmakerCase::canSolve(['item' => $parm])) { + $parm->input = []; // empty array... to prevent item update + Session::addMessageAfterRedirect(__('At least one \'Process case\' is running!
Solving is currently disabled!', 'processmaker'), false, ERROR); + return; + } + + + if (isset($_SESSION['glpiname'])) { + $locVar = [ ]; + foreach ($parm->input as $key => $val) { + 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; + break; + case 'date' : + $locVar[ 'GLPI_ITEM_OPENING_DATE' ] = $val; + break; + case 'time_to_resolve' : + $locVar[ 'GLPI_TICKET_DUE_DATE' ] = $val; + $locVar[ 'GLPI_ITEM_DUE_DATE' ] = $val; + break; + case 'urgency' : + $locVar[ 'GLPI_TICKET_URGENCY' ] = $val; + $locVar[ 'GLPI_ITEM_URGENCY' ] = $val; + break; + case 'impact' : + $locVar[ 'GLPI_ITEM_IMPACT' ] = $val; + break; + case 'priority' : + $locVar[ 'GLPI_ITEM_PRIORITY' ] = $val; + break; + } + } + + $itemId = $parm->getID(); + $itemType = $parm->getType(); + + $locCase = new PluginProcessmakerCase; + foreach (PluginProcessmakerCase::getIDsFromItem($itemType, $itemId) as $cases_id) { + $locCase->getFromDB($cases_id); + $locCase->sendVariables($locVar); + + // if entities_id of item has been changed, then must update case + if (isset($parm->input['entities_id']) && $parm->input['entities_id'] != $parm->fields['entities_id']) { + $locCase->update(['id' => $cases_id, 'entities_id' => $parm->input['entities_id']]); + } + } + } + +} + +/** + * Summary of plugin_item_update_processmaker_satisfaction + * inject satisfaction survey into case + * @param mixed $parm is the object + */ +function plugin_item_update_processmaker_satisfaction($parm) { + global $PM_SOAP; + if (Session::isCron()) { // Task cron log with user admin + $PM_SOAP->login(true); + } + $cases = PluginProcessmakerCase::getIDsFromItem('Ticket', $parm->fields['tickets_id']); + foreach ($cases as $cases_id) { + $locCase = new PluginProcessmakerCase; + if ($locCase->getFromDB($cases_id)) { + // case is existing for this item + $locCase->sendVariables( ['GLPI_SATISFACTION_QUALITY' => $parm->fields['satisfaction']] ); + } + } +} + + +/** + * Summary of plugin_item_update_processmaker_user + * When a user login is changed, then must change it in the PM tables + * @param User $param is the user being changed + */ +function plugin_item_update_processmaker_user(User $param) { + // Must test if user login has been changed + // if yes, must change the login in the PM tables: + // USERS and RBAC_USERS, othewise the link in the processmaker_users table will be invalid + if (in_array('name', $param->updates)) { + // check if user is in the processmaker_user table + $pm_user = PluginProcessmakerUser::getPMUserId($param->getID()); + if ($pm_user) { + // must update the user in PM tables + global $PM_SOAP; + if ($param->fields['is_active'] == 0 || $param->fields['is_deleted'] == 1) { + $status = "INACTIVE"; + } else { + $status = "ACTIVE"; + } + $PM_SOAP->login(true); + $pmResult = $PM_SOAP->updateUser( $pm_user, $param->fields['name'], $param->fields['firstname'], $param->fields['realname'], $status ); + } + } +} + + +function plugin_processmaker_post_init() { + global $PM_DB, $PM_SOAP; + if (!isset($PM_DB)) { + $PM_DB = new PluginProcessmakerDB; + } + if (!isset($PM_SOAP)) { + $PM_SOAP = new PluginProcessmakerProcessmaker; + // and default login is current running user if any + if (Session::getLoginUserID()) { + $PM_SOAP->login(); + } + } +} + + +function plugin_processmaker_giveItem($itemtype, $ID, $data, $num) { + + return; +} + + +function plugin_processmaker_change_profile() { + if ($_SESSION['glpiactiveprofile']['interface'] == "helpdesk") { + // must add the rights for simplified interface + $_SESSION['glpiactiveprofile']['plugin_processmaker_case'] = READ; + } +} + +/** + * Summary of plugin_item_add_update_processmaker_tasks + * @param mixed $parm + */ +function plugin_item_update_processmaker_tasks($parm) { + global $DB, $CFG_GLPI, $PM_SOAP; + + $pmTaskCat = new PluginProcessmakerTaskCategory; + if ($pmTaskCat->getFromDBbyCategory( $parm->fields['taskcategories_id'] ) + && in_array( 'state', $parm->updates ) + && $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() ); + + $pmTask = new PluginProcessmakerTask($parm->getType()); + $pmTask->getFromDB($parm->fields['id']); + + $locCase = new PluginProcessmakerCase; + $locCase->getFromDB($pmTask->fields['plugin_processmaker_cases_id']); + $srccase_guid = $locCase->fields['case_guid']; + + //$msg = Toolbox::backtrace(false); + //$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 + $casevariables = []; + + $matches = []; + if (preg_match_all( "/@@(\w+)/u", $targetTask['sourcecondition'], $matches )) { + $casevariables = $matches[1]; + } + + $targetTask['targetactions'] = []; // empty array by default + foreach ($DB->request( 'glpi_plugin_processmaker_caselinkactions', 'plugin_processmaker_caselinks_id = '.$targetTask['id']) as $actionvalue) { + $targetTask['targetactions'][$actionvalue['name']] = $actionvalue['value']; + if (preg_match_all( "/@@(\w+)/u", $actionvalue['value'], $matches )) { + $casevariables = array_merge( $casevariables, $matches[1] ); + } + } + $externalapplication = false; // by default + if ($targetTask['is_externaldata'] && isset($targetTask['externalapplication'])) { + // must read some values + $externalapplication = json_decode( $targetTask['externalapplication'], true ); + // must be of the form + // {"method":"POST","url":"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 + foreach ($externalapplication['params'] as $paramname => $variable) { + if (preg_match_all( "/@@(\w+)/u", $variable, $matches )) { + $casevariables = array_merge( $casevariables, $matches[1] ); + } + } + } + + // ask for those case variables + //$PM_SOAP = new PluginProcessmakerProcessmaker(); + //$PM_SOAP->login( ); + // now tries to get the variables to check condition + $infoForTasks = $locCase->getVariables($casevariables); + foreach ($infoForTasks as $casevar => $varval) { + $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'] ); + + $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 + + $postdata = []; + foreach ($targetTask['targetactions'] as $action => $actionvalue) { + $postdata['form'][$action] = eval( "return ".str_replace( array_keys($infoForTasks), $infoForTasks, $actionvalue)." ;" ); + } + $postdata['UID'] = $targetTask['targetdynaform_guid']; + $postdata['__DynaformName__'] = $targetTask['targetprocess_guid']."_".$targetTask['targetdynaform_guid']; + $postdata['__notValidateThisFields__'] = '[]'; + $postdata['DynaformRequiredFields'] = '[]'; + $postdata['form']['btnGLPISendRequest'] = 'submit'; + + $externalapplicationparams = []; + if ($externalapplication) { + // must call curl + foreach ($externalapplication['params'] as $paramname => $variable) { + $externalapplicationparams[$paramname] = eval( "return ".str_replace( array_keys($infoForTasks), $infoForTasks, $variable)." ;" ); + } + $externalapplicationparams['callback'] = $CFG_GLPI["url_base"]."/plugins/processmaker/ajax/asynchronousdatas.php"; + $ch = curl_init(); + $externalapplication['url'] = eval( "return '".str_replace( array_keys($infoForTasks), $infoForTasks, $externalapplication['url'])."' ;" ); // '??? + curl_setopt($ch, CURLOPT_URL, $externalapplication['url'] ); + if (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 + if ($task->guid == $targetTask['targettask_guid']) { + break; + } + } + $PM_SOAP->login(); + + $postdata['APP_UID'] = $srccase_guid; + $postdata['DEL_INDEX'] = $task->delegate; + + //need to get the 'ProcessMaker' user + $pmconfig = $PM_SOAP->config; //PluginProcessmakerConfig::getInstance(); + + $cronaction = new PluginProcessmakerCrontaskaction; + $cronaction->add( [ 'plugin_processmaker_caselinks_id' => $targetTask['id'], + 'plugin_processmaker_cases_id' => $locCase->getID(), + //'itemtype' => $itemtype, + //'items_id' => $parm->fields['tickets_id'], + 'users_id' => $pmconfig->fields['users_id'], + 'is_targettoclaim' => $targetTask['is_targettoclaim'], + 'state' => ($targetTask['is_externaldata'] ? PluginProcessmakerCrontaskaction::WAITING_DATA : PluginProcessmakerCrontaskaction::DATA_READY), + 'postdata' => json_encode( $postdata, JSON_HEX_APOS | JSON_HEX_QUOT), + 'logs_out' => json_encode( $externalapplicationparams, JSON_HEX_APOS | JSON_HEX_QUOT) + ], + null, + false); + + if ($externalapplication) { + // must call external application in order to get the needed data asynchroneously + // must be of the form + // {"url":"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_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); + + if (isset($externalapplication['ssl_verify'])) { + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $externalapplication['ssl_verify']); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $externalapplication['ssl_verify']); + } + + if (isset($externalapplication['proxy'])) { + curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1 ) ; + curl_setopt($ch, CURLOPT_PROXY, $externalapplication['proxy']); + } + + $response = curl_exec ($ch); + if ($response === false) { + //throw new Exception(curl_error($ch), curl_errno($ch)); + Toolbox::logDebug( curl_error($ch).":".curl_errno($ch) ); + } + + curl_close ($ch); + } + // } + } 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 + JOIN glpi_plugin_processmaker_taskcategories ON glpi_plugin_processmaker_taskcategories.taskcategories_id=glpi_tickettasks.taskcategories_id + JOIN glpi_plugin_processmaker_cases ON glpi_plugin_processmaker_cases.processes_id=glpi_plugin_processmaker_taskcategories.processes_id + RIGHT JOIN glpi_plugin_processmaker_tasks ON glpi_plugin_processmaker_tasks.items_id=glpi_tickettasks.id AND glpi_plugin_processmaker_tasks.case_id=glpi_plugin_processmaker_cases.id + WHERE glpi_plugin_processmaker_taskcategories.pm_task_guid = '".$targetTask['targettask_guid']."' AND glpi_tickettasks.state = 1 AND glpi_tickettasks.tickets_id=".$tlink['tickets_id']; + foreach ($DB->request($query) as $case) { + // must be only one row + + $postdata['APP_UID'] = $case['id']; + $postdata['DEL_INDEX'] = $case['del_index']; + + $cronaction = new PluginProcessmakerCrontaskaction; + $cronaction->add( [ 'plugin_processmaker_caselinks_id' => $targetTask['id'], + 'plugin_processmaker_cases_id' => $locCase->getID(), + //'itemtype' => $itemtype, + //'items_id' => $parm->fields['tickets_id'], + 'users_id' => Session::getLoginUserID(), + 'is_targettoclaim' => $targetTask['is_targettoclaim'], + 'state' => ($targetTask['is_externaldata'] ? PluginProcessmakerCrontaskaction::WAITING_DATA : PluginProcessmakerCrontaskaction::DATA_READY), + 'postdata' => json_encode( $postdata, JSON_HEX_APOS | JSON_HEX_QUOT), + 'logs_out' => json_encode( $externalapplicationparams, JSON_HEX_APOS | JSON_HEX_QUOT) + ], + null, + false); + } + } + } + } + + if ($targetTask['is_synchronous']) { + // must call PluginProcessmakerProcessmaker::cronPMTaskActions() + PluginProcessmakerProcessmaker::cronPMTaskActions(); + } + } + + } + + //$msg .= "================\n"; + //Toolbox::logInFile("processmaker", $msg); + + } +} diff --git a/inc/case.class.php b/inc/case.class.php index 80f886f..9613f25 100644 --- a/inc/case.class.php +++ b/inc/case.class.php @@ -1,1661 +1,1611 @@ -fields['plugin_processmaker_cases_id'] == 0 - && $this->canDeleteItem() - && (self::canDelete() || $this->fields['case_status'] == PluginProcessmakerCase::DRAFT); - } - - static function canCancel() { - return plugin_processmaker_haveRight('case', CANCEL); - } - - /** - * Summary of getTabNameForItem - * @param CommonGLPI $item is the item - * @param mixed $withtemplate has template - * @return array os strings - */ - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - if ($item->getType() == __CLASS__) { - // get tab name for a case itself - $tabname = __('Case', 'processmaker'); - if ($item->fields['plugin_processmaker_cases_id'] > 0) { - // case is a sub-case - $tabname = __('Sub-case', 'processmaker'); - } - return [ 'main' => $tabname." ".self::getStatus($item->fields['case_status']).""]; - } else { - $items_id = $item->getID(); - $itemtype = $item->getType(); - - // count how many cases are on this item - $cnt = count(self::getIDsFromItem($itemtype, $items_id)); - if ($cnt == 0) { - return ['processmakercases' => __('Process case', 'processmaker')]; - } - return ['processmakercases' => _n('Process case', 'Process cases', $cnt, 'processmaker')."$cnt"]; - } - } - - - /** - * Summary of getName - * @param mixed $options - * @return mixed - */ - function getName($options = []) { - return $this->fields['name']; - } - - - /** - * Summary of getIDFromItem - * @param string $itemtype is the item type - * @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; - //} - - - /** - * Summary of getIDsFromItem - * returns an array of the case ids linked to the item - * @param string $itemtype is the item type of the item (Ticket, Problem, Change) - * @param mixed $items_id is the GLPI id of the item in the type - * @return array - */ - static function getIDsFromItem($itemtype, $items_id) { - $ret = []; - $dbu = new DbUtils; - $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; - } - - /** - * Summary of getFromItem - * @param mixed $itemtype is the item type - * @param mixed $items_id is the item id - * @return mixed: returns false when there is no case associated with the item, else fills in the item fields from DB, and returns true - */ - //function getFromItem($itemtype, $items_id) { - // return $this->getFromDBByQuery(" WHERE items_id=$items_id and itemtype='$itemtype'"); - //} - - - /** - * Summary of getFromGUID - * @param mixed $case_guid - * @return boolean - */ - function getFromGUID($case_guid) { - $restrict=[ - 'WHERE' => [ - 'case_guid' => $case_guid, - ], - ]; - return $this->getFromDBByRequest($restrict); - } - - - /** - * Summary of getVariables - * @param mixed $vars - * @return mixed - */ - function getVariables($vars = []) { - global $PM_SOAP; - return $PM_SOAP->getVariables($this->fields['case_guid'], $vars); - } - - - /** - * Summary of sendVariables - * @param mixed $vars - * @return A - */ - function sendVariables($vars = []) { - global $PM_SOAP; - return $PM_SOAP->sendVariables($this->fields['case_guid'], $vars); - } - - - /** - * Summary of getCaseInfo - * @param mixed $delIndex - * @return stdClass, a getCaseInfoResponse object, or false exception occured - */ - function getCaseInfo($delIndex = '') { - global $PM_SOAP; - return $PM_SOAP->getCaseInfo($this->fields['case_guid'], $delIndex); - } - - - /** - * Summary of unpauseCase - * @param mixed $delIndex - * @param mixed $userGuid - * @return an - */ - function unpauseCase($delIndex, $userGuid) { - global $PM_SOAP; - return $PM_SOAP->unpauseCase($this->fields['case_guid'], $delIndex, $userGuid); - } - - - /** - * Summary of unassignCase - * Will unassign the delIndex task, restoring the assigned group - * @param $delIndex int the delegation index - * @param $taskGuid string the GUID of the task - * @param $tasktype string the type of task (TicketTask, ChangeTask, ProblemTask) - * @param $tasks_id int the id of the task - * @param $itemtype string the type of the ITIL object (Ticket, Change, Problem) - * @return bool - */ - function unassignCase($delIndex, $taskGuid, $tasktype, $tasks_id, $itemtype, $options) { - global $PM_DB, $PM_SOAP, $DB; - - // un-claim task - // will unclaim the task - // to unclaim a task, we must un-assign the task in the APP_DELEGATION table - // and un-assign the task in glpi_itemtypeTask table - $groupname = ''; - - // should get the group that is assigned to the task in SELF_SERVICE assign type - $query = "SELECT TAS_GROUP_VARIABLE FROM TASK WHERE TAS_UID='".$taskGuid."' AND TAS_ASSIGN_TYPE='SELF_SERVICE' LIMIT 1;"; - foreach($PM_DB->request($query) as $pmGroup) { - // should have only one record - if ($pmGroup['TAS_GROUP_VARIABLE'] == '') { - // then we are in the self-service with a group in the TASK_USER table - // TU_RELATION=2 is groups and TU_TYPE=1 means normal (= not adhoc) - // then get the group name from the CONTENT table - $query = "SELECT CONTENT.CON_VALUE FROM TASK_USER - JOIN CONTENT ON CONTENT.CON_ID=TASK_USER.USR_UID AND CONTENT.CON_CATEGORY='GRP_TITLE' AND CONTENT.CON_LANG = 'en' - WHERE TASK_USER.TAS_UID='".$taskGuid."' AND TASK_USER.TU_RELATION=2 AND TASK_USER.TU_TYPE=1 LIMIT 1;"; - - foreach ($PM_DB->request($query) as $onlyrec) { - $groupname = $onlyrec['CON_VALUE']; - } - - - } else { - // then we are in the self-service with a case variable that contains either a group either an array of users - // array of users is not yet supported by PM plugin, as GLPI tasks have one and only one users_id_tech. - // group guid (in the case variable) must be retrieved from APP DATA - - // TODO - //////////////////////////////////////////////////////////////// - // Currently this case is not manageable by GLPI - // as GLPI needs at least a user or a group to be assigned to a task - // and when using the self-service value based assignment, there - // is a case variable that contains a list of users. This list of users cannot be mapped to a group in GLI - // OR may be we may create an artificial group in GLPI that would contains the list of users - //////////////////////////////////////////////////////////////// - - // and then we get the name of the group from the CONTENT table - //$query = "SELECT CON_VALUE FROM CONTENT - // WHERE CONTENT.CON_ID='$groupId' AND CONTENT.CON_CATEGORY='GRP_TITLE' AND CONTENT.CON_LANG='en' ;"; - - } - } - - $groups_id_tech = PluginProcessmakerProcessmaker::getGLPIGroupId($groupname); - - if ($groups_id_tech) { - // unclaim the case only when a GLPI group can be found - - $query = "UPDATE APP_DELEGATION SET USR_UID='', DEL_INIT_DATE=NULL, USR_ID=0 WHERE APP_NUMBER=".$this->getID()." AND DEL_INDEX=$delIndex;"; - $PM_DB->query($query); - - $glpi_task = new $tasktype; - $glpi_task->getFromDB($tasks_id); - $foreignkey = getForeignKeyFieldForItemType( $itemtype ); - - $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); // do not send notification yet - $glpi_task->update( ['id' => $glpi_task->getID(), - $foreignkey => $glpi_task->fields[$foreignkey], - 'users_id_tech' => 0, - 'groups_id_tech' => $groups_id_tech, - 'update' => true] ); - PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); - - // send notification now! - $pm_task = new PluginProcessmakerTask($tasktype); - $pm_task->getFromDB($tasks_id); - $glpi_item = new $itemtype; - $glpi_item->getFromDB($glpi_task->fields[$foreignkey]); - $pm_task->sendNotification('task_unclaim', $glpi_task, $glpi_item, $this); - - // create an information task and add comment - $pm_process = $this->getProcess(); - $dbu = new DbUtils; - $info = __('Task un-claimed!
Case: %s
Task: "%s" has been un-assigned from "%s" and assigned to "%s" group.
Reason: %s', 'processmaker'); - $info .= ""; - $taskCat = new TaskCategory; - $taskCat->getFromDB( $glpi_task->fields['taskcategories_id'] ); - $info = sprintf($info, - $this->getNameID(['forceid' => true]), - DropdownTranslation::getTranslatedValue($glpi_task->fields['taskcategories_id'], 'TaskCategory', 'name', $_SESSION['glpilanguage'], $taskCat->fields['name']), - Html::clean($dbu->getUserName(isset($glpi_task->oldvalues['users_id_tech']) ? $glpi_task->oldvalues['users_id_tech'] : 0)), - Html::clean($groupname), - $options['comment'] - ); - // unescape some chars and replace CRLF, CR or LF by
- $info = str_replace(["\\'", '\\"', '\r\n', '\r', '\n'], ["'", '"', '
', '
', '
'], $info); - - $glpi_task->add([$foreignkey => $glpi_task->fields[$foreignkey], - 'is_private' => 0, // a post-only user can't create private task - 'taskcategories_id' => $pm_process->fields['taskcategories_id'], - 'content' => $DB->escape($info), - 'users_id' => $PM_SOAP->taskWriter, - 'state' => Planning::INFO, - 'users_id_tech' => Session::getLoginUserID(), - ]); - - return true; - } - - return false; - } - - - /** - * Summary of reassignCase - * @param mixed $delIndex - * @param mixed $taskGuid - * @param mixed $delThread - * @param mixed $users_id_source - * @param mixed $users_id_target - * @return mixed - */ - function reassignCase($delIndex, $taskGuid, $delThread, $users_id_source, $users_id_target, $options) { - global $PM_SOAP; - $users_guid_source = ''; // by default - if ($users_id_source !== 0) { // when task is not 'to be claimed' - $users_guid_source = PluginProcessmakerUser::getPMUserId($users_id_source); - } - $users_guid_target = PluginProcessmakerUser::getPMUserId($users_id_target); - $pmResponse = $PM_SOAP->reassignCase($this->fields['case_guid'], $delIndex, $users_guid_source, $users_guid_target); - // now should manage GLPI Tasks previously assigned to the $users_guid_source - if ($pmResponse->status_code == 0) { - // we need to change the delindex of the glpi task and the assigned tech to prevent creation of new tasks - // we need the delindex of the current glpi task, and the delindex of the new one - // search for new delIndex and new delThread - $newCaseInfo = $this->getCaseInfo( ); - $newDelIndex = 0; - $newDelThread = 0; - foreach ($newCaseInfo->currentUsers as $newCaseUser) { - if ($newCaseUser->taskId == $taskGuid && $newCaseUser->delThread == $delThread) { - $newDelIndex = $newCaseUser->delIndex; - $newDelThread = $newCaseUser->delThread; - break; - } - } - $this->reassignTask($delIndex, $newDelIndex, $delThread, $newDelThread, $users_id_target, $options); - return true; - } - return false; - } - - - /** - * Summary of reassignTask - * @param mixed $delIndex - * @param mixed $newDelIndex - * @param mixed $newTech - */ - public function reassignTask ($delIndex, $newDelIndex, $delThread, $newDelThread, $newTech, $options) { - global $DB, $PM_SOAP; - - $dbu = new DbUtils; - $pm_task_row = $dbu->getAllDataFromTable(PluginProcessmakerTask::getTable(), ['plugin_processmaker_cases_id' => $this->getID(), 'del_index' => $delIndex, 'del_thread' => $delThread]); - if ($pm_task_row && count($pm_task_row) == 1) { - $pm_task_row = array_shift($pm_task_row); - $glpi_task = new $pm_task_row['itemtype']; - $glpi_task->getFromDB($pm_task_row['items_id']); - - $itilobject_itemtype = $this->fields['itemtype']; - $foreignkey = getForeignKeyFieldForItemType( $itilobject_itemtype ); - - PluginProcessmakerProcessmaker::addWatcher( $itilobject_itemtype, $glpi_task->fields[ $foreignkey ], $newTech ); - - $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); // do not send notification yet - $glpi_task->update( ['id' => $glpi_task->getID(), - $foreignkey => $glpi_task->fields[$foreignkey], - 'users_id_tech' => $newTech, - 'groups_id_tech' => 0, - 'update' => true] ); - PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); - - // then update the delIndex and delThread - $DB->Update( 'glpi_plugin_processmaker_tasks', [ - 'del_index' => $newDelIndex, - 'del_thread' => $newDelThread - ], [ - 'id' => $pm_task_row['id'] - ] - ); - - // send notification now! - $pm_task = new PluginProcessmakerTask($pm_task_row['itemtype']); - $pm_task->getFromDB($pm_task_row['items_id']); - $glpi_item = new $itilobject_itemtype; - $glpi_item->getFromDB($glpi_task->fields[$foreignkey]); - $pm_task->sendNotification('task_reassign', $glpi_task, $glpi_item, $this); - - // create an information task and add comment - $pm_process = $this->getProcess(); - $old_users_tech_id = isset($glpi_task->oldvalues['users_id_tech']) ? $glpi_task->oldvalues['users_id_tech'] : 0; - $taskCat = new TaskCategory; - $taskCat->getFromDB( $glpi_task->fields['taskcategories_id'] ); - $task_name = DropdownTranslation::getTranslatedValue($glpi_task->fields['taskcategories_id'], 'TaskCategory', 'name', $_SESSION['glpilanguage'], $taskCat->fields['name']); - $new_tech_name = Html::clean($dbu->getUserName($newTech)); - if ($old_users_tech_id) { - $info = __('Task re-assigned!
Case: %s
Task: "%s" has been re-assigned from "%s" to "%s".
Reason: %s', 'processmaker'); - $info = sprintf($info, - $this->getNameID(['forceid' => true]), - $task_name, - Html::clean($dbu->getUserName(isset($glpi_task->oldvalues['users_id_tech']) ? $glpi_task->oldvalues['users_id_tech'] : 0)), - $new_tech_name, - $options['comment'] - ); - } else { - $info = __('Task assigned!
Case: %s
Task: "%s" has been assigned to "%s".
Reason: %s', 'processmaker'); - $info = sprintf($info, - $this->getNameID(['forceid' => true]), - $task_name, - $new_tech_name, - $options['comment'] - ); - } - $info .= ""; - - // unescape some chars and replace CRLF, CR or LF by
- $info = str_replace(["\\'", '\\"', '\r\n', '\r', '\n'], ["'", '"', '
', '
', '
'], $info); - - $glpi_task->add([$foreignkey => $glpi_task->fields[$foreignkey], - 'is_private' => 0, // a post-only user can't create private task - 'taskcategories_id' => $pm_process->fields['taskcategories_id'], - 'content' => $DB->escape($info), - 'users_id' => $PM_SOAP->taskWriter, - 'state' => Planning::INFO, - 'users_id_tech' => Session::getLoginUserID(), - ]); - } - } - - - /** - * Summary of getProcess - * Returns process object - * @return bool|PluginProcessmakerProcess - */ - function getProcess() { - $pm_process = new PluginProcessmakerProcess; - if (!$this->process && $pm_process->getFromDB($this->fields['plugin_processmaker_processes_id'])) { - $this->process = $pm_process; - } - return $this->process; - } - - /** - * Summary of showCaseProperties - */ - function showCaseProperties() { - global $DB, $PM_DB; - - // get all tasks that are OPEN for any sub-case of this case - $case_tasks = []; - $res = $DB->request('glpi_plugin_processmaker_tasks', [ - 'AND' => [ - 'plugin_processmaker_cases_id' => $this->getID(), - 'del_thread_status' => 'OPEN' - ] - ]); - foreach ($res as $task) { - $case_tasks[$task['del_index']] = $task; - } - //$query = "SELECT `glpi_plugin_processmaker_tasks`.* FROM `glpi_plugin_processmaker_tasks` - // WHERE `glpi_plugin_processmaker_tasks`.`plugin_processmaker_cases_id`={$this->getID()} AND `del_thread_status`='OPEN'"; - //foreach ($DB->request($query) as $task) { - // $case_tasks[$task['del_index']] = $task; - //} - - //// get all tasks that are OPEN for any sub-case of this case - //$sub_cases = []; - //$query = "SELECT `glpi_plugin_processmaker_tasks`.* FROM `glpi_plugin_processmaker_tasks` - // JOIN `glpi_plugin_processmaker_cases` on `glpi_plugin_processmaker_cases`.`id`=`glpi_plugin_processmaker_tasks`.`plugin_processmaker_cases_id` - // WHERE `glpi_plugin_processmaker_cases`.`plugin_processmaker_cases_id`={$this->getID()} AND `del_thread_status`='OPEN'"; - //foreach($DB->request($query) as $task) { - // $sub_cases[$task['plugin_processmaker_cases_id']][$task['del_index']] = $task; - //} - - $caseInfo = $this->getCaseInfo(); - if (property_exists($caseInfo, 'currentUsers')) { - $caseInfo->currentUsers = $this->sortTasks($caseInfo->currentUsers, PluginProcessmakerUser::getPMUserId(Session::getLoginUserID())); - } - $res = $PM_DB->request([ - 'SELECT' => ['DEL_INDEX', 'DEL_DELEGATE_DATE'], - 'FROM' => 'APP_DELEGATION', - 'WHERE' => ['APP_UID' => $caseInfo->caseId] - ]); - //$query = "SELECT `DEL_INDEX`, `DEL_DELEGATE_DATE` FROM `APP_DELEGATION` WHERE `APP_UID`='{$caseInfo->caseId}'"; - $tasks = []; - foreach ($res as $row) { - $tasks[$row['DEL_INDEX']] = $row['DEL_DELEGATE_DATE']; - } - //foreach ($PM_DB->request($query) as $row) { - // $tasks[$row['DEL_INDEX']] = $row['DEL_DELEGATE_DATE']; - //} - - echo "

"; - // show the case properties like given by PM server - $this->showShort($caseInfo); - - // show current (running) tasks properties - echo "

"; - - echo "
"; - echo ""; - - echo ""; - - if (property_exists($caseInfo, 'currentUsers') && count($caseInfo->currentUsers) > 0) { - echo " - - - - - "; - foreach ($caseInfo->currentUsers as $currentTask) { - $case_url = $this->getLinkURL().'&forcetab=PluginProcessmakerTask$'; - echo ""; - if (isset($case_tasks[$currentTask->delIndex])) { - $case_url .= $case_tasks[$currentTask->delIndex]['id']; - echo ""; - } else { - $res = $PM_DB->request([ - 'SELECT' => 'APP_UID', - 'FROM' => 'SUB_APPLICATION', - 'WHERE' => [ - 'AND' => [ - 'APP_PARENT' => $this->fields['case_guid'], - 'DEL_INDEX_PARENT' => $currentTask->delIndex, - 'SA_STATUS' => 'ACTIVE' - ] - ] - ]); - //$res = $PM_DB->query("SELECT APP_UID FROM SUB_APPLICATION WHERE APP_PARENT='{$this->fields['case_guid']}' AND DEL_INDEX_PARENT={$currentTask->delIndex} AND SA_STATUS='ACTIVE'"); - //if ($res && $PM_DB->numrows($res) == 1) { - // $row = $PM_DB->fetch_assoc($res); - if ($res->numrows() == 1 && $row = $res->next()) { - $sub_case = new PluginProcessmakerCase; - $sub_case->getFromGUID($row['APP_UID']); - $case_url .= $sub_case->getID()."-".$currentTask->delIndex; - echo ""; - } else { - echo ""; - } - } - echo ""; - if ($currentTask->userName == '') { - echo ""; - } else { - echo ""; - } - echo ""; - echo ""; - } - } else { - echo ""; - } - - echo "
".__('Current task(s) properties', 'processmaker')."
".__('Task', 'processmaker')."".__('Task guid', 'processmaker')."".__('Current user', 'processmaker')."".__('Task delegation date', 'processmaker')."
".$currentTask->taskName."> ".$currentTask->taskName."".$currentTask->taskName."".$currentTask->taskId."".__('To be claimed', 'processmaker')."".$currentTask->userName."".Html::convDateTime($tasks[$currentTask->delIndex])."
".__('None')."
"; - - echo "
"; - - // show the parent case if it's a sub-case - if ($this->fields['plugin_processmaker_cases_id'] > 0) { - echo "

"; - $sub_case = new self; - $sub_case->getFromDB($this->fields['plugin_processmaker_cases_id']); - $sub_case->showShort($sub_case->getCaseInfo(), true); - } - - } - - /** - * Summary of showShort - * @param mixed $caseInfo - * @param mixed $showparenturl - */ - function showShort($caseInfo, $showparenturl = false) { - - echo "
"; - echo ""; - - if ($this->fields['plugin_processmaker_cases_id'] > 0) { - echo ""; - } else { - if ($showparenturl) { - echo ""; - } else { - echo ""; - } - } - - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - //echo ""; - echo ""; - - echo ""; - echo ""; - if ($showparenturl) { - echo ""; - } else { - echo ""; - } - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - //echo ""; - echo ""; - - echo "
".__('Sub-case properties', 'processmaker')."
".__('Parent case properties', 'processmaker')."
".__('Case properties', 'processmaker')."
".__('Process', 'processmaker')."".__('Case title', 'processmaker')."".__('Case number', 'processmaker')."".__('Case status', 'processmaker')."".__('Case guid', 'processmaker')."".__('Creator', 'processmaker')."".__('Creation date', 'processmaker')."".__('Last update', 'processmaker')."".__('Case description', 'processmaker')."
".$caseInfo->processName."".$this->getLink()."".$caseInfo->caseName."".$caseInfo->caseNumber."".self::getStatus($caseInfo->caseStatus)."".$caseInfo->caseId."".$caseInfo->caseCreatorUserName."".Html::convDateTime($caseInfo->createDate)."".Html::convDateTime($caseInfo->updateDate)."".$caseInfo->????."
"; - - echo "
"; - - } - - - /** - * Summary of localSortTasks - * used to sort array of tasks in a currenUsers object - * @param mixed $a - * @param mixed $b - * @return integer - */ - static private function localSortTasks ($a, $b) { - return $a->delIndex - $b->delIndex; - } - - /** - * Summary of sortTasks - * @param mixed $tasks is the array of tasks from a getCaseInfo->currentUsers - * @param mixed $GLPICurrentPMUserId - * @return array sorted $tasks - */ - public function sortTasks($tasks, $GLPICurrentPMUserId) { - - $tbctasks = []; - $utasks = []; - $infotasks = []; - - foreach ($tasks as $caseUser) { - if ($caseUser->userId == $GLPICurrentPMUserId) { - $utasks[] = $caseUser; - } else { - if ($caseUser->userId == '') { // task to be claimed - $tbctasks[] = $caseUser; - } else { - $infotasks[] = $caseUser; - } - } - } - - // order task by "current user", then by "to be claimed", and then push to end "tasks assigned to another user" - // then by delindex ASC in these three parts - usort($utasks, 'self::localSortTasks'); - usort($tbctasks, 'self::localSortTasks'); - usort($infotasks, 'self::localSortTasks'); - - return array_merge($utasks, $tbctasks, $infotasks); - } - - - /** - * Summary of showCaseInfoTab - * Will show information about the current case - * @param CommonGLPI $case is a PluginProcessmakerCase object - * @param mixed $tabnum - * @param mixed $withtemplate - */ - 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.'; - $itemtype = $case->fields['itemtype']; - - $maintitle = __('Case is linked to a %1s', 'processmaker'); - if ($case->fields['plugin_processmaker_cases_id'] > 0) { - $maintitle = __('Sub-case is linked to a %1s', 'processmaker'); - } - - echo "".sprintf($maintitle, $itemtype::getTypeName(1)).""; - - Ticket::commonListHeader(Search::HTML_OUTPUT); - - $itemtype::showShort($case->fields['items_id']); - - echo ""; - - // show case properties - $case->showCaseProperties(); - - if ($case->fields['plugin_processmaker_cases_id'] == 0 && self::canCancel() && $case->fields['case_status'] == self::TO_DO) { - - // it's a main case, not a sub-case - // and we have the rights to cancel cases - - echo "

"; - echo ""; - echo ""; - echo ""; - echo "
".__('Case cancellation', 'processmaker')."
".__('Cancel case', 'processmaker').""; - echo ""; - echo ""; - echo ""; - echo "
"; - - } - - // 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->canPurgeItem($case->getID())) { - - // then propose a button to delete case - // the button will be effectively shown by the showFormButtons() - - echo "

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

"; - - } - - return; - } - - - /** - * Summary of showForItem - * Shows list of cases attached to an item - * @param CommonITILObject $item - */ - static function showForItem(CommonITILObject $item) { - global $DB, $CFG_GLPI, $PM_SOAP; - - $items_id = $item->getField('id'); - $itemtype = $item->getType(); - //if (!Session::haveRight("problem", Problem::READALL) - // || !$item->can($ID, READ)) { - - // return false; - //} - - $canupdate = $item->can($items_id, UPDATE); - - $rand = mt_rand(); - $res = $DB->request([ - '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' => [ - 'FKEY' => [ - 'gppp' => 'id', - 'gppc' => 'plugin_processmaker_processes_id'] - ] - ], - 'WHERE' => [ - 'AND' => [ - 'gppc.itemtype' => $itemtype, - 'gppc.items_id' => $items_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' - // AND gppc.`items_id` = $items_id - // "; - //$result = $DB->query($query); - - $cases = []; - $used = []; - $pid = []; - if ($numrows = $res->numrows()) { - foreach ($res as $data) { - $cases[$data['id']] = $data; - $used[$data['id']] = $data['id']; - if (isset($pid[$data['pid']])) { - $pid[$data['pid']] += 1; - } else { - $pid[$data['pid']] = 1; - } - } - } - //if ($numrows = $DB->numrows($result)) { - // while ($data = $DB->fetch_assoc($result)) { - // $cases[$data['id']] = $data; - // $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') - ]; - - // check if item is not solved nor closed - if ($canupdate - && $item->fields['status'] != CommonITILObject::SOLVED - && $item->fields['status'] != CommonITILObject::CLOSED - && $_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 ""; - echo ""; - echo ""; - - echo ""; - echo ""; - - echo "
".__('Add a new case', 'processmaker')."
"; - echo __('Select the process you want to add', 'processmaker'); - echo ""; - $condition['is_active'] = 1; - if ($itemtype == 'Ticket' && $item->fields['type'] == Ticket::INCIDENT_TYPE) { - $condition['is_incident'] = 1; - } else if ($itemtype == 'Ticket' && $item->fields['type'] == Ticket::DEMAND_TYPE) { - $condition['is_request'] = 1; - } else { - $condition['is_'.strtolower($itemtype)] = 1; - //$is_itemtype = "AND is_".strtolower($itemtype)."=1"; - } - PluginProcessmakerProcess::dropdown(['value' => 0, - 'entity' => $item->fields['entities_id'], - 'name' => 'plugin_processmaker_processes_id', - //'condition' => "is_active=1 $is_itemtype", - 'condition' => $condition, - 'specific_tags' => ['count_cases_per_item' => $pid] - ]); - echo ""; - echo ""; - echo "
"; - Html::closeForm(); - echo "
"; - } - - echo "
"; - if ($canupdate && $numrows) { - Html::openMassiveActionsForm('mass'.__CLASS__.$rand); - $massiveactionparams = ['num_displayed' => $numrows, - 'container' => 'mass'.__CLASS__.$rand]; - Html::showMassiveActions($massiveactionparams); - } - echo ""; - echo ""; - echo ""; - if ($numrows) { - $header_begin = ""; - $header_top = ''; - $header_bottom = ''; - $header_end = ''; - if ($canupdate - && $numrows) { - $header_top .= ""; - $header_bottom .= ""; - } - - foreach ($columns as $key => $val) { - $header_end .= ""; - } - - $header_end .= ""; - echo $header_begin.$header_top.$header_end; - - //Session::initNavigateListItems('PluginProcessmakerCase', - // //TRANS : %1$s is the itemtype name, - // // %2$s is the name of the item (used for headings of a list) - // sprintf(__('%1$s = %2$s'), - // $itemtype::getTypeName(1), $item->fields["name"])); - - $i = 0; - foreach ($cases as $data) { - Session::addToNavigateListItems('PluginProcessmakerCase', $data["id"]); - $link = NOT_AVAILABLE; - $case = new self; - if ($case->getFromDB($data["id"])) { - $link = $case->getLink(); - } - - echo ""; - if ($canupdate) { - echo ""; - } - echo ""; - echo ""; - echo ""; - echo ""; - //echo ""; - echo ""; - - $i++; - } - echo $header_begin.$header_top.$header_end; - - } - - echo "
".PluginProcessmakerCase::getTypeName($numrows)."
".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); - $header_top .= "".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); - $header_bottom .= "$val
"; - // prevent massiveaction on subprocess - if ($data['plugin_processmaker_cases_id'] == 0) { - Html::showMassiveActionCheckBox(__CLASS__, $data["assocID"]); - } - echo "".$data['pname']."".$link."".self::getStatus($data['case_status']).""; - if ($data['plugin_processmaker_cases_id'] > 0) { - // then this is a subprocess of - $maincase = new self; - if ($maincase->getFromDB($data['plugin_processmaker_cases_id'])) { - echo $maincase->getLink(); - } - } else { - echo '-'; - } - echo "".Html::convDateTime($data["date_creation"])."
"; - if ($canupdate && $numrows) { - $massiveactionparams['ontop'] = false; - Html::showMassiveActions($massiveactionparams); - Html::closeForm(); - } - echo "
"; - } - - /** - * Summary of displayTabContentForItem - * @param CommonGLPI $item - * @param mixed $tabnum - * @param mixed $withtemplate - */ - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - global $PM_SOAP; - - if ($item->getType() == __CLASS__) { - // we are in a case viewing the main tab - // the 'Case infos' tab - //self::showCaseInfoTab($item, $tabnum, $withtemplate); - - } else { - - // show the list of cases attached to the $item ITIL object - if (!$PM_SOAP->config->fields['maintenance']) { - self::showForItem($item); - } else { - PluginProcessmakerProcessmaker::showUnderMaintenance(); - } - } - } - - - /** - * Summary of deleteTasks - * will delete all tasks associated with this case from the item - * @return true if tasks have been deleted from associated item and from case table - */ - private function deleteTasks() { - global $DB; - $ret = false; - $sub = new QuerySubQuery([ - 'SELECT' => 'items_id', - 'FROM' => 'glpi_plugin_processmaker_tasks', - 'WHERE' => ['plugin_processmaker_cases_id' => $this->fields['id']] - ]); - - if ($DB->delete('glpi_'.strtolower($this->fields['itemtype']).'tasks', ['id' => $sub ])) { - if ($DB->delete('glpi_plugin_processmaker_tasks', ['plugin_processmaker_cases_id' => $this->fields['id']])) { - $ret = true; - } - } - //$query = "DELETE FROM glpi_".strtolower($this->fields['itemtype'])."tasks WHERE id IN (SELECT items_id FROM glpi_plugin_processmaker_tasks WHERE plugin_processmaker_cases_id='".$this->fields['id']."')"; - //if ($DB->query( $query )) { - // $query = "DELETE FROM glpi_plugin_processmaker_tasks WHERE plugin_processmaker_cases_id='".$this->fields['id']."'"; - // if ($DB->query( $query )) { - // $ret = true; - // } - //} - return $ret; - } - - - /** - * Summary of deleteCase - * will delete case and all tasks associated with this case from the item - * @return true if case and tasks have been deleted from associated item and from case table - */ - function deleteCase() { - return $this->delete(['id' => $this->getID()]); - } - - - /** - * Summary of cancelTasks - * will mark as information all to_do tasks - * BEWARE that this will only be done when case is in TO_DO status - * @return true if tasks have been deleted from associated item and from case table - */ - private function cancelTasks() { - global $DB; - $ret = false; - - if (isset($this->fields['case_status']) && $this->fields['case_status'] == "TO_DO") { - $sub = new QuerySubQuery([ - 'SELECT' => 'items_id', - 'FROM' => 'glpi_plugin_processmaker_tasks', - 'WHERE' => ['plugin_processmaker_cases_id' => $this->fields['id']] - ]); - $res = $DB->update('glpi_'.$this->fields['itemtype'].'tasks', [ - 'state' => 0, - 'users_id_tech' => 0, - 'groups_id_tech' => 0, - 'begin' => null, - 'end' => null - ], [ - 'AND' => [ - 'state' => 1, - 'id' => $sub - ] - ]); - if ($res) { - $ret = true; - } - //$query = "UPDATE glpi_".$this->fields['itemtype']."tasks SET state=0,users_id_tech=0,begin=NULL,end=NULL WHERE state=1 AND id in (select items_id from glpi_plugin_processmaker_tasks where plugin_processmaker_cases_id='".$this->fields['id']."')"; - //if ($DB->query( $query )) { - // $ret = true; - //} - } - return $ret; - } - - - - /** - * Summary of cancelCase - * will cancel case and mark 'to_do' tasks associated with this case from the item as information - * BEWARE that this will only be done when case is in TO_DO status - * @return true if case and tasks have been cancelled or marked from associated item and from case table - */ - function cancelCase() { - global $DB; - $ret = false; - - if (isset($this->fields['case_status']) && $this->fields['case_status'] == "TO_DO") { - if ($this->cancelTasks()) { - if ($this->update( [ 'id' => $this->getID(), 'case_status' => 'CANCELLED' ] )) { - $ret=true; - } - } - } - - return $ret; - } - - /** - * Summary of canSolve - * To know if a Ticket (Problem or Change) can be solved - * i.e. the case permits solving of item - * @param mixed $param is an array containing the item - * @return bool true to permit solve, false otherwise - */ - public static function canSolve ($param) { - $item = $param['item']; - $cases = self::getIDsFromItem($item->getType(), $item->getID()); - foreach ($cases as $cases_id) { - $myCase = new self; - if ($myCase->getFromDB($cases_id)) { - $pmVar = $myCase->getVariables(['GLPI_ITEM_CAN_BE_SOLVED']); - if ($myCase->fields['case_status'] != self::COMPLETED - && $myCase->fields['case_status'] != self::CANCELLED - && (!isset($pmVar['GLPI_ITEM_CAN_BE_SOLVED']) || $pmVar['GLPI_ITEM_CAN_BE_SOLVED'] != 1)) { - // then item can't be solved - return false; - } - } - } - return true; - } - - /** - * Summary of getToDoTasks - * @param mixed $item is a Ticket, a Problem or a Change - * @return array list of tasks with status 'to do' for case associated with item - */ - public static function getToDoTasks($item) { - $ret = []; - - $cases = self::getIDsFromItem($item->getType(), $item->getID()); - foreach ($cases as $cases_id) { - $ret = $ret + PluginProcessmakerTask::getToDoTasks($cases_id, $item->getType()."Task"); - } - - return $ret; - } - - - /** - * Summary of getMenuContent - * @return array - */ - static function getMenuContent() { - - //if (!Session::haveRightsOr('plugin_processmaker_config', [READ, UPDATE])) { - // return; - //} - - $front_page = "/plugins/processmaker/front"; - $menu = []; - $menu['title'] = self::getTypeName(Session::getPluralNumber()); - $menu['page'] = "$front_page/case.php"; - $menu['links']['search'] = PluginProcessmakerCase::getSearchURL(false); - if (Session::haveRightsOr("config", [READ, UPDATE])) { - $menu['links']['config'] = PluginProcessmakerConfig::getFormURL(false); - } - - $itemtypes = [ - 'PluginProcessmakerCase' => 'cases' - ]; - - foreach ($itemtypes as $itemtype => $option) { - //$menu['options'][$option]['title'] = $itemtype::getTypeName(Session::getPluralNumber()); - $menu['options'][$option]['page'] = $itemtype::getSearchURL(false); - $menu['options'][$option]['links']['search'] = $itemtype::getSearchURL(false); - if (Session::haveRightsOr("config", [READ, UPDATE])) { - $menu['options'][$option]['links']['config'] = PluginProcessmakerConfig::getFormURL(false); - } - switch ($itemtype) { - case 'PluginProcessmakerCase': - //if ($itemtype::canCreate()) { - //$menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); - //} - break; - default : - $menu['options'][$option]['page'] = PluginProcessmakerProcess::getSearchURL(false); - break; - } - - } - return $menu; - } - - /** - * Summary of getSpecificValueToDisplay - * @param mixed $field - * @param mixed $values - * @param array $options - * @return mixed - */ - static function getSpecificValueToDisplay($field, $values, array $options = []) { - global $PM_DB; - if (!is_array($values)) { - $values = [$field => $values]; - } - switch ($field) { - case 'id': - if (isset($options['searchopt']['processmaker_cases'])) { - switch ($options['searchopt']['processmaker_cases']) { - case 'creation_date': - $res = $PM_DB->request('APPLICATION', [ - 'APP_NUMBER' => $values['id'] - ] - ); - if ($row = $res->next()) { - return Html::convDateTime($row['APP_CREATE_DATE']); - } - //$res = $PM_DB->query('SELECT * FROM APPLICATION WHERE APP_NUMBER = '.$values['id']); - //if ($res->num_rows > 0) { - // $row = $PM_DB->fetch_assoc($res); - // return Html::convDateTime($row['APP_CREATE_DATE']); - //} - //$locCase = new self; - //$locCase->getFromDB($values['id']); - //$caseInfo = $locCase->getCaseInfo(); - //return Html::convDateTime($caseInfo->createDate); - break; - case 'update_date': - $res = $PM_DB->request('APPLICATION', [ - 'APP_NUMBER' => $values['id'] - ] - ); - if ($row = $res->next()) { - return Html::convDateTime($row['APP_UPDATE_DATE']); - } - //$res = $PM_DB->query('SELECT * FROM APPLICATION WHERE APP_NUMBER = '.$values['id']); - //if ($res->num_rows > 0) { - // $row = $PM_DB->fetch_assoc($res); - // return Html::convDateTime($row['APP_UPDATE_DATE']); - //} - //$locCase = new self; - //$locCase->getFromDB($values['id']); - //$caseInfo = $locCase->getCaseInfo(); - //return Html::convDateTime($caseInfo->updateDate); - break; - } - } - return '-'; - case 'items_id': - // show an item link - $item = new $values['itemtype']; - $item->getFromDB($values['items_id']); - return $item->getLink(['forceid' => 1]); - - case 'case_status': - return self::getStatus($values['case_status']); - - case 'itemtype': - return self::getItemtype($values['itemtype']); - - case 'plugin_processmaker_processes_id': - $item = new PluginProcessmakerProcess; - $item->getFromDB($values['plugin_processmaker_processes_id']); - return $item->getLink(); - - case 'plugin_processmaker_cases_id': - if ($values['plugin_processmaker_cases_id'] != 0) { - $locSCase = new self; - $locSCase->getFromDB($values['plugin_processmaker_cases_id']); - return $locSCase->getLink(['forceid' => 1]); - } - return '-'; - - default: - return parent::getSpecificValueToDisplay($field, $values, $options); - } - } - - - static function getSpecificValueToSelect($field, $name = '', $values = '', array $options = []) { - - if (!is_array($values)) { - $values = [$field => $values]; - } - $options['display'] = false; - - switch ($field) { - case 'case_status': - $options['name'] = $name; - $options['value'] = $values[$field]; - return self::dropdownStatus($options); - case 'itemtype': - $options['name'] = $name; - $options['value'] = $values[$field]; - return self::dropdownItemtype($options); - case 'plugin_processmaker_processes_id': - $options['name'] = $name; - $options['value'] = $values[$field]; - $options['specific_tags'] = ['process_restrict' => 0]; - return PluginProcessmakerProcess::dropdown($options); - - default: - return parent::getSpecificValueToSelect($field, $name, $values, $options); - } - } - - - static function dropdownStatus(array $options = []) { - - $p['name'] = 'case_status'; - $p['value'] = self::TO_DO; - $p['showtype'] = 'normal'; - $p['display'] = true; - - if (is_array($options) && count($options)) { - foreach ($options as $key => $val) { - $p[$key] = $val; - } - } - - switch ($p['showtype']) { - //case 'allowed' : - // $tab = static::getAllowedStatusArray($p['value']); - // break; - - case 'search' : - $tab = static::getAllStatusArray(true); - break; - - default : - $tab = static::getAllStatusArray(false); - break; - } - - return Dropdown::showFromArray($p['name'], $tab, $p); - } - - - static function getAllStatusArray($withmetaforsearch = false) { - - $tab = [self::DRAFT => _x('case_status', 'Draft', 'processmaker'), - self::TO_DO => _x('case_status', 'To do', 'processmaker'), - self::COMPLETED => _x('case_status', 'Completed', 'processmaker'), - self::CANCELLED => _x('case_status', 'Cancelled', 'processmaker')]; - - return $tab; - } - - static function getStatus($value) { - - $tab = static::getAllStatusArray(true); - // Return $value if not defined - return (isset($tab[$value]) ? $tab[$value] : $value); - } - - static function dropdownItemtype(array $options = []) { - - $p['name'] = 'itemtype'; - $p['value'] = 'Ticket'; - $p['showtype'] = 'normal'; - $p['display'] = true; - - if (is_array($options) && count($options)) { - foreach ($options as $key => $val) { - $p[$key] = $val; - } - } - - switch ($p['showtype']) { - //case 'allowed' : - // $tab = static::getAllowedStatusArray($p['value']); - // break; - - case 'search' : - $tab = static::getAllItemtypeArray(true); - break; - - default : - $tab = static::getAllItemtypeArray(false); - break; - } - - return Dropdown::showFromArray($p['name'], $tab, $p); - } - - - static function getAllItemtypeArray($withmetaforsearch = false) { - - $tab = ['Change' => Change::getTypeName(1), - 'Ticket' => Ticket::getTypeName(1), - 'Problem' => Problem::getTypeName(1) - ]; - - return $tab; - } - - - static function getItemtype($value) { - $tab = static::getAllItemtypeArray(true); - // Return $value if not defined - return (isset($tab[$value]) ? $tab[$value] : $value); - } - - - /** - * Get default values to search engine to override - **/ - static function getDefaultSearchRequest() { - - $search = ['sort' => 1, - 'order' => 'DESC']; - - return $search; - } - - - /** - * Summary of rawSearchOptions - * @return mixed - */ - function rawSearchOptions() { - $tab = []; - - $tab[] = [ - 'id' => 'common', - 'name' => __('Process cases', 'processmaker') - ]; - - $tab[] = [ - 'id' => '1', - 'table' => $this->getTable(), - 'field' => 'id', - 'name' => __('ID'), - 'datatype' => 'number', - 'searchtype' => 'contains', - 'massiveaction' => false - ]; - - $tab[] = [ - 'id' => '2', - 'table' => $this->getTable(), - 'field' => 'name', - 'name' => __('Title'), - 'datatype' => 'itemlink', - 'searchtype' => 'contains', - '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[] = [ - 'id' => '7', - 'table' => $this->getTable(), - 'field' => 'itemtype', - 'name' => __('Item type'), - 'massiveaction' => false, - 'datatype' => 'specific', - 'searchtype' => [ - '0' => 'contains', - '1' => 'equals', - '2' => 'notequals' - ] - ]; - - $tab[] = [ - 'id' => '8', - 'table' => $this->getTable(), - 'field' => 'items_id', - 'name' => __('Item'), - 'massiveaction' => false, - 'datatype' => 'specific', - 'additionalfields' => [ - '0' => 'itemtype' - ] - ]; - - $tab[] = [ - 'id' => '9', - 'table' => 'glpi_entities', - 'field' => 'name', - 'name' => __('Item entity', 'processmaker'), - 'massiveaction' => false, - 'datatype' => 'itemlink' - ]; - - $tab[] = [ - 'id' => '10', - 'table' => $this->getTable(), - 'field' => 'case_status', - 'name' => __('Status'), - 'datatype' => 'specific', - 'searchtype' => [ - '0' => 'contains', - '1' => 'equals', - '2' => 'notequals' - ], - 'massiveaction' => false - ]; - - $tab[] = [ - 'id' => '14', - 'table' => $this->getTable(), - 'field' => 'plugin_processmaker_cases_id', - 'name' => __('Sub-case of', 'processmaker'), - 'datatype' => 'specific', - 'massiveaction' => false, - 'nosearch' => true - ]; - - $tab[] = [ - 'id' => '16', - 'table' => $this->getTable(), - 'field' => 'id', - 'name' => __('Creation date'), - 'datatype' => 'specific', - 'massiveaction' => false, - 'nosearch' => true, - 'processmaker_cases' => 'creation_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]) { - $options['colspan'] = 6; - $options['formtitle'] = sprintf( __('Case status is \'%s\'', 'processmaker'), self::getStatus($this->fields['case_status'])); - - $this->showFormHeader($options); - - $process = new PluginProcessmakerProcess; - $process->getFromDB($this->fields['plugin_processmaker_processes_id']); - - if ($process->fields['maintenance']) { - PluginProcessmakerProcess::showUnderMaintenance($process->fields['name'], 'small'); - } - self::showCaseInfoTab($this); - - //echo '
' ; - - Html::closeForm(); - $options['candel'] = true; - $this->showFormButtons($options); - - echo Html::scriptBlock(" - $('#tabsbody th').css('text-align', 'center'); - $('#tabsbody td').css('text-align', 'center'); - "); - } - - - /** - * Summary of defineTabs - * @param mixed $options - * @return array - */ - function defineTabs($options = []) { - - $process = new PluginProcessmakerProcess; - $process->getFromDB($this->fields['plugin_processmaker_processes_id']); - - $ong = []; - if (self::isLayoutWithMain()) { - $this->addDefaultFormTab($ong); - } - - if (!$process->fields['maintenance']) { - $this->addStandardTab('PluginProcessmakerTask', $ong, $options); - } - - if (!self::isLayoutWithMain()) { - $this->addStandardTab(__CLASS__, $ong, $options); - } - - if (!$process->fields['maintenance']) { - $this->addStandardTab('PluginProcessmakerCasemap', $ong, $options); - - $this->addStandardTab('PluginProcessmakerCasehistory', $ong, $options); - - $this->addStandardTab('PluginProcessmakerCasechangelog', $ong, $options); - - $this->addStandardTab('PluginProcessmakerCasedynaform', $ong, $options); - } - - return $ong; - } - - /** - * Actions done after the PURGE of the item in the database - * - * @return nothing - **/ - - /** - * Summary of post_purgeItem - * Actions done after the PURGE of the item in the database - * Will purge the tasks and the PM case and recursively the sub-cases if any - * @return boolean|integer - */ - function post_purgeItem() { - global $PM_SOAP; - $ret = false; - - $PM_SOAP->login(true); - if ($this->deleteTasks() && $this->deleteCronTaskActions() && $PM_SOAP->deleteCase($this->fields['case_guid'])->status_code == 0) { - $ret = true; - $dbu = new DbUtils; - // then must delete any sub-processes (sub-cases) - $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']]); - } - } - return $ret; - } - - - /** - * Summary of deleteCronTaskActions - * Will delete any cron task actions taht are linked to current case - */ - function deleteCronTaskActions() { - global $DB; - - return $DB->delete('glpi_plugin_processmaker_crontaskactions', [ - 'plugin_processmaker_cases_id' => $this->getID() - ] - ); - //$query = "DELETE FROM `glpi_plugin_processmaker_crontaskactions` WHERE `plugin_processmaker_cases_id` = ".$this->getID(); - //return $DB->query($query); - } - -} +fields['plugin_processmaker_cases_id'] == 0 + && $this->canDeleteItem() + && (self::canDelete() || $this->fields['case_status'] == PluginProcessmakerCase::DRAFT); + } + + static function canCancel() { + return plugin_processmaker_haveRight('case', CANCEL); + } + + /** + * Summary of getTabNameForItem + * @param CommonGLPI $item is the item + * @param mixed $withtemplate has template + * @return array os strings + */ + function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { + if ($item->getType() == __CLASS__) { + // get tab name for a case itself + $tabname = __('Case', 'processmaker'); + if ($item->fields['plugin_processmaker_cases_id'] > 0) { + // case is a sub-case + $tabname = __('Sub-case', 'processmaker'); + } + return [ 'main' => $tabname." ".self::getStatus($item->fields['case_status']).""]; + } else { + $items_id = $item->getID(); + $itemtype = $item->getType(); + + // count how many cases are on this item + $cnt = count(self::getIDsFromItem($itemtype, $items_id)); + $tab = self::getTypeName(2); // to force plurial for tab name + if ($cnt) { + $tab .= "$cnt"; + } + return ['processmakercases' => $tab]; + } + } + + + /** + * Summary of getName + * @param mixed $options + * @return mixed + */ + function getName($options = []) { + return $this->fields['name']; + } + + + /** + * Summary of getIDFromItem + * @param string $itemtype is the item type + * @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; + //} + + + /** + * Summary of getIDsFromItem + * returns an array of the case ids linked to the item + * @param string $itemtype is the item type of the item (Ticket, Problem, Change) + * @param mixed $items_id is the GLPI id of the item in the type + * @return array + */ + static function getIDsFromItem($itemtype, $items_id) { + $ret = []; + $dbu = new DbUtils; + $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; + } + + /** + * Summary of getFromItem + * @param mixed $itemtype is the item type + * @param mixed $items_id is the item id + * @return mixed: returns false when there is no case associated with the item, else fills in the item fields from DB, and returns true + */ + //function getFromItem($itemtype, $items_id) { + // return $this->getFromDBByQuery(" WHERE items_id=$items_id and itemtype='$itemtype'"); + //} + + + /** + * Summary of getFromGUID + * @param mixed $case_guid + * @return boolean + */ + function getFromGUID($case_guid) { + $restrict=[ + 'WHERE' => [ + 'case_guid' => $case_guid, + ], + ]; + return $this->getFromDBByRequest($restrict); + } + + + /** + * Summary of getVariables + * @param mixed $vars + * @return mixed + */ + function getVariables($vars = []) { + global $PM_SOAP; + return $PM_SOAP->getVariables($this->fields['case_guid'], $vars); + } + + + /** + * Summary of sendVariables + * @param mixed $vars + * @return A + */ + function sendVariables($vars = []) { + global $PM_SOAP; + return $PM_SOAP->sendVariables($this->fields['case_guid'], $vars); + } + + + /** + * Summary of getCaseInfo + * @param mixed $delIndex + * @return stdClass, a getCaseInfoResponse object, or false exception occured + */ + function getCaseInfo($delIndex = '') { + global $PM_SOAP; + return $PM_SOAP->getCaseInfo($this->fields['case_guid'], $delIndex); + } + + + /** + * Summary of unpauseCase + * @param mixed $delIndex + * @param mixed $userGuid + * @return an + */ + function unpauseCase($delIndex, $userGuid) { + global $PM_SOAP; + return $PM_SOAP->unpauseCase($this->fields['case_guid'], $delIndex, $userGuid); + } + + + /** + * Summary of unassignCase + * Will unassign the delIndex task, restoring the assigned group + * @param $delIndex int the delegation index + * @param $taskGuid string the GUID of the task + * @param $tasktype string the type of task (TicketTask, ChangeTask, ProblemTask) + * @param $tasks_id int the id of the task + * @param $itemtype string the type of the ITIL object (Ticket, Change, Problem) + * @return bool + */ + function unassignCase($delIndex, $taskGuid, $tasktype, $tasks_id, $itemtype, $options) { + global $PM_DB, $PM_SOAP, $DB; + + // un-claim task + // will unclaim the task + // to unclaim a task, we must un-assign the task in the APP_DELEGATION table + // and un-assign the task in glpi_itemtypeTask table + + $groups_id_tech = $PM_SOAP->getGLPIGroupIdForSelfServiceTask($this->fields['case_guid'], $taskGuid); + + if ($groups_id_tech !== false) { + // unclaim the case only when a GLPI group can be found + + $query = "UPDATE APP_DELEGATION SET USR_UID='', DEL_INIT_DATE=NULL, USR_ID=0 WHERE APP_NUMBER=".$this->getID()." AND DEL_INDEX=$delIndex;"; + $PM_DB->query($query); + + $glpi_task = new $tasktype; + $glpi_task->getFromDB($tasks_id); + $foreignkey = getForeignKeyFieldForItemType( $itemtype ); + + $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); // do not send notification yet + $glpi_task->update( ['id' => $glpi_task->getID(), + $foreignkey => $glpi_task->fields[$foreignkey], + 'users_id_tech' => 0, + 'groups_id_tech' => $groups_id_tech['id'], + 'update' => true] ); + PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); + + // send notification now! + $pm_task = new PluginProcessmakerTask($tasktype); + $pm_task->getFromDB($tasks_id); + $glpi_item = new $itemtype; + $glpi_item->getFromDB($glpi_task->fields[$foreignkey]); + $pm_task->sendNotification('task_unclaim', $glpi_task, $glpi_item, $this); + + // create an information task and add comment + $pm_process = $this->getProcess(); + $dbu = new DbUtils; + $info = __('Task un-claimed!
Case: %s
Task: "%s" has been un-assigned from "%s" and assigned to "%s" group.
Reason: %s', 'processmaker'); + $info .= ""; + $taskCat = new TaskCategory; + $taskCat->getFromDB( $glpi_task->fields['taskcategories_id'] ); + $info = sprintf($info, + $this->getNameID(['forceid' => true]), + DropdownTranslation::getTranslatedValue($glpi_task->fields['taskcategories_id'], 'TaskCategory', 'name', $_SESSION['glpilanguage'], $taskCat->fields['name']), + Html::clean($dbu->getUserName(isset($glpi_task->oldvalues['users_id_tech']) ? $glpi_task->oldvalues['users_id_tech'] : 0)), + Html::clean($groups_id_tech['name']), + $options['comment'] + ); + // unescape some chars and replace CRLF, CR or LF by
+ $info = str_replace(["\\'", '\\"', '\r\n', '\r', '\n'], ["'", '"', '
', '
', '
'], $info); + + $glpi_task->add([$foreignkey => $glpi_task->fields[$foreignkey], + 'is_private' => 0, // a post-only user can't create private task + 'taskcategories_id' => $pm_process->fields['taskcategories_id'], + 'content' => $DB->escape($info), + 'users_id' => $PM_SOAP->taskWriter, + 'state' => Planning::INFO, + 'users_id_tech' => Session::getLoginUserID(), + ]); + + return true; + } + + return false; + } + + + /** + * Summary of reassignCase + * @param mixed $delIndex + * @param mixed $taskGuid + * @param mixed $delThread + * @param mixed $users_id_source + * @param mixed $users_id_target + * @return mixed + */ + function reassignCase($delIndex, $taskGuid, $delThread, $users_id_source, $users_id_target, $options) { + global $PM_SOAP; + $users_guid_source = ''; // by default + if ($users_id_source !== 0) { // when task is not 'to be claimed' + $users_guid_source = PluginProcessmakerUser::getPMUserId($users_id_source); + } + $users_guid_target = PluginProcessmakerUser::getPMUserId($users_id_target); + $pmResponse = $PM_SOAP->reassignCase($this->fields['case_guid'], $delIndex, $users_guid_source, $users_guid_target); + // now should manage GLPI Tasks previously assigned to the $users_guid_source + if ($pmResponse->status_code == 0) { + // we need to change the delindex of the glpi task and the assigned tech to prevent creation of new tasks + // we need the delindex of the current glpi task, and the delindex of the new one + // search for new delIndex and new delThread + $newCaseInfo = $this->getCaseInfo( ); + $newDelIndex = 0; + $newDelThread = 0; + foreach ($newCaseInfo->currentUsers as $newCaseUser) { + if ($newCaseUser->taskId == $taskGuid && $newCaseUser->delThread == $delThread) { + $newDelIndex = $newCaseUser->delIndex; + $newDelThread = $newCaseUser->delThread; + break; + } + } + $this->reassignTask($delIndex, $newDelIndex, $delThread, $newDelThread, $users_id_target, $options); + return true; + } + return false; + } + + + /** + * Summary of reassignTask + * @param mixed $delIndex + * @param mixed $newDelIndex + * @param mixed $newTech + */ + public function reassignTask ($delIndex, $newDelIndex, $delThread, $newDelThread, $newTech, $options) { + global $DB, $PM_SOAP; + + $dbu = new DbUtils; + $pm_task_row = $dbu->getAllDataFromTable(PluginProcessmakerTask::getTable(), ['plugin_processmaker_cases_id' => $this->getID(), 'del_index' => $delIndex, 'del_thread' => $delThread]); + if ($pm_task_row && count($pm_task_row) == 1) { + $pm_task_row = array_shift($pm_task_row); + $glpi_task = new $pm_task_row['itemtype']; + $glpi_task->getFromDB($pm_task_row['items_id']); + + $itilobject_itemtype = $this->fields['itemtype']; + $foreignkey = getForeignKeyFieldForItemType( $itilobject_itemtype ); + + PluginProcessmakerProcessmaker::addWatcher( $itilobject_itemtype, $glpi_task->fields[ $foreignkey ], $newTech ); + + $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); // do not send notification yet + $glpi_task->update( ['id' => $glpi_task->getID(), + $foreignkey => $glpi_task->fields[$foreignkey], + 'users_id_tech' => $newTech, + 'groups_id_tech' => 0, + 'update' => true] ); + PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); + + // then update the delIndex and delThread + $DB->Update( 'glpi_plugin_processmaker_tasks', [ + 'del_index' => $newDelIndex, + 'del_thread' => $newDelThread + ], [ + 'id' => $pm_task_row['id'] + ] + ); + + // send notification now! + $pm_task = new PluginProcessmakerTask($pm_task_row['itemtype']); + $pm_task->getFromDB($pm_task_row['items_id']); + $glpi_item = new $itilobject_itemtype; + $glpi_item->getFromDB($glpi_task->fields[$foreignkey]); + $pm_task->sendNotification('task_reassign', $glpi_task, $glpi_item, $this); + + // create an information task and add comment + $pm_process = $this->getProcess(); + $old_users_tech_id = isset($glpi_task->oldvalues['users_id_tech']) ? $glpi_task->oldvalues['users_id_tech'] : 0; + $taskCat = new TaskCategory; + $taskCat->getFromDB( $glpi_task->fields['taskcategories_id'] ); + $task_name = DropdownTranslation::getTranslatedValue($glpi_task->fields['taskcategories_id'], 'TaskCategory', 'name', $_SESSION['glpilanguage'], $taskCat->fields['name']); + $new_tech_name = Html::clean($dbu->getUserName($newTech)); + if ($old_users_tech_id) { + $info = __('Task re-assigned!
Case: %s
Task: "%s" has been re-assigned from "%s" to "%s".
Reason: %s', 'processmaker'); + $info = sprintf($info, + $this->getNameID(['forceid' => true]), + $task_name, + Html::clean($dbu->getUserName(isset($glpi_task->oldvalues['users_id_tech']) ? $glpi_task->oldvalues['users_id_tech'] : 0)), + $new_tech_name, + $options['comment'] + ); + } else { + $info = __('Task assigned!
Case: %s
Task: "%s" has been assigned to "%s".
Reason: %s', 'processmaker'); + $info = sprintf($info, + $this->getNameID(['forceid' => true]), + $task_name, + $new_tech_name, + $options['comment'] + ); + } + $info .= ""; + + // unescape some chars and replace CRLF, CR or LF by
+ $info = str_replace(["\\'", '\\"', '\r\n', '\r', '\n'], ["'", '"', '
', '
', '
'], $info); + + $glpi_task->add([$foreignkey => $glpi_task->fields[$foreignkey], + 'is_private' => 0, // a post-only user can't create private task + 'taskcategories_id' => $pm_process->fields['taskcategories_id'], + 'content' => $DB->escape($info), + 'users_id' => $PM_SOAP->taskWriter, + 'state' => Planning::INFO, + 'users_id_tech' => Session::getLoginUserID(), + ]); + } + } + + + /** + * Summary of getProcess + * Returns process object + * @return bool|PluginProcessmakerProcess + */ + function getProcess() { + $pm_process = new PluginProcessmakerProcess; + if (!$this->process && $pm_process->getFromDB($this->fields['plugin_processmaker_processes_id'])) { + $this->process = $pm_process; + } + return $this->process; + } + + /** + * Summary of showCaseProperties + */ + function showCaseProperties() { + global $DB, $PM_DB; + + // get all tasks that are OPEN for any sub-case of this case + $case_tasks = []; + $res = $DB->request('glpi_plugin_processmaker_tasks', [ + 'AND' => [ + 'plugin_processmaker_cases_id' => $this->getID(), + 'del_thread_status' => 'OPEN' + ] + ]); + foreach ($res as $task) { + $case_tasks[$task['del_index']] = $task; + } + //$query = "SELECT `glpi_plugin_processmaker_tasks`.* FROM `glpi_plugin_processmaker_tasks` + // WHERE `glpi_plugin_processmaker_tasks`.`plugin_processmaker_cases_id`={$this->getID()} AND `del_thread_status`='OPEN'"; + //foreach ($DB->request($query) as $task) { + // $case_tasks[$task['del_index']] = $task; + //} + + //// get all tasks that are OPEN for any sub-case of this case + //$sub_cases = []; + //$query = "SELECT `glpi_plugin_processmaker_tasks`.* FROM `glpi_plugin_processmaker_tasks` + // JOIN `glpi_plugin_processmaker_cases` on `glpi_plugin_processmaker_cases`.`id`=`glpi_plugin_processmaker_tasks`.`plugin_processmaker_cases_id` + // WHERE `glpi_plugin_processmaker_cases`.`plugin_processmaker_cases_id`={$this->getID()} AND `del_thread_status`='OPEN'"; + //foreach($DB->request($query) as $task) { + // $sub_cases[$task['plugin_processmaker_cases_id']][$task['del_index']] = $task; + //} + + $caseInfo = $this->getCaseInfo(); + if (property_exists($caseInfo, 'currentUsers')) { + $caseInfo->currentUsers = $this->sortTasks($caseInfo->currentUsers, PluginProcessmakerUser::getPMUserId(Session::getLoginUserID())); + } + $res = $PM_DB->request([ + 'SELECT' => ['DEL_INDEX', 'DEL_DELEGATE_DATE'], + 'FROM' => 'APP_DELEGATION', + 'WHERE' => ['APP_UID' => $caseInfo->caseId] + ]); + //$query = "SELECT `DEL_INDEX`, `DEL_DELEGATE_DATE` FROM `APP_DELEGATION` WHERE `APP_UID`='{$caseInfo->caseId}'"; + $tasks = []; + foreach ($res as $row) { + $tasks[$row['DEL_INDEX']] = $row['DEL_DELEGATE_DATE']; + } + //foreach ($PM_DB->request($query) as $row) { + // $tasks[$row['DEL_INDEX']] = $row['DEL_DELEGATE_DATE']; + //} + + echo "

"; + // show the case properties like given by PM server + $this->showShort($caseInfo); + + // show current (running) tasks properties + echo "

"; + + echo "
"; + echo ""; + + echo ""; + + if (property_exists($caseInfo, 'currentUsers') && count($caseInfo->currentUsers) > 0) { + echo " + + + + + "; + foreach ($caseInfo->currentUsers as $currentTask) { + $case_url = $this->getLinkURL().'&forcetab=PluginProcessmakerTask$'; + echo ""; + if (isset($case_tasks[$currentTask->delIndex])) { + $case_url .= $case_tasks[$currentTask->delIndex]['id']; + echo ""; + } else { + $res = $PM_DB->request([ + 'SELECT' => 'APP_UID', + 'FROM' => 'SUB_APPLICATION', + 'WHERE' => [ + 'AND' => [ + 'APP_PARENT' => $this->fields['case_guid'], + 'DEL_INDEX_PARENT' => $currentTask->delIndex, + 'SA_STATUS' => 'ACTIVE' + ] + ] + ]); + //$res = $PM_DB->query("SELECT APP_UID FROM SUB_APPLICATION WHERE APP_PARENT='{$this->fields['case_guid']}' AND DEL_INDEX_PARENT={$currentTask->delIndex} AND SA_STATUS='ACTIVE'"); + //if ($res && $PM_DB->numrows($res) == 1) { + // $row = $PM_DB->fetch_assoc($res); + if ($res->numrows() == 1 && $row = $res->next()) { + $sub_case = new PluginProcessmakerCase; + $sub_case->getFromGUID($row['APP_UID']); + $case_url .= $sub_case->getID()."-".$currentTask->delIndex; + echo ""; + } else { + echo ""; + } + } + echo ""; + if ($currentTask->userName == '') { + echo ""; + } else { + echo ""; + } + echo ""; + echo ""; + } + } else { + echo ""; + } + + echo "
".__('Current task(s) properties', 'processmaker')."
".__('Task', 'processmaker')."".__('Task guid', 'processmaker')."".__('Current user', 'processmaker')."".__('Task delegation date', 'processmaker')."
".$currentTask->taskName."> ".$currentTask->taskName."".$currentTask->taskName."".$currentTask->taskId."".__('To be claimed', 'processmaker')."".$currentTask->userName."".Html::convDateTime($tasks[$currentTask->delIndex])."
".__('None')."
"; + + echo "
"; + + // show the parent case if it's a sub-case + if ($this->fields['plugin_processmaker_cases_id'] > 0) { + echo "

"; + $sub_case = new self; + $sub_case->getFromDB($this->fields['plugin_processmaker_cases_id']); + $sub_case->showShort($sub_case->getCaseInfo(), true); + } + + } + + /** + * Summary of showShort + * @param mixed $caseInfo + * @param mixed $showparenturl + */ + function showShort($caseInfo, $showparenturl = false) { + + echo "
"; + echo ""; + + if ($this->fields['plugin_processmaker_cases_id'] > 0) { + echo ""; + } else { + if ($showparenturl) { + echo ""; + } else { + echo ""; + } + } + + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + //echo ""; + echo ""; + + echo ""; + echo ""; + if ($showparenturl) { + echo ""; + } else { + echo ""; + } + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + //echo ""; + echo ""; + + echo "
".__('Sub-case properties', 'processmaker')."
".__('Parent case properties', 'processmaker')."
".__('Case properties', 'processmaker')."
".__('Process', 'processmaker')."".__('Case title', 'processmaker')."".__('Case number', 'processmaker')."".__('Case status', 'processmaker')."".__('Case guid', 'processmaker')."".__('Creator', 'processmaker')."".__('Creation date', 'processmaker')."".__('Last update', 'processmaker')."".__('Case description', 'processmaker')."
".$caseInfo->processName."".$this->getLink()."".$caseInfo->caseName."".$caseInfo->caseNumber."".self::getStatus($caseInfo->caseStatus)."".$caseInfo->caseId."".$caseInfo->caseCreatorUserName."".Html::convDateTime($caseInfo->createDate)."".Html::convDateTime($caseInfo->updateDate)."".$caseInfo->????."
"; + + echo "
"; + + } + + + /** + * Summary of localSortTasks + * used to sort array of tasks in a currenUsers object + * @param mixed $a + * @param mixed $b + * @return integer + */ + static private function localSortTasks ($a, $b) { + return $a->delIndex - $b->delIndex; + } + + /** + * Summary of sortTasks + * @param mixed $tasks is the array of tasks from a getCaseInfo->currentUsers + * @param mixed $GLPICurrentPMUserId + * @return array sorted $tasks + */ + public function sortTasks($tasks, $GLPICurrentPMUserId) { + + $tbctasks = []; + $utasks = []; + $infotasks = []; + + foreach ($tasks as $caseUser) { + if ($caseUser->userId == $GLPICurrentPMUserId) { + $utasks[] = $caseUser; + } else { + if ($caseUser->userId == '') { // task to be claimed + $tbctasks[] = $caseUser; + } else { + $infotasks[] = $caseUser; + } + } + } + + // order task by "current user", then by "to be claimed", and then push to end "tasks assigned to another user" + // then by delindex ASC in these three parts + usort($utasks, 'self::localSortTasks'); + usort($tbctasks, 'self::localSortTasks'); + usort($infotasks, 'self::localSortTasks'); + + return array_merge($utasks, $tbctasks, $infotasks); + } + + + /** + * Summary of showCaseInfoTab + * Will show information about the current case + * @param CommonGLPI $case is a PluginProcessmakerCase object + * @param mixed $tabnum + * @param mixed $withtemplate + */ + 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.'; + $itemtype = $case->fields['itemtype']; + + $maintitle = __('Case is linked to a %1s', 'processmaker'); + if ($case->fields['plugin_processmaker_cases_id'] > 0) { + $maintitle = __('Sub-case is linked to a %1s', 'processmaker'); + } + + echo "".sprintf($maintitle, $itemtype::getTypeName(1)).""; + + Ticket::commonListHeader(Search::HTML_OUTPUT); + + $itemtype::showShort($case->fields['items_id']); + + echo ""; + + // show case properties + $case->showCaseProperties(); + + if ($case->fields['plugin_processmaker_cases_id'] == 0 && self::canCancel() && $case->fields['case_status'] == self::TO_DO) { + + // it's a main case, not a sub-case + // and we have the rights to cancel cases + + echo "

"; + echo ""; + echo ""; + echo ""; + echo "
".__('Case cancellation', 'processmaker')."
".__('Cancel case', 'processmaker').""; + echo ""; + echo ""; + echo ""; + echo "
"; + + } + + // 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->canPurgeItem($case->getID())) { + + // then propose a button to delete case + // the button will be effectively shown by the showFormButtons() + + echo "

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

"; + + } + + return; + } + + + /** + * Summary of showForItem + * Shows list of cases attached to an item + * @param CommonITILObject $item + */ + static function showForItem(CommonITILObject $item) { + global $DB, $CFG_GLPI, $PM_SOAP; + + $items_id = $item->getField('id'); + $itemtype = $item->getType(); + + + $canupdate = $item->can($items_id, UPDATE); + + $rand = mt_rand(); + $res = $DB->request([ + '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' => [ + 'FKEY' => [ + 'gppp' => 'id', + 'gppc' => 'plugin_processmaker_processes_id'] + ] + ], + 'WHERE' => [ + 'AND' => [ + 'gppc.itemtype' => $itemtype, + 'gppc.items_id' => $items_id + ] + ] + ]); + + $cases = []; + $used = []; + $pid = []; + if ($numrows = $res->numrows()) { + foreach ($res as $data) { + $cases[$data['id']] = $data; + $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') + ]; + + // check if item is not solved nor closed + if ($canupdate + && $item->fields['status'] != CommonITILObject::SOLVED + && $item->fields['status'] != CommonITILObject::CLOSED + && $_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 ""; + echo ""; + echo ""; + + echo ""; + echo ""; + + echo "
".__('Add a new case', 'processmaker')."
"; + echo __('Select the process you want to add', 'processmaker'); + echo ""; + $condition['is_active'] = 1; + if ($itemtype == 'Ticket' && $item->fields['type'] == Ticket::INCIDENT_TYPE) { + $condition['is_incident'] = 1; + } else if ($itemtype == 'Ticket' && $item->fields['type'] == Ticket::DEMAND_TYPE) { + $condition['is_request'] = 1; + } else { + $condition['is_'.strtolower($itemtype)] = 1; + //$is_itemtype = "AND is_".strtolower($itemtype)."=1"; + } + PluginProcessmakerProcess::dropdown(['value' => 0, + 'entity' => $item->fields['entities_id'], + 'name' => 'plugin_processmaker_processes_id', + //'condition' => "is_active=1 $is_itemtype", + 'condition' => $condition, + 'specific_tags' => ['count_cases_per_item' => $pid] + ]); + echo ""; + echo ""; + echo "
"; + Html::closeForm(); + echo "
"; + } + + echo "
"; + if ($canupdate && $numrows) { + Html::openMassiveActionsForm('mass'.__CLASS__.$rand); + $massiveactionparams = ['num_displayed' => $numrows, + 'container' => 'mass'.__CLASS__.$rand]; + Html::showMassiveActions($massiveactionparams); + } + echo ""; + echo ""; + echo ""; + if ($numrows) { + $header_begin = ""; + $header_top = ''; + $header_bottom = ''; + $header_end = ''; + if ($canupdate + && $numrows) { + $header_top .= ""; + $header_bottom .= ""; + } + + foreach ($columns as $key => $val) { + $header_end .= ""; + } + + $header_end .= ""; + echo $header_begin.$header_top.$header_end; + + Session::initNavigateListItems('PluginProcessmakerCase', + //TRANS : %1$s is the itemtype name, + // %2$s is the name of the item (used for headings of a list) + sprintf(__('%1$s = %2$s'), + $itemtype::getTypeName(1), $item->fields["name"])); + + $i = 0; + foreach ($cases as $data) { + Session::addToNavigateListItems('PluginProcessmakerCase', $data["id"]); + $link = NOT_AVAILABLE; + $case = new self; + if ($case->getFromDB($data["id"])) { + $link = $case->getLink(); + } + + echo ""; + if ($canupdate) { + echo ""; + } + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + + $i++; + } + echo $header_begin.$header_bottom.$header_end; + + } + + echo "
".PluginProcessmakerCase::getTypeName($numrows)."
".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); + $header_top .= "".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); + $header_bottom .= "$val
"; + // show massive action only for main cases (not for subcases) + if ($data['plugin_processmaker_cases_id'] == 0) { + Html::showMassiveActionCheckBox(__CLASS__, $data["assocID"]); + } + echo "".$data['pname']."".$link."".self::getStatus($data['case_status']).""; + if ($data['plugin_processmaker_cases_id'] > 0) { + // then this is a subcase of + $maincase = new self; + if ($maincase->getFromDB($data['plugin_processmaker_cases_id'])) { + echo $maincase->getLink(); + } + } else { + echo '-'; + } + echo "
"; + if ($canupdate && $numrows) { + $massiveactionparams['ontop'] = false; + Html::showMassiveActions($massiveactionparams); + Html::closeForm(); + } + echo "
"; + } + + /** + * Summary of displayTabContentForItem + * @param CommonGLPI $item + * @param mixed $tabnum + * @param mixed $withtemplate + */ + static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { + global $PM_SOAP; + + if ($item->getType() == __CLASS__) { + // we are in a case viewing the main tab + // the 'Case infos' tab + //self::showCaseInfoTab($item, $tabnum, $withtemplate); + + } else { + + // show the list of cases attached to the $item ITIL object + if (!$PM_SOAP->config->fields['maintenance']) { + self::showForItem($item); + } else { + PluginProcessmakerProcessmaker::showUnderMaintenance(); + } + } + } + + + /** + * Summary of deleteTasks + * will delete all tasks associated with this case from the item + * @return true if tasks have been deleted from associated item and from case table + */ + private function deleteTasks() { + global $DB; + $ret = false; + $sub = new QuerySubQuery([ + 'SELECT' => 'items_id', + 'FROM' => 'glpi_plugin_processmaker_tasks', + 'WHERE' => ['plugin_processmaker_cases_id' => $this->fields['id']] + ]); + + if ($DB->delete('glpi_'.strtolower($this->fields['itemtype']).'tasks', ['id' => $sub ])) { + if ($DB->delete('glpi_plugin_processmaker_tasks', ['plugin_processmaker_cases_id' => $this->fields['id']])) { + $ret = true; + } + } + //$query = "DELETE FROM glpi_".strtolower($this->fields['itemtype'])."tasks WHERE id IN (SELECT items_id FROM glpi_plugin_processmaker_tasks WHERE plugin_processmaker_cases_id='".$this->fields['id']."')"; + //if ($DB->query( $query )) { + // $query = "DELETE FROM glpi_plugin_processmaker_tasks WHERE plugin_processmaker_cases_id='".$this->fields['id']."'"; + // if ($DB->query( $query )) { + // $ret = true; + // } + //} + return $ret; + } + + + /** + * Summary of deleteCase + * will delete case and all tasks associated with this case from the item + * @return true if case and tasks have been deleted from associated item and from case table + */ + function deleteCase() { + return $this->delete(['id' => $this->getID()]); + } + + + /** + * Summary of cancelTasks + * will mark as information all to_do tasks + * BEWARE that this will only be done when case is in TO_DO status + * @return true if tasks have been deleted from associated item and from case table + */ + private function cancelTasks() { + global $DB; + $ret = false; + + if (isset($this->fields['case_status']) && $this->fields['case_status'] == "TO_DO") { + $sub = new QuerySubQuery([ + 'SELECT' => 'items_id', + 'FROM' => 'glpi_plugin_processmaker_tasks', + 'WHERE' => ['plugin_processmaker_cases_id' => $this->fields['id']] + ]); + $res = $DB->update('glpi_'.$this->fields['itemtype'].'tasks', [ + 'state' => 0, + 'users_id_tech' => 0, + 'groups_id_tech' => 0, + 'begin' => null, + 'end' => null + ], [ + 'AND' => [ + 'state' => 1, + 'id' => $sub + ] + ]); + if ($res) { + $ret = true; + } + //$query = "UPDATE glpi_".$this->fields['itemtype']."tasks SET state=0,users_id_tech=0,begin=NULL,end=NULL WHERE state=1 AND id in (select items_id from glpi_plugin_processmaker_tasks where plugin_processmaker_cases_id='".$this->fields['id']."')"; + //if ($DB->query( $query )) { + // $ret = true; + //} + } + return $ret; + } + + + + /** + * Summary of cancelCase + * will cancel case and mark 'to_do' tasks associated with this case from the item as information + * BEWARE that this will only be done when case is in TO_DO status + * @return true if case and tasks have been cancelled or marked from associated item and from case table + */ + function cancelCase() { + global $DB; + $ret = false; + + if (isset($this->fields['case_status']) && $this->fields['case_status'] == "TO_DO") { + if ($this->cancelTasks()) { + if ($this->update( [ 'id' => $this->getID(), 'case_status' => 'CANCELLED' ] )) { + $ret=true; + } + } + } + + return $ret; + } + + /** + * Summary of canSolve + * To know if a Ticket (Problem or Change) can be solved + * i.e. the case permits solving of item + * @param mixed $param is an array containing the item + * @return bool true to permit solve, false otherwise + */ + public static function canSolve ($param) { + $item = $param['item']; + $cases = self::getIDsFromItem($item->getType(), $item->getID()); + foreach ($cases as $cases_id) { + $myCase = new self; + if ($myCase->getFromDB($cases_id)) { + $pmVar = $myCase->getVariables(['GLPI_ITEM_CAN_BE_SOLVED']); + if ($myCase->fields['case_status'] != self::COMPLETED + && $myCase->fields['case_status'] != self::CANCELLED + && (!isset($pmVar['GLPI_ITEM_CAN_BE_SOLVED']) || $pmVar['GLPI_ITEM_CAN_BE_SOLVED'] != 1)) { + // then item can't be solved + return false; + } + } + } + return true; + } + + /** + * Summary of getToDoTasks + * @param mixed $item is a Ticket, a Problem or a Change + * @return array list of tasks with status 'to do' for case associated with item + */ + public static function getToDoTasks($item) { + $ret = []; + + $cases = self::getIDsFromItem($item->getType(), $item->getID()); + foreach ($cases as $cases_id) { + $ret = $ret + PluginProcessmakerTask::getToDoTasks($cases_id, $item->getType()."Task"); + } + + return $ret; + } + + + //static function getIcon() { + // // return "fas fa-code-branch fa-rotate-90"; + // return "fas fa-blog fa-flip-vertical"; + // // return "fas fa-cogs fa-flip-vertical"; + //} + + + /** + * Summary of getMenuContent + * @return array + */ + static function getMenuContent() { + + if (!Session::haveRightsOr('plugin_processmaker_case', [READ, DELETE, CANCEL, ADHOC_REASSIGN])) { + return []; + } + + $front_page = "/plugins/processmaker/front"; + $menu = []; + $menu['title'] = self::getTypeName(Session::getPluralNumber()); + $menu['page'] = "$front_page/case.php"; + $menu['icon'] = "'> 'cases' + ]; + + foreach ($itemtypes as $itemtype => $option) { + //$menu['options'][$option]['title'] = $itemtype::getTypeName(Session::getPluralNumber()); + $menu['options'][$option]['page'] = $itemtype::getSearchURL(false); + $menu['options'][$option]['links']['search'] = $itemtype::getSearchURL(false); + if (Session::haveRightsOr("config", [READ, UPDATE])) { + $menu['options'][$option]['links']['config'] = PluginProcessmakerConfig::getFormURL(false); + } + switch ($itemtype) { + case 'PluginProcessmakerCase': + //if ($itemtype::canCreate()) { + //$menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); + //} + break; + default : + $menu['options'][$option]['page'] = PluginProcessmakerProcess::getSearchURL(false); + break; + } + + } + return $menu; + } + + /** + * Summary of getSpecificValueToDisplay + * @param mixed $field + * @param mixed $values + * @param array $options + * @return mixed + */ + static function getSpecificValueToDisplay($field, $values, array $options = []) { + global $PM_DB; + if (!is_array($values)) { + $values = [$field => $values]; + } + switch ($field) { + case 'id': + if (isset($options['searchopt']['processmaker_cases'])) { + switch ($options['searchopt']['processmaker_cases']) { + case 'creation_date': + $res = $PM_DB->request('APPLICATION', [ + 'APP_NUMBER' => $values['id'] + ] + ); + if ($row = $res->next()) { + return Html::convDateTime($row['APP_CREATE_DATE']); + } + //$res = $PM_DB->query('SELECT * FROM APPLICATION WHERE APP_NUMBER = '.$values['id']); + //if ($res->num_rows > 0) { + // $row = $PM_DB->fetch_assoc($res); + // return Html::convDateTime($row['APP_CREATE_DATE']); + //} + //$locCase = new self; + //$locCase->getFromDB($values['id']); + //$caseInfo = $locCase->getCaseInfo(); + //return Html::convDateTime($caseInfo->createDate); + break; + case 'update_date': + $res = $PM_DB->request('APPLICATION', [ + 'APP_NUMBER' => $values['id'] + ] + ); + if ($row = $res->next()) { + return Html::convDateTime($row['APP_UPDATE_DATE']); + } + //$res = $PM_DB->query('SELECT * FROM APPLICATION WHERE APP_NUMBER = '.$values['id']); + //if ($res->num_rows > 0) { + // $row = $PM_DB->fetch_assoc($res); + // return Html::convDateTime($row['APP_UPDATE_DATE']); + //} + //$locCase = new self; + //$locCase->getFromDB($values['id']); + //$caseInfo = $locCase->getCaseInfo(); + //return Html::convDateTime($caseInfo->updateDate); + break; + } + } + return '-'; + case 'items_id': + // show an item link + $item = new $values['itemtype']; + $item->getFromDB($values['items_id']); + return $item->getLink(['forceid' => 1]); + + case 'case_status': + return self::getStatus($values['case_status']); + + case 'itemtype': + return self::getItemtype($values['itemtype']); + + case 'plugin_processmaker_processes_id': + $item = new PluginProcessmakerProcess; + $item->getFromDB($values['plugin_processmaker_processes_id']); + return $item->getLink(); + + case 'plugin_processmaker_cases_id': + if ($values['plugin_processmaker_cases_id'] != 0) { + $locSCase = new self; + $locSCase->getFromDB($values['plugin_processmaker_cases_id']); + return $locSCase->getLink(['forceid' => 1]); + } + return '-'; + + default: + return parent::getSpecificValueToDisplay($field, $values, $options); + } + } + + + static function getSpecificValueToSelect($field, $name = '', $values = '', array $options = []) { + + if (!is_array($values)) { + $values = [$field => $values]; + } + $options['display'] = false; + + switch ($field) { + case 'case_status': + $options['name'] = $name; + $options['value'] = $values[$field]; + return self::dropdownStatus($options); + case 'itemtype': + $options['name'] = $name; + $options['value'] = $values[$field]; + return self::dropdownItemtype($options); + case 'plugin_processmaker_processes_id': + $options['name'] = $name; + $options['value'] = $values[$field]; + $options['specific_tags'] = ['process_restrict' => 0]; + return PluginProcessmakerProcess::dropdown($options); + + default: + return parent::getSpecificValueToSelect($field, $name, $values, $options); + } + } + + + static function dropdownStatus(array $options = []) { + + $p['name'] = 'case_status'; + $p['value'] = self::TO_DO; + $p['showtype'] = 'normal'; + $p['display'] = true; + + if (is_array($options) && count($options)) { + foreach ($options as $key => $val) { + $p[$key] = $val; + } + } + + switch ($p['showtype']) { + //case 'allowed' : + // $tab = static::getAllowedStatusArray($p['value']); + // break; + + case 'search' : + $tab = static::getAllStatusArray(true); + break; + + default : + $tab = static::getAllStatusArray(false); + break; + } + + return Dropdown::showFromArray($p['name'], $tab, $p); + } + + + static function getAllStatusArray($withmetaforsearch = false) { + + $tab = [self::DRAFT => _x('case_status', 'Draft', 'processmaker'), + self::TO_DO => _x('case_status', 'To do', 'processmaker'), + self::COMPLETED => _x('case_status', 'Completed', 'processmaker'), + self::CANCELLED => _x('case_status', 'Cancelled', 'processmaker')]; + + return $tab; + } + + static function getStatus($value) { + + $tab = static::getAllStatusArray(true); + // Return $value if not defined + return (isset($tab[$value]) ? $tab[$value] : $value); + } + + static function dropdownItemtype(array $options = []) { + + $p['name'] = 'itemtype'; + $p['value'] = 'Ticket'; + $p['showtype'] = 'normal'; + $p['display'] = true; + + if (is_array($options) && count($options)) { + foreach ($options as $key => $val) { + $p[$key] = $val; + } + } + + switch ($p['showtype']) { + //case 'allowed' : + // $tab = static::getAllowedStatusArray($p['value']); + // break; + + case 'search' : + $tab = static::getAllItemtypeArray(true); + break; + + default : + $tab = static::getAllItemtypeArray(false); + break; + } + + return Dropdown::showFromArray($p['name'], $tab, $p); + } + + + static function getAllItemtypeArray($withmetaforsearch = false) { + + $tab = ['Change' => Change::getTypeName(1), + 'Ticket' => Ticket::getTypeName(1), + 'Problem' => Problem::getTypeName(1) + ]; + + return $tab; + } + + + static function getItemtype($value) { + $tab = static::getAllItemtypeArray(true); + // Return $value if not defined + return (isset($tab[$value]) ? $tab[$value] : $value); + } + + + /** + * Get default values to search engine to override + **/ + static function getDefaultSearchRequest() { + + $search = ['sort' => 1, + 'order' => 'DESC']; + + return $search; + } + + + /** + * Summary of rawSearchOptions + * @return mixed + */ + function rawSearchOptions() { + $tab = []; + + $tab[] = [ + 'id' => 'common', + 'name' => __('Process cases', 'processmaker') + ]; + + $tab[] = [ + 'id' => '1', + 'table' => $this->getTable(), + 'field' => 'id', + 'name' => __('ID'), + 'datatype' => 'number', + 'searchtype' => 'contains', + 'massiveaction' => false + ]; + + $tab[] = [ + 'id' => '2', + 'table' => $this->getTable(), + 'field' => 'name', + 'name' => __('Title'), + 'datatype' => 'itemlink', + 'searchtype' => 'contains', + '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[] = [ + 'id' => '7', + 'table' => $this->getTable(), + 'field' => 'itemtype', + 'name' => __('Item type'), + 'massiveaction' => false, + 'datatype' => 'specific', + 'searchtype' => [ + '0' => 'contains', + '1' => 'equals', + '2' => 'notequals' + ] + ]; + + $tab[] = [ + 'id' => '8', + 'table' => $this->getTable(), + 'field' => 'items_id', + 'name' => __('Item'), + 'massiveaction' => false, + 'datatype' => 'specific', + 'additionalfields' => [ + '0' => 'itemtype' + ] + ]; + + $tab[] = [ + 'id' => '9', + 'table' => 'glpi_entities', + 'field' => 'name', + 'name' => __('Item entity', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'itemlink' + ]; + + $tab[] = [ + 'id' => '10', + 'table' => $this->getTable(), + 'field' => 'case_status', + 'name' => __('Status'), + 'datatype' => 'specific', + 'searchtype' => [ + '0' => 'contains', + '1' => 'equals', + '2' => 'notequals' + ], + 'massiveaction' => false + ]; + + $tab[] = [ + 'id' => '14', + 'table' => $this->getTable(), + 'field' => 'plugin_processmaker_cases_id', + 'name' => __('Sub-case of', 'processmaker'), + 'datatype' => 'specific', + 'massiveaction' => false, + 'nosearch' => true + ]; + + $tab[] = [ + 'id' => '16', + 'table' => $this->getTable(), + 'field' => 'id', + 'name' => __('Creation date'), + 'datatype' => 'specific', + 'massiveaction' => false, + 'nosearch' => true, + 'processmaker_cases' => 'creation_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 = []) { + $options['colspan'] = 6; + $options['formtitle'] = sprintf( __('Case status is \'%s\'', 'processmaker'), self::getStatus($this->fields['case_status'])); + + $this->showFormHeader($options); + + $process = new PluginProcessmakerProcess; + $process->getFromDB($this->fields['plugin_processmaker_processes_id']); + + if ($process->fields['maintenance']) { + PluginProcessmakerProcess::showUnderMaintenance($process->fields['name'], 'small'); + } + self::showCaseInfoTab($this); + + //echo '
' ; + + Html::closeForm(); + + $options['candel'] = $options['candel'] ?? $this->canPurgeItem($ID); + + $this->showFormButtons($options); + + echo Html::scriptBlock(" + $('#tabsbody th').css('text-align', 'center'); + $('#tabsbody td').css('text-align', 'center'); + "); + } + + + /** + * Summary of defineTabs + * @param mixed $options + * @return array + */ + function defineTabs($options = []) { + + $process = new PluginProcessmakerProcess; + $process->getFromDB($this->fields['plugin_processmaker_processes_id']); + + $ong = []; + if (self::isLayoutWithMain()) { + $this->addDefaultFormTab($ong); + } + + if (!$process->fields['maintenance']) { + $this->addStandardTab('PluginProcessmakerTask', $ong, $options); + } + + if (!self::isLayoutWithMain()) { + $this->addStandardTab(__CLASS__, $ong, $options); + } + + if (!$process->fields['maintenance']) { + $this->addStandardTab('PluginProcessmakerCasemap', $ong, $options); + + $this->addStandardTab('PluginProcessmakerCasehistory', $ong, $options); + + $this->addStandardTab('PluginProcessmakerCasechangelog', $ong, $options); + + $this->addStandardTab('PluginProcessmakerCasedynaform', $ong, $options); + } + + return $ong; + } + + /** + * Actions done after the PURGE of the item in the database + * + * @return nothing + **/ + + /** + * Summary of post_purgeItem + * Actions done after the PURGE of the item in the database + * Will purge the tasks and the PM case and recursively the sub-cases if any + * @return boolean|integer + */ + function post_purgeItem() { + global $PM_SOAP; + $ret = false; + + $PM_SOAP->login(true); + if ($this->deleteTasks() && $this->deleteCronTaskActions() && $PM_SOAP->deleteCase($this->fields['case_guid'])->status_code == 0) { + $ret = true; + $dbu = new DbUtils; + // then must delete any sub-processes (sub-cases) + $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']]); + } + } + return $ret; + } + + + /** + * Summary of deleteCronTaskActions + * Will delete any cron task actions taht are linked to current case + */ + function deleteCronTaskActions() { + global $DB; + + return $DB->delete('glpi_plugin_processmaker_crontaskactions', [ + 'plugin_processmaker_cases_id' => $this->getID() + ] + ); + //$query = "DELETE FROM `glpi_plugin_processmaker_crontaskactions` WHERE `plugin_processmaker_cases_id` = ".$this->getID(); + //return $DB->query($query); + } + +} diff --git a/inc/config.class.php b/inc/config.class.php index 31ce71d..c7fc636 100644 --- a/inc/config.class.php +++ b/inc/config.class.php @@ -1,392 +1,383 @@ -getFromDB(1)) { - self::$_instance->getEmpty(); - } - } - return self::$_instance; - } - - /** - * Prepare input datas for updating the item - * @param array $input used to update the item - * @return array the modified $input array - **/ - function prepareInputForUpdate($input) { - global $CFG_GLPI; - - if (!isset($input["maintenance"])) { - $input["maintenance"] = 0; - } - - if (isset($input["pm_dbserver_passwd"])) { - if (empty($input["pm_dbserver_passwd"])) { - unset($input["pm_dbserver_passwd"]); - } else { - $input["pm_dbserver_passwd"] = Toolbox::encrypt(stripslashes($input["pm_dbserver_passwd"]), GLPIKEY); - } - } - - if (isset($input["_blank_pm_dbserver_passwd"]) && $input["_blank_pm_dbserver_passwd"]) { - $input['pm_dbserver_passwd'] = ''; - } - - if (isset($input["pm_admin_passwd"])) { - if (empty($input["pm_admin_passwd"])) { - unset($input["pm_admin_passwd"]); - } else { - $input["pm_admin_passwd"] = Toolbox::encrypt(stripslashes($input["pm_admin_passwd"]), GLPIKEY); - } - } - - if (isset($input["_blank_pm_admin_passwd"]) && $input["_blank_pm_admin_passwd"]) { - $input['pm_admin_passwd'] = ''; - } - - if (isset($input['pm_server_URL'])) { - $input['domain'] = self::getCommonDomain( $CFG_GLPI['url_base'], $input['pm_server_URL'] ); - } - - return $input; - } - - /** - * Summary of getCommonDomain - * @param mixed $url1 first url - * @param mixed $url2 second url - * @return string the common domain part of the given urls - */ - static function getCommonDomain($url1, $url2) { - $domain = ''; - try { - $glpi = explode(".", parse_url($url1, PHP_URL_HOST)); - $pm = explode( ".", parse_url($url2, PHP_URL_HOST)); - $cglpi = array_pop( $glpi ); - $cpm = array_pop( $pm ); - while ($cglpi && $cpm && $cglpi == $cpm) { - $domain = $cglpi.($domain==''?'':'.'.$domain); - $cglpi = array_pop( $glpi ); - $cpm = array_pop( $pm ); - } - if ($domain != '') { - return $domain; - } - } catch (Exception $e) { - $domain = ''; - } - return $domain; - } - - /** - * Summary of showConfigForm - * @param mixed $item is the config - * @return boolean - */ - static function showConfigForm($item) { - global $PM_DB, $CFG_GLPI, $PM_SOAP; - - $setup_ok = false; - - $ui_theme = [ - 'glpi_classic' => 'glpi_classic', - 'glpi_neoclassic' => 'glpi_neoclassic' - ]; - - $config = $PM_SOAP->config; - $config->showFormHeader(['colspan' => 4]); - - if (!$config->fields['maintenance']) { - - echo ""; - echo "".__('Server URL (must be in same domain than GLPI, if GLPI is using HTTPS, PM server must also use HTTPS)', 'processmaker').""; - echo ""; - echo "\n"; - - echo ""; - echo "".__('Common domain with GLPI', 'processmaker').""; - echo "
".$config->fields['domain']."
"; - - echo Html::scriptBlock(" - function setCommonDomain() { - - function parseUrl( url ) { - var a = document.createElement('a'); - a.href = url; -// debugger; - return { host: a.hostname, port: a.port, scheme: a.protocol.slice(0, -1), path: a.pathname, query: a.search.slice(1), fragment: a.hash.slice(1) } ; - } - var domain = ''; - try { - var glpi = parseUrl( '".$CFG_GLPI['url_base']."' ).host.split('.') ; - var pm = parseUrl( $('input[name=pm_server_URL]').val()).host.split('.'); - var cglpi = glpi.pop() ; - var cpm = pm.pop() ; - while( cglpi && cpm && cglpi == cpm ) { - domain = cglpi + (domain==''?'':'.' + domain) ; - cglpi = glpi.pop() ; - cpm = pm.pop() ; - } - if (domain != '' && domain.split('.').length > 1) { // common domain must be at least 'domain.com' and not 'com', otherwise some browser will not accept the CORS javascript - $('div[name=domain]').text(domain) ; - $('div[name=domain]').parent().attr('color', 'green'); - return; - } - } catch(ex) {} - $('div[name=domain]').text('".__('None!', 'processmaker')."') ; - $('div[name=domain]').parent().attr('color', 'red'); - }; - $('input[name=pm_server_URL]').on('keyup', setCommonDomain ) ; - setCommonDomain() ; - "); - echo "\n"; - - echo ""; - echo "".__('Verify SSL certificate', 'processmaker').""; - Dropdown::showYesNo("ssl_verify", $config->fields['ssl_verify']); - echo ""; - - echo ""; - echo "".__('Workspace Name', 'processmaker').""; - echo ""; - echo "\n"; - - echo ""; - echo "".__('Server administrator name', 'processmaker').""; - echo ""; - echo "\n"; - - echo ""; - echo "".__('Server administrator password', 'processmaker').""; - echo ""; - echo "  ".__('Clear'); - echo "\n"; - - echo ""; - echo "".__('Connection status', 'processmaker').""; - //$pm = new PluginProcessmakerProcessmaker; - - if ($config->fields['pm_server_URL'] != '' - && $config->fields['pm_workspace'] != '' - && $config->fields["pm_admin_user"] != '' - // && ($pm->login(true))) { - && ($PM_SOAP->login(true))) { - echo "".__('Test successful'); - $setup_ok = true; - } else { - // echo "".__('Test failed')."
".print_r($pm->lasterror, true); - echo "".__('Test failed')."
".print_r($PM_SOAP->lasterror, true); - } - echo "
\n"; - - echo "".__('SQL server setup', 'processmaker').""; - - echo ""; - echo "" . __('SQL server (MariaDB or MySQL)', 'processmaker') . ""; - echo ""; - echo "\n"; - - echo ""; - echo "" . __('Database name', 'processmaker') . ""; - echo ""; - echo "\n"; - - echo ""; - echo "" . __('SQL user', 'processmaker') . ""; - echo ""; - echo "\n"; - - echo ""; - echo "" . __('SQL password', 'processmaker') . ""; - echo ""; - echo "  ".__('Clear'); - echo "\n"; - - echo ""; - echo "".__('Connection status', 'processmaker').""; - if ($PM_DB->connected && isset($PM_DB->dbdefault) && $PM_DB->dbdefault != '') { - echo "".__('Test successful'); - } else { - echo "".__('Test failed'); - } - echo "\n"; - - echo "".__('Settings').""; - - echo ""; - echo "".__('Theme Name', 'processmaker').""; - Dropdown::showFromArray('pm_theme', $ui_theme, - ['value' => $config->fields['pm_theme']]); - echo ""; - - echo ""; - echo "".__('Main Task Category (edit to change name)', 'processmaker').""; - TaskCategory::dropdown(['name' => 'taskcategories_id', - 'display_emptychoice' => true, - 'value' => $config->fields['taskcategories_id']]); - echo "\n"; - - echo ""; - echo "".__('Task Writer (edit to change name)', 'processmaker').""; - $rand = mt_rand(); - User::dropdown(['name' => 'users_id', - 'display_emptychoice' => true, - 'right' => 'all', - 'rand' => $rand, - 'value' => $config->fields['users_id']]); - - // this code adds the + sign to the form - echo ""; - echo Ajax::createIframeModalWindow('add_dropdown'.$rand, - User::getFormURL(), - ['display' => false]); - // end of + sign - - echo "\n"; - - echo ""; - echo "".__('Group in ProcessMaker which will contain all GLPI users', 'processmaker').""; - - $pmGroups = [ 0 => Dropdown::EMPTY_VALUE ]; - //$res = $PM_DB->request([ - // 'SELECT DISTINCT' => 'CON_ID', - // 'FIELDS' => 'CON_VALUE', - // 'FROM' => 'CONTENT', - // 'WHERE' => ['CON_CATEGORY' => 'GRP_TITLE'], - // 'ORDER' => 'CON_VALUE' - // ]); - //$query = "SELECT DISTINCT CON_ID, CON_VALUE FROM CONTENT WHERE CON_CATEGORY='GRP_TITLE' ORDER BY CON_VALUE;"; - if ($PM_DB->connected) { - $res = $PM_DB->request([ - 'SELECT DISTINCT' => 'CON_ID', - 'FIELDS' => 'CON_VALUE', - 'FROM' => 'CONTENT', - 'WHERE' => ['CON_CATEGORY' => 'GRP_TITLE'], - 'ORDER' => 'CON_VALUE' - ]); - foreach ($res as $row) { - $pmGroups[ $row['CON_ID'] ] = $row['CON_VALUE']; - } - Dropdown::showFromArray( 'pm_group_guid', $pmGroups, ['value' => $config->fields['pm_group_guid']] ); - } 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 ""; - echo "".__('Maintenance mode').""; - Dropdown::showYesNo("maintenance", $config->fields['maintenance']); - echo ""; - - echo ""; - - echo "".__('Processmaker system information', 'processmaker').""; - if ($setup_ok) { - $info = $PM_SOAP->systemInformation( ); - echo ''.__('Version', 'processmaker').''.$info->version.''; - echo ''.__('Web server', 'processmaker').''.$info->webServer.''; - echo ''.__('Server name', 'processmaker').''.$info->serverName.''; - echo ''.__('PHP version', 'processmaker').''.$info->phpVersion.''; - echo ''.__('DB version', 'processmaker').''.$info->databaseVersion.''; - echo ''.__('DB server IP', 'processmaker').''.$info->databaseServerIp.''; - echo ''.__('DB name', 'processmaker').''.$info->databaseName.''; - echo ''.__('User browser', 'processmaker').''.$info->userBrowser.''; - echo ''.__('User IP', 'processmaker').''.$info->userIp.''; - } else { - echo ''.__('Version', 'processmaker').''.__('Not yet!', 'processmaker').''; - } - $config->showFormButtons(['candel' => false]); - - return false; - } - - - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - if ($item->getType()=='Config') { - return __('ProcessMaker', 'processmaker'); - } - return ''; - } - - - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - - if ($item->getType()=='Config') { - self::showConfigForm($item); - } - return true; - } - -} +getFromDB(1)) { + self::$_instance->getEmpty(); + } + } + return self::$_instance; + } + + /** + * Prepare input datas for updating the item + * @param array $input used to update the item + * @return array the modified $input array + **/ + function prepareInputForUpdate($input) { + global $CFG_GLPI; + + if (!isset($input["maintenance"])) { + $input["maintenance"] = 0; + } + + if (isset($input["pm_dbserver_passwd"])) { + if (empty($input["pm_dbserver_passwd"])) { + unset($input["pm_dbserver_passwd"]); + } else { + $input["pm_dbserver_passwd"] = Toolbox::sodiumEncrypt(stripslashes($input["pm_dbserver_passwd"])); + } + } + + if (isset($input["_blank_pm_dbserver_passwd"]) && $input["_blank_pm_dbserver_passwd"]) { + $input['pm_dbserver_passwd'] = ''; + } + + if (isset($input["pm_admin_passwd"])) { + if (empty($input["pm_admin_passwd"])) { + unset($input["pm_admin_passwd"]); + } else { + $input["pm_admin_passwd"] = Toolbox::sodiumEncrypt(stripslashes($input["pm_admin_passwd"])); + } + } + + if (isset($input["_blank_pm_admin_passwd"]) && $input["_blank_pm_admin_passwd"]) { + $input['pm_admin_passwd'] = ''; + } + + if (isset($input['pm_server_URL'])) { + $input['domain'] = self::getCommonDomain( $CFG_GLPI['url_base'], $input['pm_server_URL'] ); + } + + return $input; + } + + /** + * Summary of getCommonDomain + * @param mixed $url1 first url + * @param mixed $url2 second url + * @return string the common domain part of the given urls + */ + static function getCommonDomain($url1, $url2) { + $domain = ''; + try { + $glpi = explode(".", parse_url($url1, PHP_URL_HOST)); + $pm = explode( ".", parse_url($url2, PHP_URL_HOST)); + $cglpi = array_pop( $glpi ); + $cpm = array_pop( $pm ); + while ($cglpi && $cpm && $cglpi == $cpm) { + $domain = $cglpi.($domain==''?'':'.'.$domain); + $cglpi = array_pop( $glpi ); + $cpm = array_pop( $pm ); + } + if ($domain != '') { + return $domain; + } + } catch (Exception $e) { + $domain = ''; + } + return $domain; + } + + /** + * Summary of showConfigForm + * @param mixed $item is the config + * @return boolean + */ + static function showConfigForm($item) { + global $PM_DB, $CFG_GLPI, $PM_SOAP; + + $setup_ok = false; + + $ui_theme = [ + 'glpi_classic' => 'glpi_classic', + 'glpi_neoclassic' => 'glpi_neoclassic' + ]; + + $config = $PM_SOAP->config; + $config->showFormHeader(['colspan' => 2]); + + if (!$config->fields['maintenance']) { + + echo ""; + echo "".__('Server URL (must be in same domain than GLPI, if GLPI is using HTTPS, PM server must also use HTTPS)', 'processmaker').""; + echo ""; + echo "\n"; + + echo ""; + echo "".__('Common domain with GLPI', 'processmaker').""; + echo "
".$config->fields['domain']."
"; + + echo Html::scriptBlock(" + function setCommonDomain() { + + function parseUrl( url ) { + var a = document.createElement('a'); + a.href = url; + //debugger; + return { host: a.hostname, port: a.port, scheme: a.protocol.slice(0, -1), path: a.pathname, query: a.search.slice(1), fragment: a.hash.slice(1) } ; + } + var domain = ''; + try { + var glpi = parseUrl( '".$CFG_GLPI['url_base']."' ).host.split('.') ; + var pm = parseUrl( $('input[name=pm_server_URL]').val()).host.split('.'); + var cglpi = glpi.pop() ; + var cpm = pm.pop() ; + while( cglpi && cpm && cglpi == cpm ) { + domain = cglpi + (domain==''?'':'.' + domain) ; + cglpi = glpi.pop() ; + cpm = pm.pop() ; + } + if (domain != '' && domain.split('.').length > 1) { // common domain must be at least 'domain.com' and not 'com', otherwise some browser will not accept the CORS javascript + $('div[name=domain]').text(domain) ; + $('div[name=domain]').parent().attr('color', 'green'); + return; + } + } catch(ex) {} + $('div[name=domain]').text('".__('None!', 'processmaker')."') ; + $('div[name=domain]').parent().attr('color', 'red'); + }; + $('input[name=pm_server_URL]').on('keyup', setCommonDomain ) ; + setCommonDomain() ; + "); + echo "\n"; + + echo ""; + echo "".__('Verify SSL certificate', 'processmaker').""; + Dropdown::showYesNo("ssl_verify", $config->fields['ssl_verify']); + echo ""; + + echo ""; + echo "".__('Workspace Name', 'processmaker').""; + echo ""; + echo "\n"; + + echo ""; + echo "".__('Server administrator name', 'processmaker').""; + echo ""; + echo "\n"; + + echo ""; + echo "".__('Server administrator password', 'processmaker').""; + echo ""; + echo "  ".__('Clear'); + echo "\n"; + + echo ""; + echo "".__('Connection status', 'processmaker').""; + //$pm = new PluginProcessmakerProcessmaker; + + if ($config->fields['pm_server_URL'] != '' + && $config->fields['pm_workspace'] != '' + && $config->fields["pm_admin_user"] != '' + && ($PM_SOAP->login(true))) { + echo "".__('Test successful'); + $setup_ok = true; + } else { + // echo "".__('Test failed')."
".print_r($pm->lasterror, true); + echo "".__('Test failed')."
".print_r($PM_SOAP->lasterror, true); + } + echo "
\n"; + + echo "".__('SQL server setup', 'processmaker').""; + + echo ""; + echo "" . __('SQL server (MariaDB or MySQL)', 'processmaker') . ""; + echo ""; + echo "\n"; + + echo ""; + echo "" . __('Database name', 'processmaker') . ""; + echo ""; + echo "\n"; + + echo ""; + echo "" . __('SQL user', 'processmaker') . ""; + echo ""; + echo "\n"; + + echo ""; + echo "" . __('SQL password', 'processmaker') . ""; + echo ""; + echo "  ".__('Clear'); + echo "\n"; + + echo ""; + echo "".__('Connection status', 'processmaker').""; + if ($PM_DB->connected && isset($PM_DB->dbdefault) && $PM_DB->dbdefault != '') { + echo "".__('Test successful'); + } else { + echo "".__('Test failed'); + } + echo "\n"; + + echo "".__('Settings').""; + + echo ""; + echo "".__('Theme Name', 'processmaker').""; + Dropdown::showFromArray('pm_theme', $ui_theme, + ['value' => $config->fields['pm_theme']]); + echo ""; + + echo ""; + echo "".__('Main Task Category (edit to change name)', 'processmaker').""; + TaskCategory::dropdown(['name' => 'taskcategories_id', + 'display_emptychoice' => true, + 'value' => $config->fields['taskcategories_id']]); + echo "\n"; + + echo ""; + echo "".__('Task writer (edit to change name)', 'processmaker').""; + $rand = mt_rand(); + User::dropdown(['name' => 'users_id', + 'display_emptychoice' => true, + 'right' => 'all', + 'rand' => $rand, + 'value' => $config->fields['users_id']]); + + // this code adds the + sign to the form + echo ""; + echo Ajax::createIframeModalWindow('add_dropdown'.$rand, + User::getFormURL(), + ['display' => false]); + // end of + sign + + echo "\n"; + + echo ""; + echo "".__('Group in ProcessMaker which will contain all GLPI users', 'processmaker').""; + + $pmGroups = [ 0 => Dropdown::EMPTY_VALUE ]; + if ($PM_DB->connected) { + $res = $PM_DB->request([ + 'DISTINCT' => 'CON_ID', + 'FIELDS' => ['CON_ID', 'CON_VALUE'], + 'FROM' => 'CONTENT', + 'WHERE' => ['CON_CATEGORY' => 'GRP_TITLE'], + 'ORDER' => 'CON_VALUE' + ]); + foreach ($res as $row) { + $pmGroups[ $row['CON_ID'] ] = $row['CON_VALUE']; + } + Dropdown::showFromArray('pm_group_guid', $pmGroups, ['value' => $config->fields['pm_group_guid']]); + } 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 ""; + echo "".__('Maintenance mode').""; + Dropdown::showYesNo("maintenance", $config->fields['maintenance']); + echo ""; + + echo ""; + + echo "".__('ProcessMaker system information', 'processmaker').""; + if ($setup_ok) { + $info = $PM_SOAP->systemInformation( ); + echo ''.__('Version', 'processmaker').''.$info->version.''; + echo ''.__('Web server', 'processmaker').''.$info->webServer.''; + echo ''.__('Server name', 'processmaker').''.$info->serverName.''; + echo ''.__('PHP version', 'processmaker').''.$info->phpVersion.''; + echo ''.__('DB version', 'processmaker').''.$info->databaseVersion.''; + echo ''.__('DB server IP', 'processmaker').''.$info->databaseServerIp.''; + echo ''.__('DB name', 'processmaker').''.$info->databaseName.''; + echo ''.__('User browser', 'processmaker').''.$info->userBrowser.''; + echo ''.__('User IP', 'processmaker').''.$info->userIp.''; + } else { + echo ''.__('Version', 'processmaker').''.__('Not yet!', 'processmaker').''; + } + $config->showFormButtons(['candel' => false, 'colspan' => 1]); + + return false; + } + + + function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { + if ($item->getType()=='Config') { + return __('ProcessMaker', 'processmaker'); + } + return ''; + } + + + static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { + + if ($item->getType()=='Config') { + self::showConfigForm($item); + } + return true; + } + +} diff --git a/inc/db.class.php b/inc/db.class.php index 01f507c..31b43c4 100644 --- a/inc/db.class.php +++ b/inc/db.class.php @@ -1,26 +1,26 @@ -fields['pm_dbserver_name'] != '' - && $config->fields['pm_dbserver_user'] != '' - && $config->fields['pm_workspace'] != '' ) { - $this->dbhost = $config->fields['pm_dbserver_name']; - $this->dbuser = $config->fields['pm_dbserver_user']; - $this->dbpassword = Toolbox::decrypt($config->fields['pm_dbserver_passwd'], GLPIKEY); - $this->dbdefault = isset($config->fields['pm_dbname']) ? $config->fields['pm_dbname'] : ''; - parent::__construct(); - } - } - -} +fields['pm_dbserver_name'] != '' + && $config->fields['pm_dbserver_user'] != '' + && $config->fields['pm_workspace'] != '' ) { + $this->dbhost = $config->fields['pm_dbserver_name']; + $this->dbuser = $config->fields['pm_dbserver_user']; + $this->dbpassword = Toolbox::sodiumDecrypt($config->fields['pm_dbserver_passwd']); + $this->dbdefault = isset($config->fields['pm_dbname']) ? $config->fields['pm_dbname'] : ''; + parent::__construct(); + } + } + +} diff --git a/inc/glpikey.class.php b/inc/glpikey.class.php new file mode 100644 index 0000000..b1b8b60 --- /dev/null +++ b/inc/glpikey.class.php @@ -0,0 +1,48 @@ +fields; + } + + + /** + * Generate GLPI security key used for decryptable passwords + * and update values in DB if necessary. + * @return boolean + */ + public function migratePasswords() { + global $DB; + + // Fetch old key and migrate + $sodium_key = null; + $old_key = $this->getLegacyKey(); + + if ($DB instanceof DBmysql) { + return $this->migrateFieldsInDb($sodium_key, $old_key); + } + + return false; + } + + +} \ No newline at end of file diff --git a/inc/menu.class.php b/inc/menu.class.php index bb51c6b..f9642c9 100644 --- a/inc/menu.class.php +++ b/inc/menu.class.php @@ -1,58 +1,59 @@ - 'processes', - 'PluginProcessmakerCaselink' => 'caselinks' - ]; - - foreach ($itemtypes as $itemtype => $option) { - $menu['options'][$option]['title'] = $itemtype::getTypeName(Session::getPluralNumber()); - $menu['options'][$option]['page'] = $itemtype::getSearchURL(false); - $menu['options'][$option]['links']['search'] = $itemtype::getSearchURL(false); - if (Session::haveRightsOr("config", [READ, UPDATE])) { - $menu['options'][$option]['links']['config'] = PluginProcessmakerConfig::getFormURL(false); - } - switch ($itemtype) { - case 'PluginProcessmakerProcess': - - //if ($itemtype::canCreate()) { - // $menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); - //} - break; - case 'PluginProcessmakerCaselink': - if (Session::haveRight("plugin_processmaker_config", UPDATE)) { - $menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); - } - break; - - default : - $menu['options'][$option]['page'] = PluginProcessmakerProcess::getSearchURL(false); - break; - } - - } - return $menu; - } - - -} +
'processes', + 'PluginProcessmakerCaselink' => 'caselinks' + ]; + + foreach ($itemtypes as $itemtype => $option) { + $menu['options'][$option]['title'] = $itemtype::getTypeName(Session::getPluralNumber()); + $menu['options'][$option]['page'] = $itemtype::getSearchURL(false); + $menu['options'][$option]['links']['search'] = $itemtype::getSearchURL(false); + if (Session::haveRightsOr("config", [READ, UPDATE])) { + $menu['options'][$option]['links']['config'] = PluginProcessmakerConfig::getFormURL(false); + } + switch ($itemtype) { + case 'PluginProcessmakerProcess': + + //if ($itemtype::canCreate()) { + // $menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); + //} + break; + case 'PluginProcessmakerCaselink': + if (Session::haveRight("plugin_processmaker_config", UPDATE)) { + $menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); + } + break; + + default : + $menu['options'][$option]['page'] = PluginProcessmakerProcess::getSearchURL(false); + break; + } + + } + return $menu; + } + + +} diff --git a/inc/process.class.php b/inc/process.class.php index 704da48..fbf1118 100644 --- a/inc/process.class.php +++ b/inc/process.class.php @@ -1,967 +1,977 @@ - 1, - 'order' => 'ASC']; - - return $search; - } - - - /** - * Summary of refreshTasks - * will refresh (re-synch) all process task list - * @param array $post is the $_POST - * @return void - */ - function refreshTasks($post) { - global $PM_DB, $CFG_GLPI; - - if ($this->getFromDB( $post['id'] )) { - // here we are in the right process - // we need to get the tasks + content from PM db - //$config = PluginProcessmakerConfig::getInstance() ; - //$database = $config->fields['pm_workspace'] ; - //$translates = false; - $mapLangs = []; - $dbu = new DbUtils; - // if (class_exists('DropdownTranslation')) { - // to force rights to add translations - $_SESSION['glpi_dropdowntranslations']['TaskCategory']['name'] = 'name'; - $_SESSION['glpi_dropdowntranslations']['TaskCategory']['completename'] = 'completename'; - $_SESSION['glpi_dropdowntranslations']['TaskCategory']['comment'] = 'comment'; - //$translates = true; - // create a reversed map for languages - foreach ($CFG_GLPI['languages'] as $key => $valArray) { - $lg = locale_get_primary_language( $key ); - $mapLangs[$lg][] = $key; - $mapLangs[$key][] = $key; // also add complete lang - } - //} - $lang = locale_get_primary_language( $CFG_GLPI['language'] ); - $query = [ - 'SELECT' => ['TASK.TAS_UID', 'TASK.TAS_START', 'TASK.TAS_TYPE', 'CONTENT.CON_LANG', 'CONTENT.CON_CATEGORY', 'CONTENT.CON_VALUE'], - 'FROM' => 'TASK', - 'INNER JOIN' => [ - 'CONTENT' => [ - 'FKEY' => [ - 'CONTENT' => 'CON_ID', - 'TASK' => 'TAS_UID' - ] - ] - ], - 'WHERE' => [ - 'AND' => [ - 'TASK.TAS_TYPE' => ['NORMAL', 'SUBPROCESS'], - 'TASK.PRO_UID' => $this->fields['process_guid'], - 'CONTENT.CON_CATEGORY' => ['TAS_TITLE', 'TAS_DESCRIPTION'] - ] - ] - ]; - //if (!$translates) { - // $query['WHERE']['AND']['CONTENT.CON_LANG'] = $lang; - //} - //$query = "SELECT TASK.TAS_UID, TASK.TAS_START, TASK.TAS_TYPE, CONTENT.CON_LANG, CONTENT.CON_CATEGORY, CONTENT.CON_VALUE FROM TASK - // INNER JOIN CONTENT ON CONTENT.CON_ID=TASK.TAS_UID - // WHERE (TASK.TAS_TYPE = 'NORMAL' OR TASK.TAS_TYPE = 'SUBPROCESS') AND TASK.PRO_UID = '".$this->fields['process_guid']."' AND CONTENT.CON_CATEGORY IN ('TAS_TITLE', 'TAS_DESCRIPTION') ".($translates ? "" : " AND CONTENT.CON_LANG='$lang'")." ;"; - $taskArray = []; - $defaultLangTaskArray = []; - foreach ($PM_DB->request( $query ) as $task) { - if ($task['CON_LANG'] == $lang) { - $defaultLangTaskArray[$task['TAS_UID']][$task['CON_CATEGORY']] = $task['CON_VALUE']; - $defaultLangTaskArray[$task['TAS_UID']]['is_start'] = ($task['TAS_START'] == 'TRUE' ? 1 : 0); - $defaultLangTaskArray[$task['TAS_UID']]['is_subprocess'] = ($task['TAS_TYPE'] == 'SUBPROCESS' ? 1 : 0); - } else { - foreach ($mapLangs[ $task['CON_LANG'] ] as $valL) { - $taskArray[ $task['TAS_UID'] ][ $valL ][ $task['CON_CATEGORY'] ] = $task['CON_VALUE']; - } - } - } - - $pmtask = new PluginProcessmakerTaskCategory; - $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; - } - $inactivetasks = array_diff_key($tasks, $defaultLangTaskArray); - foreach ($inactivetasks as $taskkey => $task) { - // must verify if this taskcategory are used in a task somewhere - $objs = ['TicketTask', 'ProblemTask', 'ChangeTask']; - $countElt = 0; - foreach ($objs as $obj) { - $countElt += $dbu->countElementsInTable( $dbu->getTableForItemType($obj), "taskcategories_id = ".$task['taskcategories_id'] ); - if ($countElt != 0) { - // just set 'is_active' to 0 - $pmtask->Update( [ 'id' => $task['id'], 'is_start' => 0, 'is_active' => 0 ] ); - break; - } - } - if ($countElt == 0) { - // purge this category as it is not used anywhere - $taskCat = new TaskCategory; - $taskCat->delete([ 'id' => $task['taskcategories_id'] ], 1); - $pmTaskCat = new PluginProcessmakerTaskCategory; - $pmTaskCat->delete([ 'id' => $task['id'] ], 1); - } - } - - foreach ($defaultLangTaskArray as $taskGUID => $task) { - $pmTaskCat = new PluginProcessmakerTaskCategory; - $taskCat = new TaskCategory; - if ($pmTaskCat->getFromGUID( $taskGUID )) { - // got it then check names, and if != update - if ($taskCat->getFromDB( $pmTaskCat->fields['taskcategories_id'] )) { - // found it must test if should be updated - if ($taskCat->fields['name'] != $task['TAS_TITLE'] || $taskCat->fields['comment'] != $task['TAS_DESCRIPTION']) { - $taskCat->update( [ 'id' => $taskCat->getID(), 'name' => $PM_DB->escape($task['TAS_TITLE']), 'comment' => $PM_DB->escape($task['TAS_DESCRIPTION']), 'taskcategories_id' => $this->fields['taskcategories_id'] ] ); - } - if ($pmTaskCat->fields['is_start'] != $task['is_start']) { - $pmTaskCat->update( [ 'id' => $pmTaskCat->getID(), 'is_start' => $task['is_start'] ] ); - } - } else { - // taskcat must be created - $taskCat->add( [ 'is_recursive' => true, 'name' => $PM_DB->escape($task['TAS_TITLE']), 'comment' => $PM_DB->escape($task['TAS_DESCRIPTION']), 'taskcategories_id' => $this->fields['taskcategories_id'] ] ); - // update pmTaskCat - $pmTaskCat->update( [ 'id' => $pmTaskCat->getID(), 'taskcategories_id' => $taskCat->getID(), 'is_start' => $task['is_start'] ] ); - } - } else { - // should create a new one - // taskcat must be created - $taskCat->add( [ 'is_recursive' => true, 'name' => $PM_DB->escape($task['TAS_TITLE']), 'comment' => $PM_DB->escape($task['TAS_DESCRIPTION']), 'taskcategories_id' => $this->fields['taskcategories_id'] ] ); - // pmTaskCat must be created too - $pmTaskCat->add( ['plugin_processmaker_processes_id' => $this->getID(), - 'pm_task_guid' => $taskGUID, - 'taskcategories_id' => $taskCat->getID(), - 'is_start' => $task['is_start'], - 'is_active' => 1, - 'is_subprocess' => $task['is_subprocess'] - ] ); - } - // here we should take into account translations if any - if (isset($taskArray[ $taskGUID ])) { - foreach ($taskArray[ $taskGUID ] as $langTask => $taskL) { - // look for 'name' field - if ($loc_id = DropdownTranslation::getTranslationID( $taskCat->getID(), 'TaskCategory', 'name', $langTask )) { - if (DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'name', $langTask ) != $taskL[ 'TAS_TITLE' ]) { - // must be updated - $trans = new DropdownTranslation; - $trans->update( [ 'id' => $loc_id, 'field' => 'name', 'value' => $PM_DB->escape($taskL[ 'TAS_TITLE' ]), 'itemtype' => 'TaskCategory', 'items_id' => $taskCat->getID(), 'language' => $langTask ] ); - $trans->generateCompletename( [ 'itemtype' => 'TaskCategory', 'items_id' => $taskCat->getID(), 'language' => $langTask ] ); - } - } else { - // must be added - // must be updated - $trans = new DropdownTranslation; - $trans->add( [ 'items_id' => $taskCat->getID(), 'itemtype' => 'TaskCategory', 'language' => $langTask, 'field' => 'name', 'value' => $PM_DB->escape($taskL[ 'TAS_TITLE' ]) ] ); - $trans->generateCompletename( [ 'itemtype' => 'TaskCategory', 'items_id' => $taskCat->getID(),'language' => $langTask ] ); - } - - // look for 'comment' field - if ($loc_id = DropdownTranslation::getTranslationID( $taskCat->getID(), 'TaskCategory', 'comment', $langTask )) { - if (DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $langTask ) != $taskL[ 'TAS_DESCRIPTION' ]) { - // must be updated - $trans = new DropdownTranslation; - $trans->update( [ 'id' => $loc_id, 'field' => 'comment', 'value' => $PM_DB->escape($taskL[ 'TAS_DESCRIPTION' ]) , 'itemtype' => 'TaskCategory', 'items_id' => $taskCat->getID(), 'language' => $langTask] ); - } - } else { - // must be added - $trans = new DropdownTranslation; - $trans->add( [ 'items_id' => $taskCat->getID(), 'itemtype' => 'TaskCategory', 'language' => $langTask, 'field' => 'comment', 'value' => $PM_DB->escape($taskL[ 'TAS_DESCRIPTION' ]) ] ); - } - - } - } - } - - } - - } - - function prepareInputForAdd($input) { - global $PM_DB; - if (isset($input['name'])) { - $input['name'] = $PM_DB->escape($input['name']); - } - return $input; - } - - function prepareInputForUpdate($input) { - global $PM_DB; - if (isset($input['name'])) { - $input['name'] = $PM_DB->escape($input['name']); - } - return $input; - } - - function post_addItem() { - $this->getFromDB($this->getID()); - } - - function post_updateItem($history = 1) { - $this->getFromDB($this->getID()); - } - - /** - * Summary of refresh - * used to refresh process list and task category list - * @return void - */ - function refresh() { - global $DB, $PM_SOAP; - $dbu = new DbUtils; - $pmCurrentProcesses = []; - - // then refresh list of available process from PM to inner table - $PM_SOAP->login( true ); - $pmProcessList = $PM_SOAP->processList(); - - $config = PluginProcessmakerConfig::getInstance(); - $pmMainTaskCat = $config->fields['taskcategories_id']; - - // and get processlist from GLPI - if ($pmProcessList) { - foreach ($pmProcessList as $process) { - $glpiprocess = new PluginProcessmakerProcess; - if ($glpiprocess->getFromGUID($process->guid)) { - // then update it only if name has changed - if ($glpiprocess->fields['name'] != $process->name) { - $glpiprocess->update( [ 'id' => $glpiprocess->getID(), 'name' => $process->name] ); - } - // and check if main task category needs update - if (!$glpiprocess->fields['taskcategories_id']) { - // then needs to be added - $glpiprocess->addTaskCategory( $pmMainTaskCat ); - } else { - $glpiprocess->updateTaskCategory( $pmMainTaskCat ); - } - } else { - // create it - if (isset( $process->project_type )) { - $project_type = $process->project_type; - } else { - $project_type = 'classic'; - } - - if ($glpiprocess->add( [ 'process_guid' => $process->guid, 'name' => $process->name, 'project_type' => $project_type ])) { - // and add main task category for this process - $glpiprocess->addTaskCategory( $pmMainTaskCat ); - } - } - $pmCurrentProcesses[$glpiprocess->getID()] = $glpiprocess->getID(); - } - } - - // should de-activate other - $glpiCurrentProcesses = $dbu->getAllDataFromTable(self::getTable()); - // get difference between PM and GLPI - foreach (array_diff_key($glpiCurrentProcesses, $pmCurrentProcesses) as $key => $process) { - $proc = new PluginProcessmakerProcess; - $proc->getFromDB($key); - - // check if at least one case is existing for this process - $res = $DB->request( - PluginProcessmakerCase::getTable(), [ - 'plugin_processmaker_processes_id' => $key - ] - ); - //$query = "SELECT * FROM `".PluginProcessmakerCase::getTable()."` WHERE `plugin_processmaker_processes_id` = ".$key; - //$res = $DB->query($query); - if ($res->numrows() === 0) { - // and if no will delete the process - $proc->delete(['id' => $key]); - // delete main taskcat - $tmp = new TaskCategory; - $tmp->delete(['id' => $proc->fields['taskcategories_id']]); - - // must delete processes_profiles if any - $tmp = new PluginProcessmakerProcess_Profile; - $tmp->deleteByCriteria(['plugin_processmaker_processes_id' => $key]); - - // must delete any taskcategory and translations - $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; - $tmp->delete(['id' => $pmcat['taskcategories_id']]); - - // delete pmtaskcat - $tmp = new PluginProcessmakerTaskCategory; - $tmp->delete(['id' => $pmcat['id']]); - - // delete any translations - $tmp = new DropdownTranslation; - $tmp->deleteByCriteria(['itemtype' => 'TaskCategory', 'items_id' => $pmcat['taskcategories_id']]); - } - } else { - // set it as inactive - $proc->update(['id' => $key, 'is_active' => 0]); - } - } - - } - - /** - * Summary of updateTaskCategory - * Updates TaskCategory for current process, only if needed (i.e. name has changed) - * @param integer $pmMainTaskCat is the id of the main task category - * @return boolean true if update is done, false otherwise - */ - function updateTaskCategory($pmMainTaskCat) { - global $PM_DB; - $taskCat = new TaskCategory; - if ($taskCat->getFromDB( $this->fields['taskcategories_id'] ) && $taskCat->fields['name'] != $this->fields['name']) { - return $taskCat->update( [ 'id' => $taskCat->getID(), 'taskcategories_id' => $pmMainTaskCat, 'name' => $PM_DB->escape($this->fields['name'])] ); - } - return false; - } - - /** - * Summary of addTaskCategory - * Adds a new TaskCategory for $this process - * @param int $pmMainTaskCat is the main TaskCategory from PM configuration - * @return boolean true if TaskCategory has been created and updated into $this process, else otherwise - */ - function addTaskCategory($pmMainTaskCat) { - global $PM_DB; - $taskCat = new TaskCategory; - if ($taskCat->add( [ 'is_recursive' => true, 'taskcategories_id' => $pmMainTaskCat, 'name' => $PM_DB->escape($this->fields['name'])] )) { - return $this->update( [ 'id' => $this->getID(), 'taskcategories_id' => $taskCat->getID() ] ); - } - return false; - } - - - /** - * Print a good title for process pages - * add button for re-synchro of process list (only if rigths are w) - * @return void (display) - **/ - function title() { - global $CFG_GLPI; - - $buttons = []; - $title = __('Synchronize Process List', 'processmaker'); - - if ($this->canCreate()) { - $buttons["process.php?refresh=1"] = $title; - $title = ""; - Html::displayTitle($CFG_GLPI["root_doc"] . "/plugins/processmaker/pics/gears.png", $title, '', - $buttons); - } - - } - - /** - * Retrieve a Process from the database using its external id (unique index): process_guid - * @param string $process_guid guid of the process - * @return bool true if succeed else false - **/ - public function getFromGUID($process_guid) { - global $DB; - - $res = $DB->request( - $this->getTable(), [ - 'process_guid' => $process_guid - ] - ); - //$query = "SELECT * - // FROM `".$this->getTable()."` - // WHERE `process_guid` = '$process_guid'"; - - //if ($result = $DB->query($query)) { - if ($res) { - if ($res->numrows() != 1) {//if ($DB->numrows($result) != 1) { - return false; - } - $this->fields = $res->next(); //$DB->fetch_assoc($result); - if (is_array($this->fields) && count($this->fields)) { - return true; - } - } - return false; - } - - - /** - * Summary of rawSearchOptions - * @return mixed - */ - function rawSearchOptions() { - $tab = []; - - $tab[] = [ - 'id' => 'common', - 'name' => __('ProcessMaker', 'processmaker') - ]; - - $tab[] = [ - 'id' => '1', - 'table' => $this->getTable(), - 'field' => 'name', - 'name' => __('Name'), - 'datatype' => 'itemlink', - 'itemlink_type' => 'PluginProcessmakerProcess', - 'massiveaction' => false - ]; - - $tab[] = [ - 'id' => '8', - 'table' => $this->getTable(), - 'field' => 'is_active', - 'name' => __('Active'), - 'massiveaction' => true, - 'datatype' => 'bool' - ]; - - $tab[] = [ - 'id' => '4', - 'table' => $this->getTable(), - 'field' => 'comment', - 'name' => __('Comments'), - 'massiveaction' => true, - 'datatype' => 'text' - ]; - - $tab[] = [ - 'id' => '9', - 'table' => $this->getTable(), - 'field' => 'date_mod', - 'name' => __('Last update'), - 'massiveaction' => false, - 'datatype' => 'datetime' - ]; - - $tab[] = [ - 'id' => '10', - 'table' => $this->getTable(), - 'field' => 'process_guid', - 'name' => __('Process GUID', 'processmaker'), - 'massiveaction' => false, - 'datatype' => 'text' - ]; - - $tab[] = [ - 'id' => '11', - 'table' => $this->getTable(), - 'field' => 'project_type', - 'name' => __('Process type', 'processmaker'), - 'massiveaction' => false, - 'datatype' => 'specific' - ]; - - $tab[] = [ - 'id' => '12', - 'table' => $this->getTable(), - 'field' => 'hide_case_num_title', - 'name' => __('Hide case num. & title', 'processmaker'), - 'massiveaction' => true, - 'datatype' => 'bool' - ]; - - $tab[] = [ - 'id' => '13', - 'table' => $this->getTable(), - 'field' => 'insert_task_comment', - 'name' => __('Insert Task Category', 'processmaker'), - 'massiveaction' => true, - 'datatype' => 'bool' - ]; - - $tab[] = [ - 'id' => '14', - 'table' => 'glpi_itilcategories', - 'field' => 'completename', - 'name' => __('Category'), - 'datatype' => 'dropdown', - 'massiveaction' => false - ]; - - $tab[] = [ - 'id' => '15', - 'table' => $this->getTable(), - 'field' => 'type', - 'name' => __('Ticket type (self-service)', 'processmaker'), - 'searchtype' => 'equals', - 'datatype' => 'specific', - 'massiveaction' => false - ]; - - $tab[] = [ - 'id' => '16', - 'table' => $this->getTable(), - 'field' => 'is_incident', - 'name' => __('Visible in Incident for Central interface', 'processmaker'), - 'massiveaction' => true, - 'datatype' => 'bool' - ]; - - $tab[] = [ - 'id' => '17', - 'table' => $this->getTable(), - 'field' => 'is_request', - 'name' => __('Visible in Request for Central interface', 'processmaker'), - 'massiveaction' => true, - 'datatype' => 'bool' - ]; - - $tab[] = [ - 'id' => '18', - 'table' => $this->getTable(), - 'field' => 'is_change', - 'name' => __('Visible in Change', 'processmaker'), - 'massiveaction' => true, - 'datatype' => 'bool' - ]; - - $tab[] = [ - 'id' => '19', - 'table' => $this->getTable(), - 'field' => 'is_problem', - 'name' => __('Visible in Problem', 'processmaker'), - 'massiveaction' => true, - '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; - } - - - /** - * @since version 0.84 - * - * @param $field - * @param $values - * @param $options array - **/ - static function getSpecificValueToDisplay($field, $values, array $options = []) { - if (!is_array($values)) { - $values = [$field => $values]; - } - switch ($field) { - - case 'project_type': - return self::getProcessTypeName($values[$field]); - - case 'type': - return Ticket::getTicketTypeName($values[$field]); - } - return parent::getSpecificValueToDisplay($field, $values, $options); - } - - - /** - * Summary of getAllTypeArray - * @return string[] - */ - static function getAllTypeArray() { - - $tab = [self::CLASSIC => _x('process_type', 'Classic', 'processmaker'), - self::BPMN => _x('process_type', 'BPMN', 'processmaker')]; - - return $tab; - } - - - /** - * Summary of getProcessTypeName - * @param mixed $value - * @return mixed - */ - static function getProcessTypeName($value) { - - $tab = static::getAllTypeArray(true); - // Return $value if not defined - return (isset($tab[$value]) ? $tab[$value] : $value); - } - - - /** - * Summary of getTypeName - * @param mixed $nb - * @return mixed - */ - static function getTypeName($nb = 0) { - if ($nb>1) { - return __('Processes', 'processmaker'); - } - return __('Process', 'processmaker'); - } - - function defineTabs($options = []) { - - // $ong = array('empty' => $this->getTypeName(1)); - $ong = []; - $this->addDefaultFormTab($ong); - $this->addStandardTab(__CLASS__, $ong, $options); - - $this->addStandardTab('PluginProcessmakerTaskCategory', $ong, $options); - $this->addStandardTab('PluginProcessmakerProcess_Profile', $ong, $options); - //$this->addStandardTab('Ticket', $ong, $options); - //$this->addStandardTab('Log', $ong, $options); - - return $ong; - } - - function showForm ($ID, $options = ['candel'=>false]) { - global $DB, $CFG_GLPI; - - //if ($ID > 0) { - // $this->check($ID,READ); - //} - - //$canedit = $this->can($ID,UPDATE); - //$options['canedit'] = $canedit ; - - $this->initForm($ID, $options); - $this->showFormHeader($options); - - echo ""; - echo "".__("Name").""; - //Html::autocompletionTextField($this, "name"); - echo $this->fields["name"]; - echo ""; - echo "".__("Comments").""; - echo ""; - - echo ""; - echo "".__('Process GUID', 'processmaker').""; - echo $this->fields["process_guid"]; - echo ""; - - echo ""; - echo "".__('Active').""; - Dropdown::showYesNo("is_active", $this->fields["is_active"]); - echo ""; - - echo ""; - echo "".__('Hide case number and title in task descriptions', 'processmaker').""; - Dropdown::showYesNo("hide_case_num_title", $this->fields["hide_case_num_title"]); - echo ""; - - echo ""; - echo "".__('Insert Task Category comments in Task Description', 'processmaker').""; - 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"]); - echo ""; - - echo ""; - echo "".__('Visible in Request for Central interface', 'processmaker').""; - Dropdown::showYesNo("is_request", $this->fields["is_request"]); - echo ""; - - echo ""; - echo "".__('ITIL Category for Self-service interface (left empty to disable)', 'processmaker').""; - if (true) { // $canupdate || !$ID || $canupdate_descr - $opt = ['value' => $this->fields["itilcategories_id"]]; - - switch ($this->fields['type']) { - case Ticket::INCIDENT_TYPE : - $opt['condition'] = "`is_incident`='1'"; - break; - - case Ticket::DEMAND_TYPE : - $opt['condition'] = "`is_request`='1'"; - break; - - default : - break; - } - - echo ""; - if (isset($idticketcategorysearch)) { - $opt['rand'] = $idticketcategorysearch; - } - Dropdown::show('ITILCategory', $opt); - echo ""; - } else { - echo Dropdown::getDropdownName("glpi_itilcategories", $this->fields["itilcategories_id"]); - } - - echo "".__('Type for Self-service interface', 'processmaker').""; - if (true) { // $canupdate || !$ID - $idticketcategorysearch = mt_rand(); $opt = ['value' => $this->fields["type"]]; - $rand = Ticket::dropdownType('type', $opt, [], ['toupdate' => "search_".$idticketcategorysearch ]); - $opt = ['value' => $this->fields["type"]]; - $params = ['type' => '__VALUE__', - //'entity_restrict' => -1, //$this->fields['entities_id'], - 'value' => $this->fields['itilcategories_id'], - 'currenttype' => $this->fields['type']]; - - Ajax::updateItemOnSelectEvent("dropdown_type$rand", "show_category_by_type", - $CFG_GLPI["root_doc"]."/ajax/dropdownTicketCategories.php", - $params); - } else { - echo Ticket::getTicketTypeName($this->fields["type"]); - } - echo ""; - echo ""; - - echo ""; - echo "".__('Visible in Change', 'processmaker').""; - Dropdown::showYesNo("is_change", $this->fields["is_change"]); - echo ""; - - echo ""; - echo "".__('Visible in Problem', 'processmaker').""; - Dropdown::showYesNo("is_problem", $this->fields["is_problem"]); - echo ""; - - echo ""; - echo "".__('Process type (to be changed only if not up-to-date)', 'processmaker').""; - 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); - } - - - - /** - * Execute the query to select box with all glpi users where select key = name - * - * Internaly used by showGroup_Users, dropdownUsers and ajax/dropdownUsers.php - * - * @param $count true if execute an count(*), - * @param $search pattern - * - * @return DBmysqlIterator. - **/ - static function getSqlSearchResult ($count = true, $search = []) { - global $DB, $CFG_GLPI; - $query = []; - //$where = ''; - //$orderby = ''; - - if (isset($_REQUEST['condition']) && isset($_SESSION['glpicondition'][$_REQUEST['condition']])) { - //$where = ' WHERE '.$_SESSION['glpicondition'][$_REQUEST['condition']]; //glpi_plugin_processmaker_processes.is_active=1 '; - $query['WHERE']['AND'] = $_SESSION['glpicondition'][$_REQUEST['condition']]; - } - - if ($count) { - //$fields = " COUNT(DISTINCT glpi_plugin_processmaker_processes.id) AS cpt "; - $query['SELECT'] = ['COUNT' => 'glpi_plugin_processmaker_processes.id AS cpt']; - } else { - //$fields = " DISTINCT glpi_plugin_processmaker_processes.* "; - $query['SELECT'] = ['glpi_plugin_processmaker_processes.*']; - $query['ORDER'] ='glpi_plugin_processmaker_processes.name ASC'; - //$orderby = " ORDER BY glpi_plugin_processmaker_processes.name ASC"; - } - - if (!empty($search) && $search != $CFG_GLPI["ajax_wildcard"]) { - $query['WHERE']['AND']['OR']['glpi_plugin_processmaker_processes.name'] = $search; - $query['WHERE']['AND']['OR']['glpi_plugin_processmaker_processes.comment'] = $search; - //$where .= " AND (glpi_plugin_processmaker_processes.name $search - // OR glpi_plugin_processmaker_processes.comment $search) "; - } - $query['FROM'] = 'glpi_plugin_processmaker_processes'; - //$query = "SELECT $fields FROM glpi_plugin_processmaker_processes ".$where." ".$orderby.";"; - //return $DB->query($query); - //$r= $DB->request($query); - return $DB->request($query); - } - - /** - * Summary of getProcessName - * @param mixed $pid - * @param mixed $link - * @return mixed - */ - static function getProcessName($pid, $link = 0) { - global $DB, $CFG_GLPI; - $process=''; - if ($link==2) { - $process = ["name" => "", - "link" => "", - "comment" => ""]; - } - - $res = $DB->request('glpi_plugin_processmaker_processes', ['id' => $pid]); - //$query="SELECT * FROM glpi_plugin_processmaker_processes WHERE id=$pid"; - //$result = $DB->query($query); - //if ($result && $DB->numrows($result)==1) { - // $data = $DB->fetch_assoc($result); - if ($res && $res->numrows() == 1) { -// $processname = $res['name'];//$data["name"]; - $data = $res->next(); - $processname = $data["name"]; - if ($link == 2) { - $process["name"] = $processname; - $process["link"] = $CFG_GLPI["root_doc"]."/plugins/processmaker/front/process.form.php?id=".$pid; - $process["comment"] = __('Name')." : ".$processname."
".__('Comments'). - " : ".$data["comment"]."
"; - } else { - $process = $processname; - } - - } - return $process; - } - - /** - * retrieve the entities allowed to a process for a profile - * - * @param $processes_id Integer ID of the process - * @param $profiles_id Integer ID of the profile - * @param $child Boolean when true, include child entity when recursive right - * - * @return Array of entity ID - */ - static function getEntitiesForProfileByProcess($processes_id, $profiles_id, $child = false) { - global $DB; - $dbu = new DbUtils; - $res = $DB->request([ - 'SELECT' => ['entities_id', 'is_recursive'], - 'FROM' => 'glpi_plugin_processmaker_processes_profiles', - 'WHERE' => [ - 'AND' => [ - 'plugin_processmaker_processes_id' => $processes_id, - 'profiles_id' => $profiles_id - ] - ] - ]); - //$query = "SELECT `entities_id`, `is_recursive` - // FROM `glpi_plugin_processmaker_processes_profiles` - // WHERE `plugin_processmaker_processes_id` = '$processes_id' - // AND `profiles_id` = '$profiles_id'"; - - $entities = []; - //foreach ($DB->request($query) as $data) { - foreach ($res as $data) { - if ($child && $data['is_recursive']) { - foreach ($dbu->getSonsOf('glpi_entities', $data['entities_id']) as $id) { - $entities[$id] = $id; - } - } else { - $entities[$data['entities_id']] = $data['entities_id']; - } - } - return $entities; - } - - /** - * Summary of dropdown - * @param mixed $options - * @return mixed - */ - static function dropdown($options = []) { - global $CFG_GLPI; - - if (!isset($options['specific_tags']['process_restrict'])) { - $options['specific_tags']['process_restrict'] = 1; - } - $options['url'] = $CFG_GLPI["root_doc"].'/plugins/processmaker/ajax/dropdownProcesses.php'; - return Dropdown::show( __CLASS__, $options ); - - } - - - /** - * 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 "
"; - } -} - + 1, + 'order' => 'ASC']; + + return $search; + } + + + /** + * Summary of refreshTasks + * will refresh (re-synch) all process task list + * @param array $post is the $_POST + * @return void + */ + function refreshTasks($post) { + global $PM_DB, $CFG_GLPI; + + if ($this->getFromDB( $post['id'] )) { + // here we are in the right process + // we need to get the tasks + content from PM db + //$config = PluginProcessmakerConfig::getInstance() ; + //$database = $config->fields['pm_workspace'] ; + //$translates = false; + $mapLangs = []; + $dbu = new DbUtils; + // if (class_exists('DropdownTranslation')) { + // to force rights to add translations + $_SESSION['glpi_dropdowntranslations']['TaskCategory']['name'] = 'name'; + $_SESSION['glpi_dropdowntranslations']['TaskCategory']['completename'] = 'completename'; + $_SESSION['glpi_dropdowntranslations']['TaskCategory']['comment'] = 'comment'; + //$translates = true; + // create a reversed map for languages + foreach ($CFG_GLPI['languages'] as $key => $valArray) { + $lg = locale_get_primary_language( $key ); + $mapLangs[$lg][] = $key; + $mapLangs[$key][] = $key; // also add complete lang + } + //} + $lang = locale_get_primary_language( $CFG_GLPI['language'] ); + $query = [ + 'SELECT' => ['TASK.TAS_UID', 'TASK.TAS_START', 'TASK.TAS_TYPE', 'CONTENT.CON_LANG', 'CONTENT.CON_CATEGORY', 'CONTENT.CON_VALUE'], + 'FROM' => 'TASK', + 'INNER JOIN' => [ + 'CONTENT' => [ + 'FKEY' => [ + 'CONTENT' => 'CON_ID', + 'TASK' => 'TAS_UID' + ] + ] + ], + 'WHERE' => [ + 'AND' => [ + 'TASK.TAS_TYPE' => ['NORMAL', 'SUBPROCESS'], + 'TASK.PRO_UID' => $this->fields['process_guid'], + 'CONTENT.CON_CATEGORY' => ['TAS_TITLE', 'TAS_DESCRIPTION'] + ] + ] + ]; + //if (!$translates) { + // $query['WHERE']['AND']['CONTENT.CON_LANG'] = $lang; + //} + //$query = "SELECT TASK.TAS_UID, TASK.TAS_START, TASK.TAS_TYPE, CONTENT.CON_LANG, CONTENT.CON_CATEGORY, CONTENT.CON_VALUE FROM TASK + // INNER JOIN CONTENT ON CONTENT.CON_ID=TASK.TAS_UID + // WHERE (TASK.TAS_TYPE = 'NORMAL' OR TASK.TAS_TYPE = 'SUBPROCESS') AND TASK.PRO_UID = '".$this->fields['process_guid']."' AND CONTENT.CON_CATEGORY IN ('TAS_TITLE', 'TAS_DESCRIPTION') ".($translates ? "" : " AND CONTENT.CON_LANG='$lang'")." ;"; + $taskArray = []; + $defaultLangTaskArray = []; + foreach ($PM_DB->request( $query ) as $task) { + if ($task['CON_LANG'] == $lang) { + $defaultLangTaskArray[$task['TAS_UID']][$task['CON_CATEGORY']] = $task['CON_VALUE']; + $defaultLangTaskArray[$task['TAS_UID']]['is_start'] = ($task['TAS_START'] == 'TRUE' ? 1 : 0); + $defaultLangTaskArray[$task['TAS_UID']]['is_subprocess'] = ($task['TAS_TYPE'] == 'SUBPROCESS' ? 1 : 0); + } else { + foreach ($mapLangs[ $task['CON_LANG'] ] as $valL) { + $taskArray[ $task['TAS_UID'] ][ $valL ][ $task['CON_CATEGORY'] ] = $task['CON_VALUE']; + } + } + } + + $pmtask = new PluginProcessmakerTaskCategory; + $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; + } + $inactivetasks = array_diff_key($tasks, $defaultLangTaskArray); + foreach ($inactivetasks as $taskkey => $task) { + // must verify if this taskcategory are used in a task somewhere + $objs = ['TicketTask', 'ProblemTask', 'ChangeTask']; + $countElt = 0; + foreach ($objs as $obj) { + $countElt += $dbu->countElementsInTable( $dbu->getTableForItemType($obj), "taskcategories_id = ".$task['taskcategories_id'] ); + if ($countElt != 0) { + // just set 'is_active' to 0 + $pmtask->Update( [ 'id' => $task['id'], 'is_start' => 0, 'is_active' => 0 ] ); + break; + } + } + if ($countElt == 0) { + // purge this category as it is not used anywhere + $taskCat = new TaskCategory; + $taskCat->delete([ 'id' => $task['taskcategories_id'] ], 1); + $pmTaskCat = new PluginProcessmakerTaskCategory; + $pmTaskCat->delete([ 'id' => $task['id'] ], 1); + } + } + + foreach ($defaultLangTaskArray as $taskGUID => $task) { + $pmTaskCat = new PluginProcessmakerTaskCategory; + $taskCat = new TaskCategory; + if ($pmTaskCat->getFromGUID( $taskGUID )) { + // got it then check names, and if != update + if ($taskCat->getFromDB( $pmTaskCat->fields['taskcategories_id'] )) { + // found it must test if should be updated + if ($taskCat->fields['name'] != $task['TAS_TITLE'] || $taskCat->fields['comment'] != $task['TAS_DESCRIPTION']) { + $taskCat->update( [ 'id' => $taskCat->getID(), 'name' => $PM_DB->escape($task['TAS_TITLE']), 'comment' => $PM_DB->escape($task['TAS_DESCRIPTION']), 'taskcategories_id' => $this->fields['taskcategories_id'] ] ); + } + if ($pmTaskCat->fields['is_start'] != $task['is_start']) { + $pmTaskCat->update( [ 'id' => $pmTaskCat->getID(), 'is_start' => $task['is_start'] ] ); + } + } else { + // taskcat must be created + $taskCat->add( [ 'is_recursive' => true, 'name' => $PM_DB->escape($task['TAS_TITLE']), 'comment' => $PM_DB->escape($task['TAS_DESCRIPTION']), 'taskcategories_id' => $this->fields['taskcategories_id'] ] ); + // update pmTaskCat + $pmTaskCat->update( [ 'id' => $pmTaskCat->getID(), 'taskcategories_id' => $taskCat->getID(), 'is_start' => $task['is_start'] ] ); + } + } else { + // should create a new one + // taskcat must be created + $taskCat->add( [ 'is_recursive' => true, 'name' => $PM_DB->escape($task['TAS_TITLE']), 'comment' => $PM_DB->escape($task['TAS_DESCRIPTION']), 'taskcategories_id' => $this->fields['taskcategories_id'] ] ); + // pmTaskCat must be created too + $pmTaskCat->add( ['plugin_processmaker_processes_id' => $this->getID(), + 'pm_task_guid' => $taskGUID, + 'taskcategories_id' => $taskCat->getID(), + 'is_start' => $task['is_start'], + 'is_active' => 1, + 'is_subprocess' => $task['is_subprocess'] + ] ); + } + // here we should take into account translations if any + if (isset($taskArray[ $taskGUID ])) { + foreach ($taskArray[ $taskGUID ] as $langTask => $taskL) { + // look for 'name' field + if ($loc_id = DropdownTranslation::getTranslationID( $taskCat->getID(), 'TaskCategory', 'name', $langTask )) { + if (DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'name', $langTask ) != $taskL[ 'TAS_TITLE' ]) { + // must be updated + $trans = new DropdownTranslation; + $trans->update( [ 'id' => $loc_id, 'field' => 'name', 'value' => $PM_DB->escape($taskL[ 'TAS_TITLE' ]), 'itemtype' => 'TaskCategory', 'items_id' => $taskCat->getID(), 'language' => $langTask ] ); + $trans->generateCompletename( [ 'itemtype' => 'TaskCategory', 'items_id' => $taskCat->getID(), 'language' => $langTask ] ); + } + } else { + // must be added + // must be updated + $trans = new DropdownTranslation; + $trans->add( [ 'items_id' => $taskCat->getID(), 'itemtype' => 'TaskCategory', 'language' => $langTask, 'field' => 'name', 'value' => $PM_DB->escape($taskL[ 'TAS_TITLE' ]) ] ); + $trans->generateCompletename( [ 'itemtype' => 'TaskCategory', 'items_id' => $taskCat->getID(),'language' => $langTask ] ); + } + + // look for 'comment' field + if ($loc_id = DropdownTranslation::getTranslationID( $taskCat->getID(), 'TaskCategory', 'comment', $langTask )) { + if (DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $langTask ) != $taskL[ 'TAS_DESCRIPTION' ]) { + // must be updated + $trans = new DropdownTranslation; + $trans->update( [ 'id' => $loc_id, 'field' => 'comment', 'value' => $PM_DB->escape($taskL[ 'TAS_DESCRIPTION' ]) , 'itemtype' => 'TaskCategory', 'items_id' => $taskCat->getID(), 'language' => $langTask] ); + } + } else { + // must be added + $trans = new DropdownTranslation; + $trans->add( [ 'items_id' => $taskCat->getID(), 'itemtype' => 'TaskCategory', 'language' => $langTask, 'field' => 'comment', 'value' => $PM_DB->escape($taskL[ 'TAS_DESCRIPTION' ]) ] ); + } + + } + } + } + + } + + } + + function prepareInputForAdd($input) { + global $PM_DB; + if (isset($input['name'])) { + $input['name'] = $PM_DB->escape($input['name']); + } + return $input; + } + + function prepareInputForUpdate($input) { + global $PM_DB; + if (isset($input['name'])) { + $input['name'] = $PM_DB->escape($input['name']); + } + return $input; + } + + function post_addItem() { + $this->getFromDB($this->getID()); + } + + function post_updateItem($history = 1) { + $this->getFromDB($this->getID()); + } + + /** + * Summary of refresh + * used to refresh process list and task category list + * @return void + */ + function refresh() { + global $DB, $PM_SOAP; + $dbu = new DbUtils; + $pmCurrentProcesses = []; + + // then refresh list of available process from PM to inner table + $PM_SOAP->login( true ); + $pmProcessList = $PM_SOAP->processList(); + + $config = PluginProcessmakerConfig::getInstance(); + $pmMainTaskCat = $config->fields['taskcategories_id']; + + // and get processlist from GLPI + if ($pmProcessList) { + foreach ($pmProcessList as $process) { + $glpiprocess = new PluginProcessmakerProcess; + if ($glpiprocess->getFromGUID($process->guid)) { + // then update it only if name has changed + if ($glpiprocess->fields['name'] != $process->name) { + $glpiprocess->update( [ 'id' => $glpiprocess->getID(), 'name' => $process->name] ); + } + // and check if main task category needs update + if (!$glpiprocess->fields['taskcategories_id']) { + // then needs to be added + $glpiprocess->addTaskCategory( $pmMainTaskCat ); + } else { + $glpiprocess->updateTaskCategory( $pmMainTaskCat ); + } + } else { + // create it + if (isset( $process->project_type )) { + $project_type = $process->project_type; + } else { + $project_type = 'classic'; + } + + if ($glpiprocess->add( [ 'process_guid' => $process->guid, 'name' => $process->name, 'project_type' => $project_type ])) { + // and add main task category for this process + $glpiprocess->addTaskCategory( $pmMainTaskCat ); + } + } + $pmCurrentProcesses[$glpiprocess->getID()] = $glpiprocess->getID(); + } + } + + // should de-activate other + $glpiCurrentProcesses = $dbu->getAllDataFromTable(self::getTable()); + // get difference between PM and GLPI + foreach (array_diff_key($glpiCurrentProcesses, $pmCurrentProcesses) as $key => $process) { + $proc = new PluginProcessmakerProcess; + $proc->getFromDB($key); + + // check if at least one case is existing for this process + $res = $DB->request( + PluginProcessmakerCase::getTable(), [ + 'plugin_processmaker_processes_id' => $key + ] + ); + //$query = "SELECT * FROM `".PluginProcessmakerCase::getTable()."` WHERE `plugin_processmaker_processes_id` = ".$key; + //$res = $DB->query($query); + if ($res->numrows() === 0) { + // and if no will delete the process + $proc->delete(['id' => $key]); + // delete main taskcat + $tmp = new TaskCategory; + $tmp->delete(['id' => $proc->fields['taskcategories_id']]); + + // must delete processes_profiles if any + $tmp = new PluginProcessmakerProcess_Profile; + $tmp->deleteByCriteria(['plugin_processmaker_processes_id' => $key]); + + // must delete any taskcategory and translations + $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; + $tmp->delete(['id' => $pmcat['taskcategories_id']]); + + // delete pmtaskcat + $tmp = new PluginProcessmakerTaskCategory; + $tmp->delete(['id' => $pmcat['id']]); + + // delete any translations + $tmp = new DropdownTranslation; + $tmp->deleteByCriteria(['itemtype' => 'TaskCategory', 'items_id' => $pmcat['taskcategories_id']]); + } + } else { + // set it as inactive + $proc->update(['id' => $key, 'is_active' => 0]); + } + } + + } + + /** + * Summary of updateTaskCategory + * Updates TaskCategory for current process, only if needed (i.e. name has changed) + * @param integer $pmMainTaskCat is the id of the main task category + * @return boolean true if update is done, false otherwise + */ + function updateTaskCategory($pmMainTaskCat) { + global $PM_DB; + $taskCat = new TaskCategory; + if ($taskCat->getFromDB( $this->fields['taskcategories_id'] ) && $taskCat->fields['name'] != $this->fields['name']) { + return $taskCat->update( [ 'id' => $taskCat->getID(), 'taskcategories_id' => $pmMainTaskCat, 'name' => $PM_DB->escape($this->fields['name'])] ); + } + return false; + } + + /** + * Summary of addTaskCategory + * Adds a new TaskCategory for $this process + * @param int $pmMainTaskCat is the main TaskCategory from PM configuration + * @return boolean true if TaskCategory has been created and updated into $this process, else otherwise + */ + function addTaskCategory($pmMainTaskCat) { + global $PM_DB; + $taskCat = new TaskCategory; + if ($taskCat->add( [ 'is_recursive' => true, 'taskcategories_id' => $pmMainTaskCat, 'name' => $PM_DB->escape($this->fields['name'])] )) { + return $this->update( [ 'id' => $this->getID(), 'taskcategories_id' => $taskCat->getID() ] ); + } + return false; + } + + + /** + * Print a good title for process pages + * add button for re-synchro of process list (only if rigths are w) + * @return void (display) + **/ + function title() { + global $CFG_GLPI; + + $buttons = []; + $title = __('Synchronize Process List', 'processmaker'); + + if ($this->canCreate()) { + $buttons["process.php?refresh=1"] = $title; + $title = ""; + Html::displayTitle($CFG_GLPI["root_doc"] . "/plugins/processmaker/pics/gears.png", $title, '', + $buttons); + } + + } + + /** + * Retrieve a Process from the database using its external id (unique index): process_guid + * @param string $process_guid guid of the process + * @return bool true if succeed else false + **/ + public function getFromGUID($process_guid) { + global $DB; + + $res = $DB->request( + $this->getTable(), [ + 'process_guid' => $process_guid + ] + ); + //$query = "SELECT * + // FROM `".$this->getTable()."` + // WHERE `process_guid` = '$process_guid'"; + + //if ($result = $DB->query($query)) { + if ($res) { + if ($res->numrows() != 1) {//if ($DB->numrows($result) != 1) { + return false; + } + $this->fields = $res->next(); //$DB->fetch_assoc($result); + if (is_array($this->fields) && count($this->fields)) { + return true; + } + } + return false; + } + + + /** + * Summary of rawSearchOptions + * @return mixed + */ + function rawSearchOptions() { + $tab = []; + + $tab[] = [ + 'id' => 'common', + 'name' => __('ProcessMaker', 'processmaker') + ]; + + $tab[] = [ + 'id' => '1', + 'table' => $this->getTable(), + 'field' => 'name', + 'name' => __('Name'), + 'datatype' => 'itemlink', + 'itemlink_type' => 'PluginProcessmakerProcess', + 'massiveaction' => false + ]; + + $tab[] = [ + 'id' => '8', + 'table' => $this->getTable(), + 'field' => 'is_active', + 'name' => __('Active'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; + + $tab[] = [ + 'id' => '4', + 'table' => $this->getTable(), + 'field' => 'comment', + 'name' => __('Comments'), + 'massiveaction' => true, + 'datatype' => 'text' + ]; + + $tab[] = [ + 'id' => '9', + 'table' => $this->getTable(), + 'field' => 'date_mod', + 'name' => __('Last update'), + 'massiveaction' => false, + 'datatype' => 'datetime' + ]; + + $tab[] = [ + 'id' => '10', + 'table' => $this->getTable(), + 'field' => 'process_guid', + 'name' => __('Process GUID', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'text' + ]; + + $tab[] = [ + 'id' => '11', + 'table' => $this->getTable(), + 'field' => 'project_type', + 'name' => __('Process type', 'processmaker'), + 'massiveaction' => false, + 'datatype' => 'specific' + ]; + + $tab[] = [ + 'id' => '12', + 'table' => $this->getTable(), + 'field' => 'hide_case_num_title', + 'name' => __('Hide case num. & title', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; + + $tab[] = [ + 'id' => '13', + 'table' => $this->getTable(), + 'field' => 'insert_task_comment', + 'name' => __('Insert Task Category', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; + + $tab[] = [ + 'id' => '14', + 'table' => 'glpi_itilcategories', + 'field' => 'completename', + 'name' => __('Category (self-service)', 'processmaker'), + 'datatype' => 'dropdown', + 'massiveaction' => false + ]; + + $tab[] = [ + 'id' => '15', + 'table' => $this->getTable(), + 'field' => 'type', + 'name' => __('Ticket type (self-service)', 'processmaker'), + 'searchtype' => 'equals', + 'datatype' => 'specific', + 'massiveaction' => false + ]; + + $tab[] = [ + 'id' => '16', + 'table' => $this->getTable(), + 'field' => 'is_incident', + 'name' => __('Visible in Incident for Central interface', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; + + $tab[] = [ + 'id' => '17', + 'table' => $this->getTable(), + 'field' => 'is_request', + 'name' => __('Visible in Request for Central interface', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; + + $tab[] = [ + 'id' => '18', + 'table' => $this->getTable(), + 'field' => 'is_change', + 'name' => __('Visible in Change', 'processmaker'), + 'massiveaction' => true, + 'datatype' => 'bool' + ]; + + $tab[] = [ + 'id' => '19', + 'table' => $this->getTable(), + 'field' => 'is_problem', + 'name' => __('Visible in Problem', 'processmaker'), + 'massiveaction' => true, + '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; + } + + + /** + * @since version 0.84 + * + * @param $field + * @param $values + * @param $options array + **/ + static function getSpecificValueToDisplay($field, $values, array $options = []) { + if (!is_array($values)) { + $values = [$field => $values]; + } + switch ($field) { + + case 'project_type': + return self::getProcessTypeName($values[$field]); + + case 'type': + return Ticket::getTicketTypeName($values[$field]); + } + return parent::getSpecificValueToDisplay($field, $values, $options); + } + + + /** + * Summary of getAllTypeArray + * @return string[] + */ + static function getAllTypeArray() { + + $tab = [self::CLASSIC => _x('process_type', 'Classic', 'processmaker'), + self::BPMN => _x('process_type', 'BPMN', 'processmaker')]; + + return $tab; + } + + + /** + * Summary of getProcessTypeName + * @param mixed $value + * @return mixed + */ + static function getProcessTypeName($value) { + + $tab = static::getAllTypeArray(true); + // Return $value if not defined + return (isset($tab[$value]) ? $tab[$value] : $value); + } + + + /** + * Summary of getTypeName + * @param mixed $nb + * @return mixed + */ + static function getTypeName($nb = 0) { + if ($nb>1) { + return __('Processes', 'processmaker'); + } + return __('Process', 'processmaker'); + } + + function defineTabs($options = []) { + + // $ong = array('empty' => $this->getTypeName(1)); + $ong = []; + $this->addDefaultFormTab($ong); + $this->addStandardTab(__CLASS__, $ong, $options); + + $this->addStandardTab('PluginProcessmakerTaskCategory', $ong, $options); + $this->addStandardTab('PluginProcessmakerProcess_Profile', $ong, $options); + //$this->addStandardTab('Ticket', $ong, $options); + //$this->addStandardTab('Log', $ong, $options); + + return $ong; + } + + function showForm ($ID, $options = ['candel'=>false]) { + global $DB, $CFG_GLPI; + + //if ($ID > 0) { + // $this->check($ID,READ); + //} + + //$canedit = $this->can($ID,UPDATE); + //$options['canedit'] = $canedit ; + + $this->initForm($ID, $options); + $this->showFormHeader($options); + + echo ""; + echo "".__("Name").""; + //Html::autocompletionTextField($this, "name"); + echo $this->fields["name"]; + echo ""; + echo "".__("Comments").""; + echo ""; + + echo ""; + echo "".__('Process GUID', 'processmaker').""; + echo $this->fields["process_guid"]; + echo ""; + + echo ""; + echo "".__('Active').""; + Dropdown::showYesNo("is_active", $this->fields["is_active"]); + echo ""; + + echo ""; + echo "".__('Hide case number and title in task descriptions', 'processmaker').""; + Dropdown::showYesNo("hide_case_num_title", $this->fields["hide_case_num_title"]); + echo ""; + + echo ""; + echo "".__('Insert Task Category comments in Task Description', 'processmaker').""; + 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"]); + echo ""; + + echo ""; + echo "".__('Visible in Request for Central interface', 'processmaker').""; + Dropdown::showYesNo("is_request", $this->fields["is_request"]); + echo ""; + + echo ""; + echo "".__('Visible for Self-service interface (change ITIL Category for Self-service to enable / disable)', 'processmaker').""; + echo "".Dropdown::getYesNo($this->fields["itilcategories_id"]).""; + echo "".__('Type for Self-service interface', 'processmaker').""; + if (true) { // $canupdate || !$ID + + $rand = Ticket::dropdownType('type', + ['value' => $this->fields["type"], + ]); + $params = ['type' => '__VALUE__', + 'value' => $this->fields['itilcategories_id'], + 'currenttype' => $this->fields['type'], + 'condition' => ['is_helpdeskvisible' => '1'] + ]; + + Ajax::updateItemOnSelectEvent("dropdown_type$rand", "show_category_by_type", + $CFG_GLPI["root_doc"]."/plugins/processmaker/ajax/dropdownTicketCategories.php", + $params); + } else { + echo Ticket::getTicketTypeName($this->fields["type"]); + } + echo ""; + + echo ""; + echo "".__('ITIL Category for Self-service interface (left empty to disable)', 'processmaker').""; + if (true) { // $canupdate || !$ID || $canupdate_descr + $opt['value'] = $this->fields["itilcategories_id"]; + $opt['condition']['is_helpdeskvisible'] = '1'; + switch ($this->fields['type']) { + case Ticket::INCIDENT_TYPE : + $opt['condition']['is_incident'] = '1'; + break; + + case Ticket::DEMAND_TYPE : + $opt['condition']['is_request'] = '1'; + break; + + default : + break; + } + + echo ""; + Dropdown::show('ITILCategory', $opt); + echo ""; + } else { + echo Dropdown::getDropdownName("glpi_itilcategories", $this->fields["itilcategories_id"]); + } + + echo ""; + + echo ""; + echo "".__('Visible in Change', 'processmaker').""; + Dropdown::showYesNo("is_change", $this->fields["is_change"]); + echo ""; + + echo ""; + echo "".__('Visible in Problem', 'processmaker').""; + Dropdown::showYesNo("is_problem", $this->fields["is_problem"]); + echo ""; + + echo ""; + echo "".__('Process type (to be changed only if not up-to-date)', 'processmaker').""; + 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); + } + + + + /** + * Execute the query to select box with all glpi users where select key = name + * + * Internaly used by showGroup_Users, dropdownUsers and ajax/dropdownUsers.php + * + * @param $count true if execute an count(*), + * @param $search pattern + * + * @return DBmysqlIterator. + **/ + static function getSqlSearchResult ($count = true, $search = []) { + global $DB, $CFG_GLPI; + $query = []; + //$where = ''; + //$orderby = ''; + + if (isset($_REQUEST['condition']) && isset($_SESSION['glpicondition'][$_REQUEST['condition']])) { + //$where = ' WHERE '.$_SESSION['glpicondition'][$_REQUEST['condition']]; //glpi_plugin_processmaker_processes.is_active=1 '; + $query['WHERE']['AND'] = $_SESSION['glpicondition'][$_REQUEST['condition']]; + } + + if ($count) { + //$fields = " COUNT(DISTINCT glpi_plugin_processmaker_processes.id) AS cpt "; + $query['SELECT'] = ['COUNT' => 'glpi_plugin_processmaker_processes.id AS cpt']; + } else { + //$fields = " DISTINCT glpi_plugin_processmaker_processes.* "; + $query['SELECT'] = ['glpi_plugin_processmaker_processes.*']; + $query['ORDER'] ='glpi_plugin_processmaker_processes.name ASC'; + //$orderby = " ORDER BY glpi_plugin_processmaker_processes.name ASC"; + } + + if (!empty($search) && $search != $CFG_GLPI["ajax_wildcard"]) { + $query['WHERE']['AND']['OR']['glpi_plugin_processmaker_processes.name'] = $search; + $query['WHERE']['AND']['OR']['glpi_plugin_processmaker_processes.comment'] = $search; + //$where .= " AND (glpi_plugin_processmaker_processes.name $search + // OR glpi_plugin_processmaker_processes.comment $search) "; + } + $query['FROM'] = 'glpi_plugin_processmaker_processes'; + //$query = "SELECT $fields FROM glpi_plugin_processmaker_processes ".$where." ".$orderby.";"; + //return $DB->query($query); + //$r= $DB->request($query); + return $DB->request($query); + } + + /** + * Summary of getProcessName + * @param mixed $pid + * @param mixed $link + * @return mixed + */ + static function getProcessName($pid, $link = 0) { + global $DB, $CFG_GLPI; + $process=''; + if ($link==2) { + $process = ["name" => "", + "link" => "", + "comment" => ""]; + } + + $res = $DB->request('glpi_plugin_processmaker_processes', ['id' => $pid]); + //$query="SELECT * FROM glpi_plugin_processmaker_processes WHERE id=$pid"; + //$result = $DB->query($query); + //if ($result && $DB->numrows($result)==1) { + // $data = $DB->fetch_assoc($result); + if ($res && $res->numrows() == 1) { +// $processname = $res['name'];//$data["name"]; + $data = $res->next(); + $processname = $data["name"]; + if ($link == 2) { + $process["name"] = $processname; + $process["link"] = $CFG_GLPI["root_doc"]."/plugins/processmaker/front/process.form.php?id=".$pid; + $process["comment"] = __('Name')." : ".$processname."
".__('Comments'). + " : ".$data["comment"]."
"; + } else { + $process = $processname; + } + + } + return $process; + } + + /** + * retrieve the entities allowed to a process for a profile + * + * @param $processes_id Integer ID of the process + * @param $profiles_id Integer ID of the profile + * @param $child Boolean when true, include child entity when recursive right + * + * @return Array of entity ID + */ + static function getEntitiesForProfileByProcess($processes_id, $profiles_id, $child = false) { + global $DB; + $dbu = new DbUtils; + $res = $DB->request([ + 'SELECT' => ['entities_id', 'is_recursive'], + 'FROM' => 'glpi_plugin_processmaker_processes_profiles', + 'WHERE' => [ + 'AND' => [ + 'plugin_processmaker_processes_id' => $processes_id, + 'profiles_id' => $profiles_id + ] + ] + ]); + //$query = "SELECT `entities_id`, `is_recursive` + // FROM `glpi_plugin_processmaker_processes_profiles` + // WHERE `plugin_processmaker_processes_id` = '$processes_id' + // AND `profiles_id` = '$profiles_id'"; + + $entities = []; + //foreach ($DB->request($query) as $data) { + foreach ($res as $data) { + if ($child && $data['is_recursive']) { + foreach ($dbu->getSonsOf('glpi_entities', $data['entities_id']) as $id) { + $entities[$id] = $id; + } + } else { + $entities[$data['entities_id']] = $data['entities_id']; + } + } + return $entities; + } + + /** + * Summary of dropdown + * @param mixed $options + * @return mixed + */ + static function dropdown($options = []) { + global $CFG_GLPI; + + if (!isset($options['specific_tags']['process_restrict'])) { + $options['specific_tags']['process_restrict'] = 1; + } + $options['url'] = $CFG_GLPI["root_doc"].'/plugins/processmaker/ajax/dropdownProcesses.php'; + return Dropdown::show( __CLASS__, $options ); + + } + + + /** + * 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 2bcdb64..2e75a89 100644 --- a/inc/process_profile.class.php +++ b/inc/process_profile.class.php @@ -1,219 +1,204 @@ -getField('id'); - - $canshowentity = Session::haveRight("entity", READ); - $canedit = Session::haveRight('plugin_processmaker_config', UPDATE); - - $rand=mt_rand(); - - if ($canedit) { - echo "
"; - echo ""; - echo ""; - echo ""; - - echo ""; - - echo "
".__('Authorizations', 'processmaker')."
"; - echo ""; - Entity::Dropdown( ['entity' => $_SESSION['glpiactiveentities']]); - echo "".Profile::getTypeName(1).""; - Profile::dropdownUnder(['value' => Profile::getDefault()]); - echo "".__('Recursive').""; - Dropdown::showYesNo("is_recursive", 0); - echo ""; - echo ""; - echo "
"; - Html::closeForm(); - echo "
"; - } - $res = $DB->request([ - 'SELECT DISTINCT' => 'gpp.id AS linkID', - 'FIELDS' => [ - 'gpp.id AS linkID', - 'glpi_profiles.id', - 'glpi_profiles.name', - 'gpp.is_recursive', - 'glpi_entities.completename', - 'gpp.entities_id' - ], - 'FROM' => self::getTable() .' AS gpp', - 'LEFT JOIN' => [ - 'glpi_profiles' => [ - 'FKEY' => [ - 'glpi_profiles' => 'id', - 'gpp' => 'profiles_id' - ] - ], - 'glpi_entities' => [ - 'FKEY' => [ - 'glpi_entities' => 'id', - 'gpp' => 'entities_id' - ] - ] - ], - 'WHERE' => [ 'gpp.plugin_processmaker_processes_id' => $ID ], - 'ORDER' => [ 'glpi_profiles.name', 'glpi_entities.completename' ] - ]); - //$query = "SELECT DISTINCT gpp.`id` AS linkID, - // `glpi_profiles`.`id`, - // `glpi_profiles`.`name`, - // `gpp`.`is_recursive`, - // `glpi_entities`.`completename`, - // `gpp`.`entities_id` - // FROM `". self::getTable() ."` as gpp - // LEFT JOIN `glpi_profiles` - // ON (`gpp`.`profiles_id` = `glpi_profiles`.`id`) - // LEFT JOIN `glpi_entities` - // ON (`gpp`.`entities_id` = `glpi_entities`.`id`) - // WHERE `gpp`.`plugin_processmaker_processes_id` = '$ID' - // ORDER BY `glpi_profiles`.`name`, `glpi_entities`.`completename`"; - //$result = $DB->query($query); - //$num = $DB->numrows($result); - $num = $res->numrows(); - echo "
"; - Html::openMassiveActionsForm('mass'.__CLASS__.$rand); - - if ($canedit && $num) { - $massiveactionparams = ['num_displayed' => $num, - 'container' => 'mass'.__CLASS__.$rand]; - Html::showMassiveActions($massiveactionparams); - } - - if ($num > 0) { - echo ""; - $header_begin = ""; - $header_top = ''; - $header_bottom = ''; - $header_end = ''; - if ($canedit) { - $header_begin .= ""; - } - $header_end .= ""; - $header_end .= ""; - echo $header_begin.$header_top.$header_end; - - //while ($data = $DB->fetch_assoc($result)) { - foreach ($res as $data) { - echo ""; - if ($canedit) { - echo ""; - } - echo ""; - - if (Profile::canView()) { - $entname = "". - $data["name"].""; - } else { - $entname = $data["name"]; - } - - if ($data["is_recursive"]) { - $entname = sprintf('%1$s %2$s', $entname, "("); - if ($data["is_recursive"]) { - //TRANS: letter 'R' for Recursive - $entname = sprintf('%1$s%2$s', $entname, __('R')); - } - $entname = sprintf('%1$s%2$s', $entname, ")"); - } - echo ""; - echo ""; - } - echo $header_begin.$header_bottom.$header_end; - echo "
"; - $header_top .= Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); - $header_bottom .= Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); - $header_end .= ""._n('Entity', 'Entities', Session::getPluralNumber())."".sprintf('%1$s (%2$s)', Profile::getTypeName(Session::getPluralNumber()), - __('D=Dynamic, R=Recursive')); - $header_end .= "
"; - if (in_array($data["entities_id"], $_SESSION['glpiactiveentities'])) { - Html::showMassiveActionCheckBox(__CLASS__, $data["linkID"]); - } else { - echo " "; - } - echo ""; - - $link = $data["completename"]; - if ($_SESSION["glpiis_ids_visible"]) { - $link = sprintf('%1$s (%2$s)', $link, $data["entities_id"]); - } - - if ($canshowentity) { - echo ""; - } - echo $link.($canshowentity ? "" : ''); - echo "".$entname."
"; - } else { - echo ""; - echo ""; - echo "
".__('No item found')."
\n"; - } - - if ($canedit && $num) { - $massiveactionparams['ontop'] = false; - Html::showMassiveActions($massiveactionparams); - } - Html::closeForm(); - echo "
"; - } - - - /** - * Summary of prepareInputForAdd - * @param mixed $input - * @return mixed - */ - function prepareInputForAdd($input) { - $tmp = new self; - $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']]); - Session::addMessageAfterRedirect(__('Authorization not added: already existing!', 'processmaker'), true, WARNING); - - return []; // to cancel add - } - return $input; - } - -} +getField('id'); + + $canshowentity = Session::haveRight("entity", READ); + $canedit = Session::haveRight('plugin_processmaker_config', UPDATE); + + $rand=mt_rand(); + + if ($canedit) { + echo "
"; + echo ""; + echo ""; + echo ""; + + echo ""; + + echo "
".__('Authorizations', 'processmaker')."
"; + echo ""; + Entity::Dropdown( ['entity' => $_SESSION['glpiactiveentities']]); + echo "".Profile::getTypeName(1).""; + Profile::dropdownUnder(['value' => Profile::getDefault()]); + echo "".__('Recursive').""; + Dropdown::showYesNo("is_recursive", 0); + echo ""; + echo ""; + echo "
"; + Html::closeForm(); + echo "
"; + } + $res = $DB->request([ + 'SELECT' => [ + 'gpp.id AS linkID', + 'glpi_profiles.id', + 'glpi_profiles.name', + 'gpp.is_recursive', + 'glpi_entities.completename', + 'gpp.entities_id' + ], + 'DISTINCT' => true, + 'FROM' => self::getTable() .' AS gpp', + 'LEFT JOIN' => [ + 'glpi_profiles' => [ + 'FKEY' => [ + 'glpi_profiles' => 'id', + 'gpp' => 'profiles_id' + ] + ], + 'glpi_entities' => [ + 'FKEY' => [ + 'glpi_entities' => 'id', + 'gpp' => 'entities_id' + ] + ] + ], + 'WHERE' => [ 'gpp.plugin_processmaker_processes_id' => $ID ], + 'ORDER' => [ 'glpi_profiles.name', 'glpi_entities.completename' ] + ]); + $num = $res->numrows(); + echo "
"; + Html::openMassiveActionsForm('mass'.__CLASS__.$rand); + + if ($canedit && $num) { + $massiveactionparams = ['num_displayed' => $num, + 'container' => 'mass'.__CLASS__.$rand]; + Html::showMassiveActions($massiveactionparams); + } + + if ($num > 0) { + echo ""; + $header_begin = ""; + $header_top = ''; + $header_bottom = ''; + $header_end = ''; + if ($canedit) { + $header_begin .= ""; + } + $header_end .= ""; + $header_end .= ""; + echo $header_begin.$header_top.$header_end; + + //while ($data = $DB->fetch_assoc($result)) { + foreach ($res as $data) { + echo ""; + if ($canedit) { + echo ""; + } + echo ""; + + if (Profile::canView()) { + $entname = "". + $data["name"].""; + } else { + $entname = $data["name"]; + } + + if ($data["is_recursive"]) { + $entname = sprintf('%1$s %2$s', $entname, "("); + if ($data["is_recursive"]) { + //TRANS: letter 'R' for Recursive + $entname = sprintf('%1$s%2$s', $entname, __('R')); + } + $entname = sprintf('%1$s%2$s', $entname, ")"); + } + echo ""; + echo ""; + } + echo $header_begin.$header_bottom.$header_end; + echo "
"; + $header_top .= Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); + $header_bottom .= Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); + $header_end .= ""._n('Entity', 'Entities', Session::getPluralNumber())."".sprintf('%1$s (%2$s)', Profile::getTypeName(Session::getPluralNumber()), + __('D=Dynamic, R=Recursive')); + $header_end .= "
"; + if (in_array($data["entities_id"], $_SESSION['glpiactiveentities'])) { + Html::showMassiveActionCheckBox(__CLASS__, $data["linkID"]); + } else { + echo " "; + } + echo ""; + + $link = $data["completename"]; + if ($_SESSION["glpiis_ids_visible"]) { + $link = sprintf('%1$s (%2$s)', $link, $data["entities_id"]); + } + + if ($canshowentity) { + echo ""; + } + echo $link.($canshowentity ? "" : ''); + echo "".$entname."
"; + } else { + echo ""; + echo ""; + echo "
".__('No item found')."
\n"; + } + + if ($canedit && $num) { + $massiveactionparams['ontop'] = false; + Html::showMassiveActions($massiveactionparams); + } + Html::closeForm(); + echo "
"; + } + + + /** + * Summary of prepareInputForAdd + * @param mixed $input + * @return mixed + */ + function prepareInputForAdd($input) { + $tmp = new self; + $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']]); + Session::addMessageAfterRedirect(__('Authorization not added: already existing!', 'processmaker'), true, WARNING); + + return []; // to cancel add + } + return $input; + } + +} diff --git a/inc/processmaker.class.php b/inc/processmaker.class.php index 5774c3c..67363d1 100644 --- a/inc/processmaker.class.php +++ b/inc/processmaker.class.php @@ -1,3601 +1,3526 @@ -$value) { - if (is_array($value)) { - $temp = []; - foreach ($value as $k2 => $val2) { - $temp[ $key.'['.$k2.']' ] = $val2; - } - $vars = array_merge( $vars, http_formdata_flat_hierarchy($temp) ); - } else { - $vars[$key]=$value; - } - } - return $vars; - } - -} - -if (!function_exists('stripcslashes_deep')) { - /** - * Strip c slash for variable & array - * - * @param $value array or string: item to stripslashes (array or string) - * - * @return stripcslashes item - **/ - function stripcslashes_deep($value) { - - $value = is_array($value) ? - array_map('stripcslashes_deep', $value) : - stripcslashes($value); - - return $value; - } -} - -/** - * PluginProcessmakerProcessmaker short summary. - * - * PluginProcessmakerProcessmaker description. - * - * @version 1.0 - * @author MoronO - */ -class PluginProcessmakerProcessmaker extends CommonDBTM { - - var $serverURL; - - var $config; - private $pmSoapClient = null; - private $pmWorkspace = ""; - private $pmAdminSession = false; - - var $taskWriter = 0; - private $pm_group_guid = ''; // guid for default user group in Process Maker is used for all GLPI user synchronization into ProcessMaker - var $lasterror; - var $lang; - - static $rightname = ''; - - const ERROR_CREATING_CASE = 11; - const ERROR_NO_RIGHTS = 14; - const ERROR_CREATING_CASE2 = 100; - - - ///** - //* Return the table used to store this object - //* - //* @return string - //**/ - static function getTable($classname = null) { - - return "glpi_plugin_processmaker_processes"; - } - - - /** - * Summary of getAllTypeArray - * @return string[] - */ - static function getAllPMErrorArray() { - - $tab = [self::ERROR_CREATING_CASE => _x('errors', 'Error creating case!', 'processmaker'), - self::ERROR_NO_RIGHTS => _x('errors', 'Can\'t create case: no rights for it!', 'processmaker'), - self::ERROR_CREATING_CASE2 => _x('errors', 'Error creating case!', 'processmaker')]; - - return $tab; - } - - - /** - * Summary of getProcessTypeName - * @param mixed $value - * @return mixed - */ - static function getPMErrorMessage($value) { - - $tab = static::getAllPMErrorArray(); - // Return $value if not defined - return (isset($tab[$value]) ? $tab[$value] : $value); - } - - - /** - * Summary of addItemFollowup - * @param mixed $itemId - * @param mixed $txtForFollowup - * @param integer $users_id optional, if null will uses logged-in user - */ - public function addItemFollowup($itemtype, $itemId, $txtForFollowup, $users_id = null) { - global $DB; - $fu = new ITILFollowup();//new TicketFollowup(); - //$fu->getEmpty(); // to get default values - $input = $fu->fields; - if (isset( $txtForFollowup['GLPI_TICKET_FOLLOWUP_CONTENT']) && $txtForFollowup['GLPI_TICKET_FOLLOWUP_CONTENT'] != "" ) { - $input['content'] = $DB->escape($txtForFollowup['GLPI_TICKET_FOLLOWUP_CONTENT']); - } - if (isset( $txtForFollowup['GLPI_ITEM_FOLLOWUP_CONTENT']) && $txtForFollowup['GLPI_ITEM_FOLLOWUP_CONTENT'] != "" ) { - $input['content'] = $DB->escape($txtForFollowup['GLPI_ITEM_FOLLOWUP_CONTENT']); - } - if (isset( $txtForFollowup['GLPI_TICKET_FOLLOWUP_IS_PRIVATE'] ) && $txtForFollowup['GLPI_TICKET_FOLLOWUP_IS_PRIVATE'] != "") { - $input['is_private'] = $txtForFollowup['GLPI_TICKET_FOLLOWUP_IS_PRIVATE']; - } - if (isset( $txtForFollowup['GLPI_ITEM_FOLLOWUP_IS_PRIVATE'] ) && $txtForFollowup['GLPI_TICKET_FOLLOWUP_IS_PRIVATE'] != "") { - $input['is_private'] = $txtForFollowup['GLPI_ITEM_FOLLOWUP_IS_PRIVATE']; - } - if (isset( $txtForFollowup['GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID'] ) && $txtForFollowup['GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID'] != "") { - $input['requesttypes_id'] = $txtForFollowup['GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID']; - } - if (isset( $txtForFollowup['GLPI_ITEM_FOLLOWUP_REQUESTTYPES_ID'] ) && $txtForFollowup['GLPI_ITEM_FOLLOWUP_REQUESTTYPES_ID'] != "") { - $input['requesttypes_id'] = $txtForFollowup['GLPI_ITEM_FOLLOWUP_REQUESTTYPES_ID']; - } - $input['items_id'] = $itemId;//$input['tickets_id'] = $itemId; - $input['users_id'] = (isset($users_id) ? $users_id : Session::getLoginUserID( true )); // $this->taskWriter; - $input['itemtype'] = $itemtype; - - $fu->add( $input ); - } - - - /** - * Summary of openSoap - * @return true if open succeeded, and pmSoapClient is initialized - * false otherwise - */ - private function openSoap() { - - try { - if ($this->pmSoapClient == null) { - $this->lang = substr( $_SESSION["glpilanguage"], 0, 2); - if (strlen( $this->lang ) <> 2) { - $this->lang = "en"; // by default - } - $this->config = PluginProcessmakerConfig::getInstance(); - $this->pmWorkspace = $this->config->fields['pm_workspace']; - $this->serverURL = trim($this->config->fields['pm_server_URL'], '/').'/sys'.$this->config->fields['pm_workspace'].'/'.$this->lang.'/'.$this->config->fields['pm_theme']; - $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, - 'keep_alive' => false, - //'trace' => true, - //'exceptions' => false, - //'proxy_host' => 'localhost', - //'proxy_port' => 8889 - ]; - - $this->pmSoapClient = new SoapClient($wsdl, $options); - - } - - return true; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - $this->lasterror = $e; - return false; //null ; - } - } - - - /** - * Summary of getPMSessionID - * @param mixed $case_guid - * @return mixed - */ - function getPMSessionID() { - return $_SESSION["pluginprocessmaker"]["session"]['id']; - } - - /** - * Summary of login - * @param mixed $admin_or_user if true will be admin, otherwise is user name (or user id), or current user - * @return true if login has been correctly done with current GLPI user, or if a PM session was already open - * false if an exception occured (like SOAP error or PM login error) - */ - function login($admin_or_user = false, $case_guid = 'default') { - global $DB, $PM_DB; - try { - $locSession = new stdClass; // by default empty object - if ($this->openSoap( )) { - $cookie_lifetime = ini_get('session.cookie_lifetime'); - if ($cookie_lifetime == 0) { - $cookie_lifetime = 15 * 60; //= 15 minutes - } - if ($admin_or_user === true) { // admin rights has been requested, then force new login - $config = PluginProcessmakerConfig::getInstance(); - $locSession = $this->pmSoapClient->login( [ 'userid' => $config->fields['pm_admin_user'], 'password' => Toolbox::decrypt($config->fields['pm_admin_passwd'], GLPIKEY)] ); - if (is_object( $locSession ) && $locSession->status_code == 0) { - $_SESSION["pluginprocessmaker"]["session"]["admin"] = true; - $_SESSION["pluginprocessmaker"]["session"]["id"] = $locSession->message; - $_SESSION["pluginprocessmaker"]["session"]["date"] = $locSession->timestamp; - $this->pmAdminSession = true; - return true; - } - } else if (empty($_SESSION["pluginprocessmaker"]["session"]["date"]) || ($_SESSION["pluginprocessmaker"]["session"]["admin"] == true) - || $this->pmAdminSession == true - || date_add( date_create( $_SESSION["pluginprocessmaker"]["session"]["date"] ), new DateInterval( "PT".$cookie_lifetime."S" ) ) < date_create( date( "Y-m-d H:i:s" ) ) ) { - // get user from glpi_users table - $gusr = new User; - if (is_numeric($admin_or_user)) { - $gusr->getFromDB($admin_or_user); - } else if ($admin_or_user !== false) { - $gusr->getFromDBbyName($admin_or_user); - } else { - $gusr->getFromDB(Session::getLoginUserID()); - } - if ($gusr) { - // get user from glpi_plugin_processmaker_users table - $pmusr = new PluginProcessmakerUser; - $pmusr->getFromDB($gusr->getID()); - //if (!isset($pmusr->fields['password']) || $pmusr->fields['password'] == "") { - if (is_object($pmusr) && array_key_exists('pm_users_id', $pmusr->fields)) { - $pass = md5(Toolbox::encrypt( $gusr->getID().$gusr->getName().time(), GLPIKEY) ); - //$pmusr->update( array('id' => $pmusr->getID(), 'password' => $pass) ); - // and must be updated also in PM db - $PM_DB->update('RBAC_USERS', ['USR_PASSWORD' => $pass], ['USR_UID' => $pmusr->fields['pm_users_id']]); - //$PM_DB->query("UPDATE RBAC_USERS SET USR_PASSWORD='".$pass."' WHERE USR_UID='".$pmusr->fields['pm_users_id']."' "); - $PM_DB->update('USERS', ['USR_PASSWORD' => $pass], ['USR_UID' => $pmusr->fields['pm_users_id']]); - //$PM_DB->query("UPDATE USERS SET USR_PASSWORD='".$pass."' WHERE USR_UID='".$pmusr->fields['pm_users_id']."' "); - //} - //$locSession = $this->pmSoapClient->login( array( 'userid' => $gusr->fields['name'], 'password' => 'md5:'.$pmusr->fields['password']) ); - $locSession = $this->pmSoapClient->login( ['userid' => $gusr->fields['name'], 'password' => 'md5:'.$pass] ); - if (is_object( $locSession ) && $locSession->status_code == 0) { - $_SESSION["pluginprocessmaker"]["session"]["id"] = $locSession->message; - $_SESSION["pluginprocessmaker"]["session"]["date"] = $locSession->timestamp; - $_SESSION["pluginprocessmaker"]["session"]["admin"] = false; - $this->pmAdminSession = false; - return true; - } - } else { - Toolbox::logDebug( "Processmaker Plugin: $admin_or_user - User not existing in glpi_plugin_processmaker_users table." ); - return false; - } - } else { - Toolbox::logDebug( "Processmaker Plugin: $admin_or_user - User not existing in glpi_users table." ); - return false; - } - } else { - return true; // means a session is already existing in $_SESSION["pluginprocessmaker"]["session"] - } - } - - $this->pmAdminSession = false; - unset($_SESSION["pluginprocessmaker"]["session"]); - Toolbox::logDebug( "Processmaker Plugin: $admin_or_user - Soap problem: ". print_r( $locSession, true ) ); - $this->lasterror = $locSession; - return false; - } catch (Exception $e) { - $this->pmAdminSession = false; - unset($_SESSION["pluginprocessmaker"]["session"]); - Toolbox::logDebug( $e ); - return false; - } - } - - - /** - * Summary of processList - * Returns list of processes - * Embedded processList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#processList.28.29) - * A session must be open before with login() - * Normalizes output to an array, even when only one element is returned by PM - * @return an array of processListStruct objects - */ - function processList() { - try { - $pmProcessList = $this->pmSoapClient->processList( [ 'sessionId' => $this->getPMSessionID()] ); - if (isset( $pmProcessList->processes )) { - if (is_array( $pmProcessList->processes )) { - return $pmProcessList->processes; - } else { - return [ 0 => $pmProcessList->processes ]; - } - } - - return false; - - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of getCaseInfo - * returns information about a given case (as long as the logged in user has privileges to access the case). - * Embedded getCaseInfo() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#getCaseInfo.28.29) - * A session must be open before with login() - * Normalizes output of currentUsers to an array, even when only one element is returned by PM, - * Note: currentUsers field doesn't exist when case is CANCELLED - * @param $caseGuid: The case GUID, which can be obtained with the caseList() function - * @param $delIndex: The delegation index, which is a positive integer to identify the current task of the case. If empty then use current delIndex. - * @return a getCaseInfoResponse object, or false exception occured - */ - function getCaseInfo($caseGuid, $delIndex = '') { - try { - $pmCaseInfo = $this->pmSoapClient->getCaseInfo( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $caseGuid, 'delIndex' => $delIndex] ); - if (property_exists($pmCaseInfo, 'currentUsers')) { - switch ($pmCaseInfo->caseStatus) { - case 'DRAFT' : - case 'TO_DO': - // case 'CANCELLED' : - if (is_object( $pmCaseInfo->currentUsers )) { - $pmCaseInfo->currentUsers = [ 0 => $pmCaseInfo->currentUsers ]; - } - if ($pmCaseInfo->currentUsers[0]->delThreadStatus == 'PAUSE') { - $pmCaseInfo->caseStatus = "PAUSED"; - } - break; - } - } - return $pmCaseInfo; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - - } - - /** - * Summary of routeCase - * routes a case (i.e., moves the case to the next task in the process according to its routing rules). - * Embedded routeCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#routeCase.28.29) - * A session must be open before with login() - * @param $case_guid string The case GUID, which can be obtained with the caseList() function - * @param $delIndex integer The delegation index, which is a positive integer to identify the current task of the case. If empty then use current delIndex. - * @return stdClass|boolean routeCaseResponse object or false when exception occured. routing is normalized to be always an array of routeListStruct - */ - function routeCase($case_guid, $delIndex) { - try { - $pmRouteCaseResponse = $this->pmSoapClient->routeCase( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $case_guid, 'delIndex' => $delIndex] ); - if ($pmRouteCaseResponse->status_code != 0) { - Toolbox::logDebug( 'routeCase res:', $pmRouteCaseResponse ); - } - - if (property_exists( $pmRouteCaseResponse, 'routing' ) && is_object( $pmRouteCaseResponse->routing )) { - $pmRouteCaseResponse->routing = [ 0 => $pmRouteCaseResponse->routing]; - } - - return $pmRouteCaseResponse; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of triggerList - * Returns list of triggers - * Embedded triggerList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#triggerList.28.29) - * A session must be open before with login() - * Normalizes output to an array, even when only one element is returned by PM - * @return an array of triggerListStruct objects, or false when exception occured - */ - function triggerList() { - try { - $pmTriggerList = $this->pmSoapClient->triggerList( [ 'sessionId' => $this->getPMSessionID()] ); - if (is_array( $pmTriggerList->triggers )) { - return $pmTriggerList->triggers; - } else { - return [ 0 => $pmTriggerList->triggers ]; - } - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of taskList - * Returns list of tasks to which the logged-in user is assigned - * Embedded taskList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#taskList.28.29) - * A session must be open before with login() - * Normalizes output to an array, even when only one element is returned by PM - * @return an array of taskListStruct objects, or false when exception occured - */ - function taskList() { - try { - $pmTaskList = $this->pmSoapClient->taskList( [ 'sessionId' => $this->getPMSessionID()] ); - - if (is_array( $pmTaskList->tasks )) { - return $pmTaskList->tasks; - } else { - return [ 0 => $pmTaskList->tasks ]; - } - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - - /** - * Summary of taskCase - * Returns list of tasks to which the logged-in user is assigned - * Embedded taskList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#taskList.28.29) - * A session must be open before with login() - * Normalizes output to an array, even when only one element is returned by PM - * @return array of taskListStruct objects, or false when exception occured - */ - function taskCase($case_guid) { - try { - $pmTaskCase = $this->pmSoapClient->taskCase( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $case_guid ] ); - - if (is_array( $pmTaskCase->taskCases )) { - return $pmTaskCase->taskCases; - } else { - return [ 0 => $pmTaskCase->taskCases ]; - } - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of claimCase - * @param mixed $case_guid - * @param mixed $delIndex - * @return mixed - */ - function claimCase($case_guid, $delIndex) { - try { - $pmClaimCase = $this->pmSoapClient->claimCase( [ 'sessionId' => $this->getPMSessionID(), 'guid' => $case_guid, 'delIndex' => $delIndex] ); - return $pmClaimCase; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of unpauseCase - * Unpauses a specified case. - * Embedded UnpauseCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#UnpauseCase.28.29) - * A session must be open before with login() - * Normalizes output to an array, even when only one element is returned by PM - * @param $caseGuid The unique ID of the case. - * @param $delIndex The delegation index of the current task in the case. - * @param $userGuid The unique ID of the user who will unpause the case. - * @return an array of UnpauseCaseStruct, or false when exception occured - */ - function unpauseCase($caseGuid, $delIndex, $userGuid) { - try { - $pmUnpauseCase = $this->pmSoapClient->unpauseCase( [ 'sessionId' => $this->getPMSessionID(), 'caseUid' => $caseGuid, 'delIndex' => $delIndex, 'userUid' => $userGuid] ); - - if (is_array( $pmUnpauseCase->processes )) { - return $pmUnpauseCase->processes; - } else { - return [ 0 => $pmUnpauseCase->processes ]; - } - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of caseList - * returns a list of the cases for the logged-in user. - * Embedded caseList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#caseList.28.29) - * A session must be open before with login() - * Normalizes output to an array, even when only one element is returned by PM - * @return an array of cases, or false when exception occured - */ - function caseList() { - try { - $pmCaseList = $this->pmSoapClient->caseList( [ 'sessionId' => $this->getPMSessionID()] ); - - if (is_array( $pmCaseList->cases )) { - return $pmCaseList->cases; - } else { - return [ 0 => $pmCaseList->cases ]; - } - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of systemInformation - * returns information about the PM system - * Embedded systemInformation() PM web service call (definition: http://wiki.processmaker.com/index.php/ProcessMaker_WSDL_Web_Services#systemInformation.28.29) - * A session must be open before with login() - * @return an object containing information, or false when exception occured - */ - function systemInformation() { - try { - $pmSystemInfo = $this->pmSoapClient->systemInformation( [ 'sessionId' => $this->getPMSessionID()] ); - return $pmSystemInfo; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of reassignCase - * reassigns a case to a different user. Note that the logged-in user needs to have the PM_REASSIGNCASE permission in his/her role in order to be able to reassign the case. - * Embedded caseList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#reassignCase.28.29) - * A session must be open before with login() - * @param $caseGuid The case GUID, which can be obtained with the caseList() function. - * @param $delIndex The current delegation index number of the case, which can be obtained with the caseList() function. - * @param $userGuidSource The PM user GUID who is currently assigned the case, which can be obtained with the caseList() function. - * @param $userGuidTarget The PM target user GUID who will be newly assigned to the case, which can be obtained with userList(). The case can only be reassigned to a user who is one of the assigned users or ad-hoc users to the current task in the case. - * @return stdClass, a pmResponse object, or false when exception occured - */ - function reassignCase($caseGuid, $delIndex, $userGuidSource, $userGuidTarget) { - try { - $pmResults = $this->pmSoapClient->reassignCase( ['sessionId' => $this->getPMSessionID(), - 'caseId' => $caseGuid, - 'delIndex' => $delIndex, - 'userIdSource' => $userGuidSource, - 'userIdTarget'=> $userGuidTarget] ); - return $pmResults; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - - /** - * Summary of deleteCase - * Deletes a case - * Embedded deleteCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#deleteCase.28.29) - * A session must be open before with login() - * Beware that at any time you may delete a case!!! - * @param $caseUid The case ID, which can be obtained with the caseList() function. - * @return A deleteCaseResponse object, or false when exception occured - */ - function deleteCase($caseUid) { - try { - $deleteCaseResponse = $this->pmSoapClient->deleteCase( [ 'sessionId' => $this->getPMSessionID(), 'caseUid' => $caseUid] ); - return $deleteCaseResponse; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - - /** - * Summary of cancelTask - * Cancels a task - * Embedded cancelCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#cancelCase.28.29) - * A session must be open before with login() - * Beware that this will only cancel the task with delIndex - * in the case of // tasks you must call cancelTask for each running task. - * in the case of one and only one task running, then it will cancel the case - * @param $caseUid The case ID, which can be obtained with the caseList() function. - * @param $delIndex The delegation index of the current task in the case. - * @param $userUid: The unique ID of the user who will unpause the case. - * @return A cancelCaseResponse object, or false when exception occured - */ - function cancelTask($caseUid, $delIndex, $userUid) { - try { - $cancelTaskResponse = $this->pmSoapClient->cancelCase( [ 'sessionId' => $this->getPMSessionID(), 'caseUid' => $caseUid, 'delIndex' => $delIndex, 'userUid' => $userUid] ); - return $cancelTaskResponse; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - - /** - * Summary of cancelCase - * Cancels a case - * Embedded cancelCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#cancelCase.28.29) - * A session must be open before with login() - * Beware that this will cancel all running task - * in the case of // tasks you must call cancelCase for each running task. - * in the case of one and only one task is running, then it will cancel the case - * @param $caseUid The case ID, which can be obtained with the caseList() function. - * @param $delIndex The delegation index of the current task in the case. - * @param $userUid: The unique ID of the user who will unpause the case. - * @return A cancelCaseResponse object, or false when exception occured - */ - function cancelCase($caseUid) { - try { - $pmCaseInfo = $this->getCaseInfo( $caseUid ); - if ($pmCaseInfo->status_code == 0) { - foreach ($pmCaseInfo->currentUsers as $pmUser) { - $pmCancelTask = $this->cancelTask( $caseUid, $pmUser->delIndex, $pmUser->userId ); - if ($pmCancelTask->status_code != 0) { - return $pmCancelTask; - } - } - } - return $pmCancelTask; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - - /** - * Summary of newCaseImpersonate - * Starts a new case under the name of the logged-in user. - * The task that will be started is the default one (=must be unique in process definition)! - * logged-in user must be assigned to this task, otherwise use newCaseImpersonate() to start the case. - * New case is started with DRAFT status. - * Embedded newCaseImpersonate() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#newCaseImpersonate.28.29) - * A session must be open before with login(), in order to call this function. - * @param $processes_id integer: The GLPI ID of the process that must be used to start a new case - * @param $userId The ID of the user who initiates the case, which can be obtained with userList(). - * @param $vars an array of associative variables (name => value) that will be injected into the case as case variables - * @return A newCaseResponse object, or false when exception occured - */ - function newCaseImpersonate($processes_id, $userId, $vars = null) { - try { - $this->getFromDB($processes_id); - - if ($vars !== null) { - $aVars = []; - foreach ($vars as $key => $val) { - $obj = new variableStruct(); - $obj->name = $key; - $obj->value = $val; - $aVars[] = $obj; - } - } else { - $aVars = ''; - } - - $newCaseResponse = $this->pmSoapClient->newCaseImpersonate( [ 'sessionId' => $this->getPMSessionID(), 'processId'=> $this->fields['process_guid'], 'userId' => $userId, 'taskId'=>'', 'variables'=> $aVars] ); - return $newCaseResponse; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of newCase - * Starts a new case under the name of the logged-in user. - * The task that will be started is the default one (=must be unique in process definition)! - * logged-in user must be assigned to this task, otherwise use newCaseImpersonate() to start the case. - * New case is started with DRAFT status. - * Embedded newCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#newCase.28.29) - * A session must be open before with login() - * @param $processes_id integer: the GLPI ID of the process which will be instantied into a case - * @param array $vars an array of associative variables (name => value) that will be injected into the case as case variables - * @return boolean|newCaseResponse: false when exception occured - */ - function newCase($processes_id, $vars = []) { - try { - $this->getFromDB($processes_id); - - $aVars = []; - foreach ($vars as $key => $val) { - $obj = new variableStruct(); - $obj->name = $key; - $obj->value = $val; - $aVars[] = $obj; - } - - $newCaseResponse = $this->pmSoapClient->newCase( [ 'sessionId' => $this->getPMSessionID(), 'processId'=> $this->fields['process_guid'], 'taskId'=>'', 'variables'=> $aVars] ); - - return $newCaseResponse; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of sendVariables - * Sends variables to a case. - * Embedded sendVariables() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#sendVariables.28.29) - * A session must be open before with login() - * @param string $caseGuid The GUID of the case - * @param array $vars an array of associative variables (name => value) that will be injected into the case as case variables - * @return A pmResponse object, or false when exception occured - */ - function sendVariables($caseGuid, $vars = []) { - if (count( $vars ) == 0) { // nothing to send - return true; - } - try { - $aVars = []; - foreach ($vars as $key => $val) { - $obj = new variableStruct(); - $obj->name = $key; - if (is_array( $val )) { - $obj->value = join( "|", $val ); - } else { - $obj->value = $val; - } - $aVars[] = $obj; - } - - $pmResponse = $this->pmSoapClient->sendVariables( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $caseGuid, 'variables'=> $aVars] ); - - return $pmResponse; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - - - /** - * Summary of getVariables - * Gets variables from a case. - * Embedded getVariables() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#getVariables.28.29) - * A session must be open before with login() - * @param string $case_guid The uID of the case - * @param array $vars an array of variable name that will be read from the case as case variables Normalizes output to an array, even when only one element is returned by PM Normalizes output to an array, even when only one element is returned by PM - * Normalizes output to an array, even when only one element is returned by PM - * @return array: an associative array (variable_name => value), or false when exception occured. The return array can be empty if requested variables are not found. - */ - function getVariables($case_guid, $vars = []) { - try { - $aVars = []; - foreach ($vars as $key => $name) { - $obj = new getVariableStruct(); - $obj->name = $name; - $aVars[] = $obj; - } - - $pmvariableListResponse = $this->pmSoapClient->getVariables( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $case_guid, 'variables'=> $aVars] ); - - $variablesArray = []; - - if ($pmvariableListResponse->status_code == 0 && isset( $pmvariableListResponse->variables )) { - if (is_array( $pmvariableListResponse->variables )) { - foreach ($pmvariableListResponse->variables as $variable) { - $variablesArray[$variable->name] = $variable->value; - } } else { - $variablesArray[$pmvariableListResponse->variables->name] = $pmvariableListResponse->variables->value; - } - } - - return $variablesArray; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of groupList - * returns a list of the groups. For privileges to see the list, the logged-in user must have the PM_USERS permission in his/her role. - * Embedded groupList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#groupList.28.29) - * A session must be open before with login() - * Normalizes output to an array, even when only one element is returned by PM - * @return an array of groupListStruct, or false when exception occured - */ - function groupList() { - try { - $pmGroupList = $this->pmSoapClient->groupList( [ 'sessionId' => $this->getPMSessionID()] ); - - if (is_array( $pmGroupList->groups )) { - return $pmGroupList->groups; - } else { - return [ 0 => $pmGroupList->groups ]; - } - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of assignUserToGroup - * assigns a user to a group. For privileges to assign a user, the logged-in user must have the PM_USERS permission in his/her role. - * Embedded assignUserToGroup() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#assignUserToGroup.28.29) - * A session must be open before with login() - * @param $userId a Processmaker user id (see userList()) - * @param $groupId a Processmaker group id (see groupList()) - * @return A pmResponse object, or false when exception occured - */ - function assignUserToGroup($userId, $groupId) { - try { - $pmResults = $this->pmSoapClient->assignUserToGroup([ 'sessionId' => $this->getPMSessionID(), - 'userId' => $userId, - 'groupId' => $groupId - ] ); - return $pmResults; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of createGroup - * creates a new group. For privileges to create a group, the logged-in user must have the PM_USERS permission in his/her role. - * group will be created as 'ACTIVE' - * Embedded createGroup() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#createGroup.28.29) - * A session must be open before with login() - * @param $name: the name of the group to be created - * @return A pmResponse object, or false when exception occured - */ - function createGroup($name) { - try { - $pmResults = $this->pmSoapClient->createGroup([ 'sessionId' => $this->getPMSessionID(), - 'name' => $name ] ); - return $pmResults; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of updateGroup - * updates group directly into Processmaker DB - * @param $group_id: guid of the pm group - * @param $groupStatus: new status to be set to $group_id, could be 'ACTIVE' or 'INACTIVE' - * @return true if group status has been modified, false otherwise - */ - function updateGroup($group_id, $groupStatus) { - global $PM_DB; - $PM_DB->update('GROUPWF', ['GRP_STATUS' => $groupStatus], ['GRP_UID' => $group_id]); - //$query = "UPDATE GROUPWF SET GRP_STATUS='$groupStatus' WHERE GRP_UID='$group_id';"; - //$PM_DB->query( $query ); - if ($PM_DB->affected_rows != 1) { - return false; - } else { - return true; - } - } - - /** - * Summary of userList - * returns a list of the Processmaker users. For privileges to see the list, the logged-in user must have the PM_USERS permission in his/her role. - * Embedded userList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#userList.28.29) - * A session must be open before with login() - * Normalizes output to an array, even if only one element is returned by PM - * @return an array of userListStruct, or false when exception occured - */ - function userList() { - try { - $pmUserList = $this->pmSoapClient->userList( [ 'sessionId' => $this->getPMSessionID()] ); - - if (is_array( $pmUserList->users )) { - return $pmUserList->users; - } else { - return [ 0 => $pmUserList->users ]; - } - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of createUser - * creates a new user. For privileges to create a user, the logged-in user must have the PM_USERS permission in his/her role. - * Embedded createUser() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#createUser.28.29) - * A session must be open before with login() - * @param $userId The username for the new user. The unique ID for the user will be automatically generated. Is the user Windows login! - * @param $firstname The user's first name. If empty (== null or == "") will default to $userId. - * @param $lastname The user's last name. If empty (== null or == "") will default to $userId. - * @param $email The user's email address. If empty (== null or == "") will default to $userId@DoNotReply.com. - * @param $role The user's role, such as 'PROCESSMAKER_ADMIN', 'PROCESSMAKER_MANAGER' or 'PROCESSMAKER_OPERATOR'. Possible values can be looked up with the roleList() function. - * @param $password The user's password, such as 'Be@gle2'. (It will be automatically converted into an MD5 hash when inserted in the database.) - * @param $status The user's status, such as "ACTIVE", "INACTIVE". - * @return returns a createUserResponse object, or false if exception occurred - */ - function createUser($userId, $firstname, $lastname, $email, $role, $password, $status) { - try { - if ($firstname == null || $firstname == "") { - $firstname = $userId; - } - if ($lastname == null || $lastname == "") { - $lastname = $userId; - } - if ($email == "") { - $email = $userId."@DoNotReply.com"; - } - - $pmResults = $this->pmSoapClient->createUser([ 'sessionId' => $this->getPMSessionID(), - 'userId' => $userId, - 'firstname'=> $firstname, - 'lastname' => $lastname, - 'email' => $email, - 'role' => $role, - 'password' => $password, - 'status' => $status ] ); - return $pmResults; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - - /** - * Summary of updateUser - * updates user information. - * Embedded updateUser() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#updateUser.28.29) - * A session must be open before with login() - * @param $userUid the unique Id for the user (Processmaker user id) - * @param $userName is the user logon. IT IS STRONGLY ADVISE NOT TO CHANGE THIS INFORMATION - * @param $firstname The user's first name. If empty (== null or == "") will default to $userName. - * @param $lastname The user's last name. If empty (== null or == "") will default to $userName. - * @param $status The user's status, such as "ACTIVE", "INACTIVE". - * @return returns a UpdateUserResponse object, or false if exception occurred - */ - function updateUser($userUid, $userName, $firstName, $lastName, $status) { - try { - if ($firstName == null || $firstName == "") { - $firstName = $userName; - } - if ($lastName == null || $lastName == "") { - $lastName = $userName; - } - - $pmResults = $this->pmSoapClient->updateUser([ 'sessionId' => $this->getPMSessionID(), - 'userUid' => $userUid, - 'userName' => $userName, - 'firstName'=> $firstName, - 'lastName' => $lastName, - 'status' => $status - ] ); - return $pmResults; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - /** - * Summary of executeTrigger - * executes a ProcessMaker trigger. - * Note that triggers which are tied to case derivation will be executed automatically, so this function does not need to be called when deriving cases. - * Embedded executeTrigger() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#executeTrigger.28.29) - * A session must be open before with login() - * @param $caseId The case ID, which is can be found with caseList(). - * @param $triggerIndex The ID of the trigger to execute, which can be found with triggerList(). - * @param $delIndex The delegation index number of the case, which can be found with caseList(). - * @return A pmResponse object. If successful, the message will contain "executed: ". Otherwise false in case of SOAP error - */ - function executeTrigger($caseId, $triggerIndex, $delIndex) { - try { - $pmResults = $this->pmSoapClient->executeTrigger([ 'sessionId' => $this->getPMSessionID(), 'caseId' => $caseId, 'triggerIndex'=> $triggerIndex, 'delIndex' => $delIndex ] ); - return $pmResults; - } catch (Exception $e) { - Toolbox::logDebug( $e ); - return false; - } - } - - - - /** - * summary of cronInfo - * Gives localized information about 1 cron task - * @param $name of the task - * @return array of strings - */ - static function cronInfo($name) { - switch ($name) { - case 'pmusers' : - return ['description' => __('Syncs GLPI users and groups into ProcessMaker.', 'processmaker')]; - case 'pmorphancases' : - return ['description' => __('Cleaning of orphan cases.', 'processmaker'), 'parameter' => __('Number of days to keep orphan cases', 'processmaker')]; - case 'pmtaskactions' : - return ['description' => __('To apply task actions between cases.', 'processmaker')]; - } - return []; - } - - /** - * summary of cronPMTaskActions - * Execute 1 task managed by the plugin - * @param: $task CronTask class for log / stat - * @return integer - * >0 : done - * <0 : to be run again (not finished) - * 0 : nothing to do - */ - static function cronPMTaskActions($crontask = null) { - global $DB, $PM_DB, $PM_SOAP; - $dbu = new DbUtils; - - // also create a GLPI session with the processmaker task writer - $usr = new User; - $config = PluginProcessmakerConfig::getInstance(); - $usr->getFromDB($config->fields['users_id']); - $save_session = $_SESSION; - $usr->loadMinimalSession(0, true); - $_SESSION['glpiparententities'] = []; - - $actionCode = 0; // by default - $error = false; - if ($crontask) { - $crontask->setVolume(0); // start with zero - } - - $existingpmsession = isset($_SESSION["pluginprocessmaker"]["session"]); - $formerusers_id = 0; - // get the list of taskactions to be done - $locCase = new PluginProcessmakerCase; - //foreach ($DB->request( $dbu->getTableForItemType('PluginProcessmakerCrontaskaction'), ' `state` = '.PluginProcessmakerCrontaskaction::DATA_READY ) as $taskaction) { - foreach ($DB->request( $dbu->getTableForItemType('PluginProcessmakerCrontaskaction'), ['state' => PluginProcessmakerCrontaskaction::DATA_READY] ) as $taskaction) { - if ($locCase->getFromDB($taskaction['plugin_processmaker_cases_id'])) { - // there is an existing case for this crontaskaction. - try { - - $users_id = $taskaction['users_id']; - if ($formerusers_id != $users_id) { - unset($_SESSION["pluginprocessmaker"]["session"]); // to reset previous user login if any - } - - $caselink = new PluginProcessmakerCaselink; - $caselink->getFromDB($taskaction['plugin_processmaker_caselinks_id']); - - // get current task in current case - $PM_SOAP->login(true); - $caseinfo = $locCase->getCaseInfo(); - $currenttask = false; - if (property_exists($caseinfo, 'currentUsers')) { - foreach ($caseinfo->currentUsers as $loctask) { - if ($loctask->taskId == $caselink->fields['targettask_guid']) { - $currenttask = $loctask; - break; - } - } - } - - // if $currenttask is false then it means that the target task MUST not derived - if ($currenttask) { - if ($caselink->fields['is_targettoimpersonate'] && !$taskaction['is_targettoclaim']) { - // 1) get the current assigned user for this task - // then must login with the user assigned to the task, and not with the user who did the current task - if ($currenttask->userId != '') { - // 3) change login: impersonate - $users_id = PluginProcessmakerUser::getGLPIUserId($loctask->userId); - } - } - - $PM_SOAP->login($users_id); - - $postdata = json_decode($taskaction['postdata'], true); - - // must filter arrays as arrays are grids and index must start at 1 instead of 0 like in json - // TODO: to check if it would be possible to do this in a more generic way - foreach ($postdata['form'] as &$field) { - if (is_array($field)) { - if (count($field) > 0) { - // then must reindex the array starting to 1 instead of 0 - array_unshift($field, ''); - unset($field[0]); - } else { - $field[] = ""; - } - } - } - - if ($taskaction['is_targettoclaim'] && !$caselink->fields['is_targettoimpersonate']) { - // must do a claim before solving task - if (!$PM_SOAP->claimCase( $postdata['APP_UID'], $postdata['DEL_INDEX'] )) { - throw new Exception("Can't claim case"); - } - - // do not send notifications - $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); - - // now manage tasks associated with item - $PM_SOAP->claimTask( $postdata['APP_UID'], $postdata['DEL_INDEX'], $users_id ); - - PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); - - } - - $tkaction = new PluginProcessmakerCrontaskaction; - $tkaction->update( ['id' => $taskaction['id'], 'state' => PluginProcessmakerCrontaskaction::DONE] ); - - $PM_SOAP->derivateCase($locCase, $postdata, $users_id ); - - if ($crontask) { - $crontask->addVolume(1); - } - if ($crontask) { - $crontask->log( "Applied task action id: '".$taskaction['id']."'" ); - } - } else { - $tkaction = new PluginProcessmakerCrontaskaction; - $tkaction->update( ['id' => $taskaction['id'], 'state' => PluginProcessmakerCrontaskaction::NOT_DONE] ); - if ($crontask) { - $crontask->log( "Task action id: '".$taskaction['id']."' case task not found or not open!" ); - } - } - - } catch (Exception $e) { - if ($crontask) { - $crontask->log( "Can't apply task action id: '".$taskaction['id']."'" ); - } - $error = true; - } - - $formerusers_id = $users_id; - } - } - - if ($existingpmsession) { - unset($_SESSION["pluginprocessmaker"]["session"]); // reset the one created during the foreach - if (!Session::isCron()) { - $PM_SOAP->login(); // re-log default user - } - } - - // restore previous session - Session::destroy(); - Session::start(); - $_SESSION = $save_session; - - if ($error) { - return -1; - } else { - return $actionCode; - } - - } - - - /** - * summary of cronPMOrphanCases - * Execute 1 task managed by the plugin - * @param: $task CronTask class for log / stat - * @return integer - * >0 : done - * <0 : to be run again (not finished) - * 0 : nothing to do - */ - static function cronPMOrphanCases($task) { - global $PM_DB, $DB, $PM_SOAP; - - //plugin_processmaker_post_init(); - - // get list of case assigned to GLPI items - $draftCases = [0]; - $query = "SELECT id FROM glpi_plugin_processmaker_cases WHERE case_status = 'DRAFT';"; - //foreach ($DB->request( $query ) as $row) { - foreach ($DB->request(['SELECT' => 'id', 'FROM' => 'glpi_plugin_processmaker_cases'], ['case_status' => 'DRAFT']) as $row) { - $draftCases[] = $row['id']; - } - - $actionCode = 0; // by default - $error = false; - $task->setVolume(0); // start with zero - - if (count($draftCases) > 0) { - //$PM_SOAP = new self; - $PM_SOAP->login(true); - $query = "SELECT * FROM APPLICATION - WHERE APP_DATA LIKE '%s:24:\"GLPI_SELFSERVICE_CREATED\";s:1:\"1\"%' - AND APP_STATUS = 'DRAFT' - AND DATEDIFF( NOW(), APP_UPDATE_DATE) > ".$task->fields['param']." - AND APP_NUMBER NOT IN (".implode(',', $draftCases)."); - "; - $res = $PM_DB->request('APPLICATION', ['AND' => [ - 'APP_DATA' => ['LIKE', '%s:24:\"GLPI_SELFSERVICE_CREATED\";s:1:\"1\"%'], - 'APP_STATUS' => 'DRAFT', - 'RAW' => ['DATEDIFF(NOW(), APP_UPDATE_DATE)' => ['>', $task->fields['param']]], - 'NOT' => ['APP_NUMBER' => $draftCases] - ]]); - //foreach ($PM_DB->request( $query ) as $row) { - foreach ($res as $row) { - $ret = $PM_SOAP->deleteCase( $row['APP_UID'] ); - $task->addVolume(1); - if ($ret !== false) { - $task->log( "Deleted case num: '".$row['APP_NUMBER']."'" ); - $actionCode = 1; - } else { - $task->log( "Can't delete case num: '".$row['APP_NUMBER']."'" ); - $error = true; - } - } - } - if ($error) { - return -1; - } else { - return $actionCode; - } - - } - - - /** - * summary of cronPMUsers - * Executes 1 task managed by the plugin - * @param $task CronTask class for log / stat - * @return integer - * >0 : done - * <0 : to be run again (not finished) - * 0 : nothing to do - */ - static function cronPMUsers($task) { - global $DB, $PM_DB, $PM_SOAP; - - //plugin_processmaker_post_init(); - - $actionCode = 0; // by default - $error = false; - $task->setVolume(0); // start with zero - - // start a processmaker session - if (!isset($PM_SOAP)) { - $PM_SOAP = new PluginProcessmakerProcessmaker(); - } - if (!$PM_SOAP->login( true )) { - $task->log( "Error PM: '".print_r($PM_SOAP->lasterror, true)."'" ); - return -1; - } - - $pmGroupList = $PM_SOAP->groupList( ); - $pmGroup = null; - //if($pmgrp_key = array_search($PM_SOAP->pm_group_guid, array_column($pmGroupList, 'guid'))) { - // $pmgroup = $pmGroupList[$pmgrp_key]; - //} - foreach ($pmGroupList as $pmGroupList) { - if ($pmGroupList->guid == $PM_SOAP->pm_group_guid) { - $pmGroup = $pmGroupList; - break; // to get the name :) - } - } - - $pmUserList = []; - foreach ($PM_SOAP->userList() as $pmuser) { - $pmUserList[ strtolower($pmuser->name)] = [ 'name' => $pmuser->name, 'guid' => $pmuser->guid, 'status' => $pmuser->status ]; - } - - // get the complete user list from GLPI DB - $glpiUserList = []; - $res = $DB->request(['SELECT' => ['glpi_users.id', 'glpi_users.name', 'glpi_users.realname', 'glpi_users.firstname', 'glpi_users.is_active', 'glpi_users.is_deleted', 'glpi_plugin_processmaker_users.pm_users_id as pmUserId'], - 'FROM' => 'glpi_users', - 'LEFT JOIN' => ['glpi_plugin_processmaker_users' => ['FKEY' => ['glpi_plugin_processmaker_users' => 'id', 'glpi_users' => 'id']]], - 'WHERE' => ['name' => ['NOT LIKE', '*%']] - ]); - //foreach ($DB->request("SELECT glpi_users.id, glpi_users.name, glpi_users.realname, glpi_users.firstname, glpi_users.is_active, glpi_users.is_deleted, glpi_plugin_processmaker_users.pm_users_id as pmUserId - // FROM glpi_users - // LEFT JOIN glpi_plugin_processmaker_users on glpi_plugin_processmaker_users.id = glpi_users.id - // WHERE name not like '*%'") as $dbgroup) { - foreach ($res as $dbgroup) { - $glpiUserList[ strtolower($dbgroup['name'])] = $dbgroup; - } - - $arrayDiff = array_diff_key( $glpiUserList, $pmUserList ); - - foreach ($arrayDiff as $user) { - if ($user['is_active'] != 0 && $user['is_deleted'] != 1) { - $status = "ACTIVE"; - $task->addVolume(1); - $pass = substr( Toolbox::encrypt($user['id'].$user['name'].time(), GLPIKEY), 0, 20); - $pmResult = $PM_SOAP->createUser( $user['name'], $user['firstname'], $user['realname'], "", "PROCESSMAKER_OPERATOR", $pass, $status); - if ($pmResult->status_code == 0) { - $task->log( "Added user: '".$user['name']."'" ); - - // then assign user to group - if($pmGroup) { - $pmResult2 = $PM_SOAP->assignUserToGroup( $pmResult->userUID, $pmGroup->guid ); - if ($pmResult2->status_code == 0) { - $task->log( "Added user: '".$user['name']."' to '".$pmGroup->name."' group" ); - } else { - $task->log( "Error PM: '".$pmResult2->message."'" ); - } - } - // insert into DB the link between glpi users and pm user - $pmuser = new PluginProcessmakerUser; - if ($pmuser->getFromDB( $user['id'] )) { - $pmuser->update( [ 'id' => $user['id'], 'pm_users_id' => $pmResult->userUID ] ); - } else { - $pmuser->add( [ 'id' => $user['id'], 'pm_users_id' => $pmResult->userUID ] ); - } - $actionCode = 1; - - } else { - $task->log( "Error adding user: '".$user['name']."'" ); - $task->log( "Error PM: '".$pmResult->message."'" ); - $actionCode = -1; - $error = true; - } - } else { - unset( $glpiUserList[$user['name']] ); - } - } - - if (!$error) { - - // now should refresh the existing users - $arrayIntersect = array_intersect_key( $glpiUserList, $pmUserList ); - foreach ($arrayIntersect as $user) { - if ($user['pmUserId'] == null || ($user['pmUserId'] != $pmUserList[strtolower($user['name'])]['guid'])) { //must be inserted into DB - // insert into DB the link between glpi users and pm user - $pmuser = new PluginProcessmakerUser; - if ($pmuser->getFromDB( $user['id'] )) { - $ret = $pmuser->update( [ 'id' => $user['id'], 'pm_users_id' => $pmUserList[strtolower($user['name'])]['guid'] ] ); - } else { - $ret = $pmuser->add( [ 'id' => $user['id'], 'pm_users_id' => $pmUserList[strtolower($user['name'])]['guid'] ] ); - } - - //$query = "REPLACE INTO glpi_plugin_processmaker_users (glpi_users_id, pm_users_id) VALUES (".$user['id'].", '". $pmUserList[strtolower($user['name'])]['guid']."');" ; - //$DB->query( $query ) or - if (!$ret) { - $task->log( "Cannot update user: '".$user['id']."' into glpi_plugin_processmaker_users!" ); - } - - } - if ($user['is_active'] == 0 || $user['is_deleted'] == 1) { - $status = "INACTIVE"; - } else { - $status = "ACTIVE"; - } - if ($status != $pmUserList[strtolower($user['name'])]['status']) { - $task->addVolume(1); - $pmResult = $PM_SOAP->updateUser( $pmUserList[strtolower($user['name'])]['guid'], $user['name'], $user['firstname'], $user['realname'], $status ); - if ($pmResult->status_code == 0) { - $task->log( "Updated user: '".$user['name']."', status: '".$pmUserList[strtolower($user['name'])]['status']."' -> '".$status."'" ); - $actionCode = 1; - } else { - $task->log( "Error updating user: '".$user['name']."'" ); - $task->log( "Error PM: '".$pmResult->message."'" ); - $actionCode = -1; - $error = true; - } - } - - } - } - - // now we should desactivate PM users who are not in glpi user list - //if( !$error ) { - // $status = "INACTIVE" ; - // $arrayDiff = array_diff_key( $pmUserList , $glpiUserList ) ; - // foreach( $arrayDiff as $user ){ - // $task->addVolume(1); - // if( $user['status'] == 'ACTIVE' && $user['name'] != 'admin' && $user['name'] != 'glpi'){ - // $pmResult = $myProcessMaker->updateUser( $user['guid'], $user['name'], null, null, $status ) ; - // if( $pmResult->status_code == 0) { - // $task->log( "Updated user: '".$user['name']."', status: '".$user['status']."' -> '".$status."'" ) ; - // $actionCode = 1 ; - // } else { - // $task->log( "Error updating user: '".$user['name']."'" ) ; - // $task->log( "Error PM: '".$pmResult->message."'" ) ; - // $actionCode = -1 ; - // $error = true ; - // } - // } - // } - //} - - // so now treat GLPI groups - $glpiGroupList = []; - $res = $DB->request(['SELECT' => ['id', 'name', 'is_task', 'is_usergroup'], - 'FROM' => 'glpi_groups', - 'WHERE' => ['AND' => ['is_task' => 1, 'is_usergroup' => 1]] - ]); - //foreach ($DB->request("SELECT id, name, is_task, is_usergroup FROM glpi_groups WHERE is_task=1 AND is_usergroup=1") as $dbgroup) { - foreach ($res as $dbgroup) { - $glpiGroupList[$dbgroup['name']] = $dbgroup; - } - - $pmGroupList = self::getPMGroups(); // array(); - - // here we can compare group lists like done for the users - $arrayDiff = array_diff_key( $glpiGroupList, $pmGroupList ); - - // then for each group we must check if it exists, and if not create a real PM group - foreach ($arrayDiff as $group) { - // it is not existing in PM - // then create - $pmResult = $PM_SOAP->createGroup( $group['name'] ); - if ($pmResult->status_code == 0) { - $task->addVolume(1); - $task->log( "Added group: '".$group['name']."'" ); - } - } - - // review and update all users in each group - $pmGroupList = self::getPMGroups(); // array(); - - // now should refresh the existing users into groups - $arrayDiff = array_intersect_key( $glpiGroupList, $pmGroupList ); - foreach ($arrayDiff as $group) { - // for each group will delete users and re-create them - // not really optimized, but this way we are sure that groups are synchronized - // must be redesigned - $PM_DB->delete('GROUP_USER', ['GROUP_USER.GRP_UID' => $pmGroupList[$group['name']]['CON_ID']]); - //$query = "DELETE FROM GROUP_USER WHERE GROUP_USER.GRP_UID='".$pmGroupList[$group['name']]['CON_ID']."';"; - //$PM_DB->query( $query ); - // and insert all users from real GLPI group - $res = $DB->request(['SELECT' => ['glpi_groups_users.users_id', 'glpi_plugin_processmaker_users.pm_users_id'], - 'FROM' => 'glpi_groups', - 'INNER JOIN' => ['glpi_groups_users' => ['FKEY' => ['glpi_groups_users' => 'groups_id', 'glpi_groups' => 'id']], - 'glpi_plugin_processmaker_users' => ['FKEY' => ['glpi_plugin_processmaker_users' => 'id', 'glpi_groups_users' => 'users_id']]], - 'WHERE' => ['glpi_groups.name' => $group['name']]]); - - //foreach ($DB->request("SELECT glpi_groups_users.users_id, glpi_plugin_processmaker_users.pm_users_id - // FROM glpi_groups - // JOIN glpi_groups_users ON glpi_groups_users.groups_id=glpi_groups.id - // JOIN glpi_plugin_processmaker_users ON glpi_plugin_processmaker_users.id=glpi_groups_users.users_id - // WHERE glpi_groups.name='".$group['name']."'") as $user ) { - foreach ($res as $user) { - //$query = "INSERT INTO GROUP_USER (`GRP_UID`, `USR_UID`) VALUES ( '".$pmGroupList[$group['name']]['CON_ID']."', '".$user['pm_users_id']."' )"; - //$PM_DB->query( $query ); - $PM_DB->insert('GROUP_USER', ['GRP_UID' => $pmGroupList[$group['name']]['CON_ID'], - 'USR_UID' => $user['pm_users_id'] - ] - ); - } - $task->addVolume(1); - $task->log( "Updated users into PM group: '".$group['name']."'" ); - } - - // now should renew the duedate of the users - //$PM_DB->query("UPDATE USERS SET USR_DUE_DATE='2035-12-31' WHERE USR_DUE_DATE<>'2035-12-31'; "); - //$PM_DB->query("UPDATE RBAC_USERS SET USR_DUE_DATE='2035-12-31' WHERE USR_DUE_DATE<>'2035-12-31'; "); - $PM_DB->update('USERS', - ['USR_DUE_DATE' => '2035-12-31'], - ['USR_DUE_DATE' => ['!=', '2035-12-31']] - ); - $PM_DB->update('RBAC_USERS', - ['USR_DUE_DATE' => '2035-12-31'], - ['USR_DUE_DATE' => ['!=', '2035-12-31']] - ); - if ($error) { - return -1; - } else { - return $actionCode; - } - } - - - public static function plugin_pre_item_add_processmaker($parm) { - global $PM_DB; - - if (isset($parm->input['processmaker_caseguid'])) { - // a case is already started for this ticket, then change ticket title and ticket type and ITILCategory - - $myProcessMaker = new PluginProcessmakerProcessmaker( ); - $myProcessMaker->login( ); - $caseInfo = $myProcessMaker->getCaseInfo( $parm->input['processmaker_caseguid'], $parm->input['processmaker_delindex']); - $parm->input['name'] = $PM_DB->escape($caseInfo->caseName ); - - $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', $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'])) { - $parm->input['type'] = $procDef->fields['type']; - } - - if (isset($parm->input['itilcategories_id'])) { - $parm->input['itilcategories_id'] = $procDef->fields['itilcategories_id']; - } - - } - } - - - /** - * Summary of plugin_item_add_processmaker - * @param mixed $parm - * @return void - */ - public static function plugin_item_add_processmaker($parm) { - global $DB, $GLOBALS, $PM_SOAP; - - if (isset($parm->input['processmaker_caseguid'])) { - // a case is already started for this ticket, then bind them together - $itemtype = $parm->getType(); - $items_id = $parm->fields['id']; - $case_guid = $parm->input['processmaker_caseguid']; - - $caseInfo = $PM_SOAP->getCaseInfo($case_guid);//$parm->input['processmaker_delindex']); - - $myCase = new PluginProcessmakerCase; - $myCase->add(['id' => $parm->input['processmaker_casenum'], - 'itemtype' => $itemtype, - 'items_id' => $items_id, - 'entities_id' => $parm->fields['entities_id'], - 'name' => $caseInfo->caseName, - 'case_guid' => $case_guid, - 'case_status' => $caseInfo->caseStatus, - 'plugin_processmaker_processes_id' => $parm->input['processmaker_processes_id'] - ]); - - // here we create a fake task that will be used to store the creator of the case - // this is due for traceability only - $PM_SOAP->add1stTask($myCase->getID(), $myCase->fields['itemtype'], $myCase->fields['items_id'], $caseInfo, [ 'notif' => false] ); // no notif - - // before routing, send items_id and itemtype - // as this information was not available at case creation - $myCase->sendVariables( [ "GLPI_TICKET_ID" => $items_id, - "GLPI_ITEM_ID" => $items_id, - "GLPI_ITEM_TYPE" => $itemtype, - ] ); - - $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"; - $str = $parm->input['content']; - if (preg_match($ptnProcessToStart, $str, $matches) > 0) { - // and it is requested to start a case of process - $processGuid = $matches[1]; - $hasCase = self::hasCase( 'Ticket', $parm->fields['id'] ); - if ($hasCase === false) { - // check writer - $writer = new User; - $writer->getFromDB( $parm->fields['users_id_recipient'] ); - //$PM_SOAP = new PluginProcessmakerProcessmaker(); - $PM_SOAP->login( $writer->fields['name'] ); - $locProcess = new PluginProcessmakerProcess; - if ($locProcess->getFromGUID( $processGuid )) { - $found = false; - // check rights of writer to start this $processGuid on the Ticket entity - foreach (Profile_User::getUserProfiles( $writer->getID() ) as $profID) { - if (in_array( $parm->fields['entities_id'], PluginProcessmakerProcess::getEntitiesForProfileByProcess( $locProcess->getID(), $profID, true) )) { - $found=true; - break; - } - } - if ($found) { - $PM_SOAP->startNewCase( $locProcess->getID(), 'Ticket', $parm->fields['id'], $writer->getID() ); - } - } - } - } - } - return; - } - - - public static function plugin_pre_item_add_processmaker_followup($parm) { - //global $DB ; - - } - - - /** - * Summary of addWatcher - * add $techId as watcher to $glpi_item when techId has no rights on it - * @param string $itemType is the type of the CommonITILObject - * @param integer $itemId is the id of the ITIL object - * @param integer $techId is the users_id to be added - * @return boolean true if added, - */ - public static function addWatcher($itemType, $itemId, $techId) { - if ($techId && $itemType != '' && $itemId > 0) { - $dbu = new DbUtils; - $glpi_item = $dbu->getItemForItemtype( $itemType ); - $glpi_item->getFromDB( $itemId ); - - // then we should check if this user has rights on the item, if not then we must add it to the watcher list! - $glpi_item = $dbu->getItemForItemtype( $itemType ); - $glpi_item->getFromDB( $itemId ); - if (!$glpi_item->isUser( CommonITILActor::REQUESTER, $techId ) - && !$glpi_item->isUser( CommonITILActor::OBSERVER, $techId ) - && !$glpi_item->isUser( CommonITILActor::ASSIGN, $techId ) ) { - - // then we must add this tech user to watcher list - $glpi_item_user = $dbu->getItemForItemtype( $glpi_item->getType() . "_User" ); - - // do not send notifications - $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); - $glpi_item_user->add( [ $glpi_item::getForeignKeyField() => $glpi_item->getId(), 'users_id' => $techId, 'type' => CommonITILActor::OBSERVER, '_disablenotif' => true ] ); - PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); - return true; - } - } - return false; - } - - - /** - * Summary of addTask - * adds a GLPI task to given item - * @param $cases_id integer the GLPI id of the case - * @param $itemtype string item type to which a task will be added - * @param $items_id integer item id to which a task will be added - * @param $caseInfo mixed getCaseInfoResponse object (see: getCaseInfo() function) - * @param $delIndex integer index of the delegation - * @param $techId integer GLPI user id to which a task must be assigned, if == 0 will use $groupId and/or $pmTaskId - * @param $groupId string PM group guid to assign to task, used when $techId == 0 - * @param $pmTaskId string PM task guid, used when $groupId == 0 AND $techID == 0 - * @param $options array of options, default values are - * 'txtTaskContent' => '', - * 'start_date' => '', - * 'end_date' => '', - * 'notif' => true - * @return - */ - public function addTask($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; - } - } - - $glpi_task = $dbu->getItemForItemtype( "{$itemtype}Task" ); - $glpi_task->getEmpty(); - - $input = []; // will contain all data for the Task - - $input[getForeignKeyFieldForItemType($itemtype)] = $items_id; - // search for task category - // - $pmtaskcat = new PluginProcessmakerTaskCategory; - $pmtaskcat->getFromGUID( $pmTaskId ); - $input['taskcategories_id'] = $pmtaskcat->fields['taskcategories_id']; - // load process information - $pmProcess = new PluginProcessmakerProcess; - $pmProcess->getFromDB( $pmtaskcat->fields['plugin_processmaker_processes_id'] ); - - if ($options['start_date'] == '') { - $options['start_date'] = new DateTime( $_SESSION["glpi_currenttime"] ); - } else { - $options['start_date'] = new DateTime( $options['start_date'] ); - } - - $input['begin'] = $options['start_date']->format("Y-m-d H:i:s"); - - if ($options['end_date'] == '' || $options['end_date'] <= $input['begin']) { - $options['end_date'] = clone $options['start_date']; - $options['end_date']->add( new DateInterval('PT15M') ); - } else { - $options['end_date'] = new DateTime( $options['end_date'] ); - } - $input['end'] = $options['end_date']->format("Y-m-d H:i:s"); - $input['plan']['begin'] = $input['begin']; - $temp = $options['start_date']->diff( $options['end_date'] ); - $input['plan']['_duration'] = $temp->d * DAY_TIMESTAMP + $temp->h * HOUR_TIMESTAMP + $temp->i * MINUTE_TIMESTAMP + $temp->s; - if ($input['plan']['_duration'] == 0) { - $input['plan']['_duration'] = 60; // at least - } - - $input['users_id'] = $this->taskWriter; - - // manage groups - $groups_id_tech = 0; - if ($techId == 0) { // then we must look-up DB to get the group that will be assigned to the task - $groupname=''; - if ($groupId == 0) { - // TU_RELATION=2 is groups and TU_TYPE=1 means normal (= not adhoc) - $res = $PM_DB->request([ - 'SELECT' => 'CONTENT.CON_VALUE', - 'FROM' => 'TASK_USER', - 'INNER JOIN' => [ - 'CONTENT' => [ - 'AND' => [ - 'FKEY' => [ - 'CONTENT' => 'CON_ID', - 'TASK_USER' => 'USR_UID' - ], - ['CONTENT.CON_CATEGORY' => 'GRP_TITLE'], - ['CONTENT.CON_LANG' => 'en'] - ] - ] - ], - 'WHERE' => [ - 'AND' => [ - 'TASK_USER.TAS_UID' => $pmTaskId, - 'TASK_USER.TU_RELATION' => 2, - 'TASK_USER.TU_TYPE' => 1 - ] - ], - 'LIMIT' => 1 - ]); - //$query = "SELECT CONTENT.CON_VALUE FROM TASK_USER - // JOIN CONTENT ON CONTENT.CON_ID=TASK_USER.USR_UID AND CONTENT.CON_CATEGORY='GRP_TITLE' AND CONTENT.CON_LANG = 'en' - // WHERE TASK_USER.TAS_UID='$pmTaskId' AND TASK_USER.TU_RELATION=2 LIMIT 1;"; - } else { - $res = $PM_DB->request([ - 'SELECT' => 'CON_VALUE', - 'FROM' => 'CONTENT', - 'WHERE' => [ - 'AND' => [ - 'CONTENT.CON_ID' => $groupId, - 'CONTENT.CON_CATEGORY' => 'GRP_TITLE', - 'CONTENT.CON_LANG' => 'en' - ] - ] - ]); - //$query = "SELECT CON_VALUE FROM CONTENT - // WHERE CONTENT.CON_ID='$groupId' AND CONTENT.CON_CATEGORY='GRP_TITLE' AND CONTENT.CON_LANG='en' ;"; - } - // as there is a LIMIT of 1 - // or - // as there is only one group per guid - // then we should have at maximun 1 record - foreach ($res as $onlyrec) { - //foreach ($PM_DB->request($query) as $onlyrec) { - $groupname = $onlyrec['CON_VALUE']; - } - - $res = $DB->request([ - 'SELECT' => 'id AS glpi_group_id', - 'FROM' => 'glpi_groups', - 'WHERE' => ['name' => ['LIKE', $groupname]] - ]); - if ($row = $res->next()) { - $groups_id_tech = $row['glpi_group_id']; - } - //$query = "SELECT id AS glpi_group_id FROM glpi_groups WHERE name LIKE '$groupname';"; - //$res = $DB->query($query); - //if ($DB->numrows($res) > 0) { - // $row = $DB->fetch_array( $res ); - // $groups_id_tech = $row['glpi_group_id']; - //} - - } else { - // adds the user tech to ticket watcher if neccessary - self::addWatcher( $itemtype, $items_id, $techId ); - } - - // manage task description - $input['content'] = ""; // by default empty :) - - if ($pmProcess->fields["insert_task_comment"]) { - $input['content'] .= "##processmaker.taskcomment##\n"; - } - - if ($options['txtTaskContent'] != '') { - $input['content'] .= $options['txtTaskContent']."\n"; - } else if (!$pmProcess->fields["hide_case_num_title"]) { - $input['content'] .= __('Case title: ', 'processmaker').$caseInfo->caseName."\n"; - } - - $input['content'] .= "##processmakercase.url##"; - - $input['is_private'] = 0; - $input['actiontime'] = 0; - $input['state'] = Planning::TODO; // == TO_DO - $input['users_id_tech'] = 0; // by default as it can't be empty - if ($techId) { - $input['users_id_tech'] = $techId; - } else if ($groups_id_tech) { - $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 = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); // do not send notification yet as the PluginProcessmakerTask is not yet added to DB - $glpi_task->add( Toolbox::addslashes_deep( $input ) ); - PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); - - // to prevent error message for overlapping planning - if (isset($_SESSION["MESSAGE_AFTER_REDIRECT"][WARNING])) { - unset($_SESSION["MESSAGE_AFTER_REDIRECT"][WARNING]); - } - - if ($glpi_task->getId() > 0) { - // stores link to task in DB - //$tmp = new PluginProcessmakerTask($glpi_task->getType()); - //$tmp->add([ 'itemtype' => $glpi_task->getType(), - // 'items_id' => $glpi_task->getId(), - // 'plugin_processmaker_cases_id' => $cases_id, - // 'del_index' => $delIndex - // ], [], false); - $DB->insert('glpi_plugin_processmaker_tasks', - [ - 'items_id' => $glpi_task->getId(), - 'itemtype' => $glpi_task->getType(), - 'plugin_processmaker_cases_id' => $cases_id, - 'plugin_processmaker_taskcategories_id' => $pmtaskcat->fields['id'], - 'del_index' => $delIndex, - 'del_thread' => $delThread - ]); - //$query = "INSERT INTO glpi_plugin_processmaker_tasks (items_id, itemtype, plugin_processmaker_cases_id, plugin_processmaker_taskcategories_id, del_index, del_thread) - // VALUES ({$glpi_task->getId()}, '{$glpi_task->getType()}', $cases_id, {$pmtaskcat->fields['id']}, $delIndex, $delThread);"; - //$DB->query( $query ); - //} - - // send notification if needed for new task as now we have the PluginProcessmakerTask in the DB - $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState($options['notif']); - // Notification management - $item = new $itemtype; - $item->getFromDB($items_id); - // search if at least one active notification is existing for that pm task with that event 'task_update_'.$glpi_task->fields['taskcategories_id'] - $res = PluginProcessmakerNotificationTargetTask::getNotifications('task_add', $glpi_task->fields['taskcategories_id'], $item->fields['entities_id']); - if ($res['notifications'] && count($res['notifications']) > 0) { - $pm_task = new PluginProcessmakerTask($glpi_task->getType()); - $pm_task->getFromDB($glpi_task->getId()); - NotificationEvent::raiseEvent($res['event'], - $pm_task, - ['plugin_processmaker_cases_id' => $cases_id, - 'itemtype' => $glpi_task->getType(), - 'task_id' => $glpi_task->getID(), - 'is_private' => isset($glpi_task->fields['is_private']) ? $glpi_task->fields['is_private'] : 0, - 'entities_id' => $item->fields['entities_id'] - ]); - } else { - NotificationEvent::raiseEvent('add_task', - $item, - ['plugin_processmaker_cases_id' => $cases_id, - 'itemtype' => $itemtype, - 'task_id' => $glpi_task->getID(), - 'is_private' => isset($glpi_task->fields['is_private']) ? $glpi_task->fields['is_private'] : 0 - ]); - } - - PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); - } - } - - - /** - * Summary of getGLPIGroupId - * returns GLPI group id from pm group name - * returns false when not found - * @param string $pmGroupName - * @return bool|integer - */ - static function getGLPIGroupId(string $pmGroupName) { - global $DB; - $query = "SELECT id AS glpi_group_id FROM glpi_groups WHERE name LIKE '$pmGroupName';"; - $res = $DB->query($query); - if ($DB->numrows($res) > 0) { - $row = $DB->fetch_array($res); - return $row['glpi_group_id']; - } - return false; - } - - /** - * Summary of add1stTask - * adds a GLPI task to ticket - * @param $cases_id integer the GLPI id of the case - * @param $itemType string itemtype of object (Ticket, Problem, ....) - * @param $itemId integer item id to which a task will be added - * @param $caseInfo mixed getCaseInfoResponse object (see: getCaseInfo() function) - * @param $options array of options, defaults are: - * 'txtTaskContent' => '', is content of the task - * 'userId' => false, is user id to be assigned to task - * 'notif' => true, if true notifications will be sent - * @return - */ - public function add1stTask ($cases_id, $itemType, $itemId, $caseInfo, $options = []) { - - $default_options = [ - 'txtTaskContent' => '', - 'userId' => false, - 'notif' => true - ]; - foreach ($default_options as $key => $opt) { - if (!isset($options[$key])) { - $options[$key] = $opt; - } - } - $start_date = new DateTime( $_SESSION["glpi_currenttime"] ); - $official_date_time = $_SESSION["glpi_currenttime"]; - $_SESSION["glpi_currenttime"] = $start_date->sub(new DateInterval("PT1S"))->format("Y-m-d H:i:s"); - $userId = $options['userId'] ? $options['userId'] : Session::getLoginUserID(); - unset($options['userId']); // unset it as it's not in the options of addTask - - $this->addTask( $cases_id, - $itemType, - $itemId, - $caseInfo, - $caseInfo->currentUsers[0]->delIndex, - $userId, - 0, - $caseInfo->currentUsers[0]->taskId, - $caseInfo->currentUsers[0]->delThread, - $options - ); - $_SESSION["glpi_currenttime"] = $official_date_time; - } - - - /** - * Summary of setItemStatus - * @param mixed $itemtype - * @param mixed $itemId - * @param mixed $newstatus - */ - public function setItemStatus($itemtype, $itemId, $newstatus) { - $dbu = new DbUtils; - $item = $dbu->getItemForItemtype( $itemtype ); - if ($item->getFromDB( $itemId )) { //&& $itemtype::isAllowedStatus( $item->fields['status'], $newstatus )) { - //$item->fields['status'] = $newstatus ; - $item->update( ['id' => $itemId, 'status' => $newstatus] ); - } - } - - - /** - * Summary of setItemTitle - * @param mixed $itemtype - * @param mixed $itemId - * @param mixed $newtitle - */ - public function setItemTitle($itemtype, $itemId, $newtitle) { - global $DB; - - $dbu = new DbUtils; - $item = $dbu->getItemForItemtype( $itemtype ); - if ($item->getFromDB( $itemId )) { - $item->update( ['id' => $itemId, 'name' => $DB->escape($newtitle)] ); - } - } - - - /** - * 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 - * @param mixed $itemId - * @param mixed $casevariablevalues - */ - public function setItemSolution($itemType, $itemId, $casevariablevalues) { - global $DB; - - $dbu = new DbUtils; - $item = $dbu->getItemForItemtype( $itemType ); - if ($item->getFromDB( $itemId )) { - // default values - $solutiontemplates_id = 0; - $solutiontypes_id = 0; - $solution = ''; - $to_update = false; - - // check solution template - if (array_key_exists( 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID', $casevariablevalues ) - && $casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID' ] != '' - && $casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID' ] != 0) { - // get template - $template = new SolutionTemplate; - $template->getFromDB($casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID' ]); - $entities = $template->isRecursive() ? $dbu->getSonsOf(Entity::getTable(), $template->getEntityID()) : [$template->getEntityID()]; - // and check entities - if (in_array($item->getEntityID(), $entities)) { - $solutiontemplates_id = $template->getID(); - $solutiontypes_id = $template->fields['solutiontypes_id']; - $solution = $template->fields['content']; - $to_update = true; - } - } - - // check solution type - if (array_key_exists( 'GLPI_ITEM_SET_SOLUTION_TYPE_ID', $casevariablevalues ) - && $casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TYPE_ID' ] != '' - && $casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TYPE_ID' ] != 0) { - // get solution type - $type = new SolutionType; - $type->getFromDB($casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TYPE_ID' ]); - $entities = $type->isRecursive() ? $dbu->getSonsOf(Entity::getTable(), $type->getEntityID()) : [$type->getEntityID()]; - // and check entities - if (in_array($item->getEntityID(), $entities)) { - $solutiontypes_id = $type->getID(); - $to_update = true; - } - } - - // Check solution description - if (array_key_exists( 'GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION', $casevariablevalues ) - && $casevariablevalues[ 'GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION' ] != '') { - if ($solution != '') { - $solution .= "\n"; - } - $solution .= $DB->escape($casevariablevalues[ 'GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION' ]); - $to_update = true; - } - - if ($to_update) { - $item->update( ['id' => $itemId, 'solutiontemplates_id' => $solutiontemplates_id, 'solutiontypes_id' => $solutiontypes_id, 'solution' => $solution] ); - } - } - } - - - /** - * Summary of computeTaskDuration - * @param mixed $task - * @param mixed $entity - * @return mixed - */ - function computeTaskDuration($begin, $end, $entity) { - - $calendars_id = Entity::getUsedConfig('calendars_id', $entity); - $calendar = new Calendar(); - - // Using calendar - if ($calendars_id>0 && $calendar->getFromDB($calendars_id)) { - return max(0, $calendar->getActiveTimeBetween($begin, $end)); - } - // Not calendar defined - return max(0, strtotime($end) - strtotime($begin)); - } - - - - /** - * Summary of solveTask - * @param string $cases_id GLPI case id - * @param int $delIndex - * @param array $options - * 'txtToAppend' => '' : text to append to solved task - * 'notif' => true : if true will send notifications - * 'users_id_tech' => is the users_id of the tech that solved the task - * 'begin' => is the new begin date of the task - * 'end' => is the new end date of the task - * 'toInformation' => is the new status of the task (usually set to INFORMATION) - * @return false|object the solved task, when found - */ - public function solveTask($cases_id, $delIndex, $options = []) { - global $DB; - - //$query = "SELECT * FROM glpi_plugin_processmaker_tasks WHERE plugin_processmaker_cases_id=$cases_id and del_index=$delIndex; "; - //$res = $DB->query($query); - $res = $DB->request('glpi_plugin_processmaker_tasks', ['AND' => ['plugin_processmaker_cases_id' => $cases_id, 'del_index' => $delIndex]]); - //if ($DB->numrows($res) > 0) { - if ($row = $res->next()) { - $dbu = new DbUtils; - //$row = $DB->fetch_array( $res ); - - $glpi_task = new $row['itemtype']; - $glpi_task->getFromDB( $row['items_id'] ); - $hostItem = $dbu->getItemForItemtype( $glpi_task->getItilObjectItemType() ); - $itemFKField = getForeignKeyFieldForItemType( $glpi_task->getItilObjectItemType() ); - $hostItem->getFromDB( $glpi_task->fields[ $itemFKField ] ); - - // change current glpi_currenttime to be sure that date_mode for solved task will not be identical than date_mode of the newly started task - $saved_date_time = $_SESSION["glpi_currenttime"]; - $_SESSION["glpi_currenttime"] = (new DateTime($saved_date_time))->sub(new DateInterval("PT1S"))->format("Y-m-d H:i:s"); - - $default_options = [ - 'txtToAppend' => '', - 'notif' => true, - 'users_id_tech' => null, - 'begin' => $glpi_task->fields['begin'] > $_SESSION["glpi_currenttime"] ? - (new DateTime($_SESSION["glpi_currenttime"]))->sub(new DateInterval("PT1S"))->format("Y-m-d H:i:s") : - $glpi_task->fields['begin'], - 'end' => $_SESSION["glpi_currenttime"], - 'toInformation' => false - ]; - foreach ($default_options as $key => $opt) { - if (!isset($options[$key]) || ($options[$key] === '')) { - $options[$key] = $opt; - } - } - - $duration = $this->computeTaskDuration($options['begin'], $options['end'], $hostItem->fields['entities_id']); - if ($options['txtToAppend'] != "") { - $options['txtToAppend'] = "\n
".$options['txtToAppend']; - } - $params = ['id' => $row['items_id'], - 'state' => $options['toInformation'] ? Planning::INFO : Planning::DONE, - 'begin' => $options['begin'], - 'end' => $options['end'], - $itemFKField => $hostItem->getID(), - 'actiontime' => $duration, - 'users_id_tech' => (isset($options['users_id_tech']) ? $options['users_id_tech'] : Session::getLoginUserID()), - //'groups_id_tech' => 0, - 'content' => $DB->escape($glpi_task->fields[ 'content' ].$options['txtToAppend']) - ]; - - $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); // do not send notification yet - $glpi_task->update($params); - PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); - - // Close the task - //$DB->query("UPDATE glpi_plugin_processmaker_tasks SET del_thread_status = '".PluginProcessmakerTask::CLOSED."' WHERE id = {$row['id']}"); - $DB->update('glpi_plugin_processmaker_tasks', ['del_thread_status' => PluginProcessmakerTask::CLOSED], ['id' => $row['id']]); - - // send notification if needed for new task as now the PluginProcessmakerTask has been updated in the DB - $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState($options['notif']); - // Notification management - // search if at least one active notification is existing for that pm task with that event 'task_update_'.$glpi_task->fields['taskcategories_id'] - $res = PluginProcessmakerNotificationTargetTask::getNotifications('task_done', $glpi_task->fields['taskcategories_id'], $hostItem->fields['entities_id']); - if ($res['notifications'] && count($res['notifications']) > 0) { - $pm_task = new PluginProcessmakerTask($glpi_task->getType()); - $pm_task->getFromDB($glpi_task->getId()); - NotificationEvent::raiseEvent($res['event'], - $pm_task, - ['plugin_processmaker_cases_id' => $cases_id, - 'itemtype' => $glpi_task->getType(), - 'task_id' => $glpi_task->getID(), - 'is_private' => isset($glpi_task->fields['is_private']) ? $glpi_task->fields['is_private'] : 0, - 'entities_id' => $hostItem->fields['entities_id'] - ]); - } else { - NotificationEvent::raiseEvent('update_task', - $hostItem, - ['plugin_processmaker_cases_id' => $cases_id, - 'itemtype' => $hostItem->getType(), - 'task_id' => $glpi_task->getID(), - 'is_private' => isset($glpi_task->fields['is_private']) ? $glpi_task->fields['is_private'] : 0 - ]); - } - PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); - - // restore current glpi time - $_SESSION["glpi_currenttime"] = $saved_date_time; - - return $glpi_task; - } - - return false; - } - - /** - * Summary of claimTask - * will unassign group, and assign tech - * @param mixed $cases_id GLPI case id - * @param mixed $delIndex - * @param mixed $users_id_tech optional is the id of the tech - * who's claimed the task, default current logged-in user - */ - public function claimTask($cases_id, $delIndex, $users_id_tech = null) { - global $DB; - $res = $DB->request('glpi_plugin_processmaker_tasks', ['AND' => ['plugin_processmaker_cases_id' => $cases_id, 'del_index' => $delIndex]]); - //$query = "SELECT * FROM glpi_plugin_processmaker_tasks WHERE plugin_processmaker_cases_id='$cases_id' and del_index=$delIndex; "; - //$res = $DB->query($query); - //if ($DB->numrows($res) > 0) { - if ($row = $res->next()) { - $dbu = new DbUtils; - //$row = $DB->fetch_array( $res ); - $glpi_task = new $row['itemtype']; - $glpi_task->getFromDB( $row['items_id'] ); - - $itemType = str_replace( 'Task', '', $row['itemtype'] ); - $glpi_item = $dbu->getItemForItemtype( $itemType ); - $glpi_item->getFromDB( $glpi_task->fields[ getForeignKeyFieldForItemType( $itemType ) ] ); - - $glpi_task->update( [ 'id' => $row['items_id'], - $glpi_item->getForeignKeyField() => $glpi_item->getId(), - 'users_id_tech' => (isset($users_id_tech)?$users_id_tech: Session::getLoginUserID()), - 'groups_id_tech' => 0, - 'update' => true]); - } - } - - - // /** - // * Summary of getCaseIdFromItem - // * get case id for an id item_id of type item_type (if a case if attached to it) - // * @param string $item_type, the type for the item ("Ticket", "Problem", ...) - // * @param integer $item_id, the id for the item - // * @return string the case guid, false if no case is attached to item, or if an error occurred - // */ - //public static function getCaseIdFromItem ($item_type, $item_id) { - // global $DB; - // $res = $DB->request('glpi_plugin_processmaker_cases', ['AND' => ['itemtype' => $item_type, 'items_id' => $item_id]]); - // //$query = "SELECT * FROM glpi_plugin_processmaker_cases WHERE `itemtype` = '$item_type' AND `items_id` = $item_id ;"; - // // $res = $DB->query($query); - // //if ($DB->numrows($res) > 0) { - // // // case is existing for this item - // // // then get info from db - // // $row = $DB->fetch_array($res); - // if ($row = $res->next()) { - // return $row['id']; - // } - - // return false; - //} - - /** - * Summary of hasCase - * returns true if cases are attached to item, false otherwise - * @param string $item_type, the type for the item ("Ticket", "Problem", ...) - * @param integer $item_id, the id for the item - * @return boolean true if at least one case is attached, otherwise false - */ - public static function hasCase($item_type, $item_id) { - global $DB; - $res = $DB->request('glpi_plugin_processmaker_cases', ['AND' => ['itemtype' => $item_type, 'items_id' => $item_id]]); - if ($res->numrows() > 0) { - return true; - } - - return false; - } - - - ///** - // * Summary of getCaseGuidFromItem - // * get case id for an id item_id of type item_type (if a case if attached to it) - // * @param string $item_type, the type for the item ("Ticket", "Problem", ...) - // * @param integer $item_id, the id for the item - // * @return string the case guid, false if no case is attached to item, or if an error occurred - // */ - //public static function getCaseGuidFromItem ($item_type, $item_id) { - // global $DB; - // $res = $DB->request('glpi_plugin_processmaker_cases', ['AND' => ['itemtype' => $item_type, 'items_id' => $item_id]]); - // //$query = "SELECT * FROM glpi_plugin_processmaker_cases WHERE `itemtype` = '$item_type' AND `items_id` = $item_id ;"; - // //$res = $DB->query($query); - // //if ($DB->numrows($res) > 0) { - // // // case is existing for this item - // // // then get info from db - // // $row = $DB->fetch_array($res); - // if ($row = $res->next()) { - // return $row['case_guid']; - // } - - // return false; - //} - - // /** - // * Summary of getCaseFromItem - // * get case infos for an id item_id of type item_type (if a case if attached to it) - // * @param string $item_type, the type for the item ("Ticket", "Problem", ...) - // * @param integer $item_id, the id for the item - // * @return getCaseInfoResponse object, false if no case is attached to item, or if an error occurred - // */ - //public function getCaseFromItem($item_type, $item_id) { - // global $DB; - - // $caseId = self::getCaseGuidFromItem( $item_type, $item_id ); - // if ($caseId !== false) { - // $caseInfo = $this->getCaseInfo( $caseId ); - // if ($caseInfo !== false && $caseInfo->status_code == 0) { - // return $caseInfo; - // } else { - // return false; // means any error - // } - // } else { - // return false; // means no case - // } - //} - - /** - * Summary of multiexplode - * @param $delimiters - * @param $string - * @return - */ - static function multiexplode($delimiters, $string) { - - $ready = str_replace($delimiters, $delimiters[0], $string); - $launch = explode($delimiters[0], $ready); - return $launch; - } - - /** - * Summary of pre_show_item_processmaker - * @param $params - */ - public static function pre_show_item_processmaker($params) { - - if (!is_array($params['item']) && is_subclass_of($params['item'], 'CommonITILTask')) { - // must check if Task is bound to a PM task - $pmTask = new PluginProcessmakerTask($params['item']->getType()); - $is_pmtask = $pmTask->getFromDB($params['item']->getId()); - if (!$is_pmtask && $params['item']->fields['state'] == Planning::INFO) { - // look if it is a meta task for this process - // means a re-assign or an un-claim task info - $pm_process = new PluginProcessmakerProcess; - if ($pm_process->getFromDBByQuery( " WHERE `taskcategories_id` = ".$params['item']->fields['taskcategories_id'])) { - // then look into content to get case id - $re = '//'; - if (preg_match($re, $params['item']->fields['content'], $matches)) { - // here we get the case id and the task id - $is_pmtask = $pmTask->getFromDB($matches['taskid']); - } - } - } - if ($is_pmtask) { - $params['item']->fields['can_edit'] = false; // to prevent task edition - - // replace ##ticket.url##_PluginProcessmakerCase$processmakercases by a setActiveTab to the Case panel - $taskCat = new TaskCategory; - $taskCat->getFromDB( $params['item']->fields['taskcategories_id'] ); - $taskComment = isset($taskCat->fields['comment']) ? $taskCat->fields['comment'] : ''; - if (Session::haveTranslations('TaskCategory', 'comment')) { - $params['item']->fields['content'] = str_replace( '##processmaker.taskcomment##', - DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskComment ), $params['item']->fields['content'] ); - } else { - $params['item']->fields['content'] = str_replace( '##processmaker.taskcomment##', $taskComment, $params['item']->fields['content'] ); - } - $taskJSId = strtolower("viewitem".$params['item']->getType().$params['item']->getId()); - - // special case for
which will provoke the rendering to be split into several

- // add

which othervise will be missing - if (stripos($params['item']->fields['content'], '
') !== false) { - $params['item']->fields['content'] = str_ireplace('
', '

', $params['item']->fields['content']).'

'; - } - - $tmpCase = new PluginProcessmakerCase; - $tmpCase->getFromDB($pmTask->fields['plugin_processmaker_cases_id']); - $urlLink = $tmpCase->getLinkURL().'&forcetab=PluginProcessmakerTask$'.$pmTask->fields['items_id']; - - echo Html::scriptBlock( " - $('#$taskJSId').find('.item_content').children().not('.read_more').on('click', function ( ) { - //debugger; - document.location='$urlLink' - } ).css('cursor', 'pointer') ; - $('tr[id=\"$taskJSId\"]').children().on('click', function ( ) { - //debugger; - document.location='$urlLink' - } ).css('cursor', 'pointer') ; - "); - - $params['item']->fields['content'] = str_replace( ["\n##processmakercase.url##", '\n##processmakercase.url##', '##processmakercase.url##'], "", $params['item']->fields['content'] ); - - // in order to set NavigationList - Session::initNavigateListItems('PluginProcessmakerCase', - //TRANS : %1$s is the itemtype name, - // %2$s is the name of the item (used for headings of a list) - sprintf('%1$s = %2$s', - $params['options']['parent']->getTypeName(1), $params['options']['parent']->fields["name"])); - } - } - } - - /** - * Summary of pre_show_tab_arbehaviours - * @param array $params info about tab to be shown - * @return void - */ - static function pre_show_tab_processmaker($params) { - global $pmHideSolution; - $plugin = new Plugin(); - $itemtype = $params['item']->getType(); - switch ($itemtype) { - case 'Ticket': - case 'Problem': - case 'Change': - if ($params['options']['id'] && $params['options']['itemtype'] == $itemtype) { - // then we are in an ITIL Object - if (isset($_SESSION['glpiactiveprofile']['interface']) && $_SESSION['glpiactiveprofile']['interface'] != "helpdesk") { - $tabnum = $params['options']['tabnum']; - // tabnum 1 : Processing Ticket, tabnum 2 : Solution - - if ($tabnum == 2 or $tabnum == 1) { - // we must check if we can solve item even if PM case is still running (ex: PIR tasks for Change Management) - $pmCanSolve = PluginProcessmakerCase::canSolve( $params ); - if (!$pmCanSolve) { - // don't display message if arbehaviours is install and activated - if (!$plugin->isInstalled('arbehaviours') || !$plugin->isActivated('arbehaviours')) { - $messageOne = __('A \'Case\' is running!', 'processmaker'); - $messageTwo = __('You must manage it first (see \'Process - Case\' tab)!', 'processmaker'); - // output explicit message to explain why it's not possible to add solution - - $message = "
-
-
-
-
-
-
-
-
-
-

- ".$messageOne." -
-
-

-

- ".$messageTwo." - -

-
-
-
-
-
-
-
-
-
-
"; - } - - $pmHideSolution = true; - $itemtype = strtolower($itemtype); - if ($tabnum == 1 && isset($_SESSION['glpiactiveprofile'][$itemtype.'_status'])) { - // don't display message if arbehaviours is install and activated - if (!$plugin->isInstalled('arbehaviours') || !$plugin->isActivated('arbehaviours')) { - self::displayMessage($message, '', WARNING); - - //save current $_SESSION['glpiactiveprofile'][$itemtype.'_status''] - $_SESSION['glpiactiveprofile'][$itemtype.'_status_save'] = $_SESSION['glpiactiveprofile'][$itemtype.'_status']; - // for all $params['options']['itemtype']. status, disable solved ( life cycles ) - foreach ($_SESSION['glpiactiveprofile'][$itemtype.'_status'] as $key => $value) { - $_SESSION['glpiactiveprofile'][$itemtype.'_status'][$key][CommonITILObject::SOLVED] = 0; - } - } - } else { - // then output a new div and hide solution for content - echo $message; - echo ""; - - } - $itemtype = strtolower($itemtype); - // replace $_SESSION['glpiactiveprofile'][$itemtype.'_status'] with saved value - if ($tabnum == 1 && isset($_SESSION['glpiactiveprofile'][$itemtype.'_status_save'])) { - $_SESSION['glpiactiveprofile'][$itemtype.'_status'] = $_SESSION['glpiactiveprofile'][$itemtype.'_status_save']; - } - - } - } - - } - break; - - } - - } - - - /** - * Summary of getItemUsers - * returns an array of glpi ids and pm ids for each user type assigned to given ticket - * @param string $itemtype - * @param integer $itemId is the ID of the titem - * @param integer $userType is 1 for ticket requesters, 2 for ticket technicians, and if needed, 3 for watchers - * @return array of users in the returned array - */ - public static function getItemUsers($itemtype, $itemId, $userType) { - global $DB; - $dbu = new DbUtils; - $users = [ ]; - - //$itemtable = $dbu->getTableForItemType( $itemtype ) ; - $item = new $itemtype(); - $item_users = $item->userlinkclass; - $item_userstable = $dbu->getTableForItemType( $item_users ); - $itemlink = getForeignKeyFieldForItemType( $itemtype ); - $res = $DB->request([ - 'SELECT' => ['glpi_plugin_processmaker_users.pm_users_id as pm_users_id', 'glpi_plugin_processmaker_users.id as id'], - 'FROM' => $item_userstable, - 'LEFT JOIN' => ['glpi_plugin_processmaker_users' => ['FKEY' => ['glpi_plugin_processmaker_users' => 'id', $item_userstable => 'users_id']]], - 'WHERE' => ['AND' => ["$item_userstable.$itemlink" => $itemId, "$item_userstable.type" => $userType]], - 'ORDER' => ['ORDER' => $item_userstable.'.id'] - ]); - //$query = "select glpi_plugin_processmaker_users.pm_users_id as pm_users_id, glpi_plugin_processmaker_users.id as id from $item_userstable - // left join glpi_plugin_processmaker_users on glpi_plugin_processmaker_users.id = $item_userstable.users_id - // where $item_userstable.$itemlink = $itemId and $item_userstable.type = $userType - // order by $item_userstable.id"; - //foreach ($DB->request( $query ) as $dbuser) { - foreach ($res as $dbuser) { - $users[] = [ 'glpi_id' => $dbuser['id'], 'pm_id' => $dbuser['pm_users_id'] ]; - } - - return $users; - } - - /** - * Summary of saveForm - * This function posts dynaform variables to PM, using the CURL module. - * @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) { - - $loggable = false; - $request = stripcslashes_deep( $request ); - - $ch = curl_init(); - - //to be able to trace network traffic with a local proxy - // curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1 ); - // curl_setopt($ch, CURLOPT_PROXY, "localhost:8888"); - - //curl_setopt($ch, CURLINFO_HEADER_OUT, 1); - //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); - curl_setopt($ch, CURLOPT_HEADER, 1); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_VERBOSE, 1); - curl_setopt($ch, CURLOPT_HTTPHEADER, ["Expect:"]); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->config->fields['ssl_verify']); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->config->fields['ssl_verify']); - - //curl_setopt($ch, CURLOPT_HEADERFUNCTION, "HandleHeaderLine"); - // to store cookies in memory - // ( replace HandleHeaderLine function ) - curl_setopt($ch, CURLOPT_COOKIEFILE, ""); - - // ### first call to open case and get cookies GET ### - curl_setopt($ch, CURLOPT_URL, $this->serverURL."/cases/cases_Open?sid=".$this->getPMSessionID()."&APP_UID=".$request['APP_UID']."&DEL_INDEX=".$request['DEL_INDEX']."&action=TO_DO" ); - $response = curl_exec ($ch); - if ($loggable) { - Toolbox::logInFile( "pmtrace", "URL:\n".$this->serverURL."/cases/cases_Open?sid=".$this->getPMSession()."\nResponse:\n".$response."\n\n\n" ); - } - - // change option to indicate that the next call will be POST - curl_setopt($ch, CURLOPT_POST, 1); - // get and format post values - $data = http_formdata_flat_hierarchy( $request ); - // check if any files are in the $_FILES global array - // and add them to the curl POST - $fileForm = isset($_FILES['form']['name']) ? $_FILES['form']['name'] : null; - if (isset($fileForm) && !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]); - $data["form[$key][$row][$control]"] = $cfile; - } - } - } else { - $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); - curl_setopt($ch, CURLOPT_HTTPHEADER, ["Expect:"]); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // inject POST values - // add agent and referer params - //$agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'; - //$referer = $this->getSiteURL(); - //curl_setopt($ch, CURLOPT_USERAGENT, $agent); - //curl_setopt($ch, CURLOPT_REFERER, $referer); - - // ### 2nd call to save Data POST ### - curl_setopt($ch, CURLOPT_URL, $this->serverURL."/cases/cases_SaveData?UID=".$request['UID']."&APP_UID=".$request['APP_UID'] ); - $response = curl_exec ($ch); - if ($response === false) { - //throw new Exception(curl_error($ch), curl_errno($ch)); - Toolbox::logInFile( "pmtrace", curl_error($ch).":".curl_errno($ch)."\n" ); - } - curl_close ($ch); - if ($loggable) { - Toolbox::logInFile( "pmtrace", "URL:\n".$this->serverURL."/cases/cases_SaveData?UID=".$request['UID']."&APP_UID=".$request['APP_UID']."\nData:\n".print_r($data, true )."\nResponse:\n".$response."\n\n\n" ); - } - - return ($response ? true : false); - } - - /** - * Function to get current site url with protocol ( http or https ) - * @return string - */ - function getSiteURL() { - $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; - $domainName = $_SERVER['HTTP_HOST']; - return $protocol.$domainName; - } - - /** - * Summary of initCaseAndShowTab - * Is used to workaround a SESSION issue in PM server - * PM server stores case context in SESSION variables, - * which leads to issues when viewing two different cases - * in two different tabs of the same browser. - * This workaround will artificially load cases_Open page to force - * initialization of those SESSION variables to prevent mix of values - * when viewing tabs like map, change log, history, and dynaforms - * - * it will also manage the glpi_domain parameter - * - * @param mixed $currentCase array that contains APP_UID, DEL_INDEX - * @param mixed $iFrameUrl string which is the url of the tab panel - * @param mixed $rand integer - */ - public function initCaseAndShowTab($currentCase, $iFrameUrl, $rand) { - $iFrameUrl = urlencode($iFrameUrl); - - echo "
"; - - // will use ajax to be sure that cases_Open page is fully loaded before load of the $iFrameUrl - // this mechanism is mandatory to have correct management of cookies, as cookies transport the session id, - // and such the SESSION variables that contain the case context - echo ""; - - } - - /** - * Summary of plugin_item_get_data_processmaker - * @param mixed $item - */ - public static function plugin_item_get_data_processmaker($item) { - global $_SESSION, $CFG_GLPI; - if (isset( $item->data ) && isset( $item->data['tasks'] )) { - $pmtask_itemtype = $item->obj->getType().'Task'; - $pmtask = new PluginProcessmakerTask($pmtask_itemtype); - foreach ($item->data['tasks'] as &$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 - $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 - } - - $task['##task.description##'] = str_replace( '##processmaker.taskcomment##', $task['##task.categorycomment##'], $task['##task.description##'] ); - $task['##task.description##'] = Html::nl2br_deep($task['##task.description##']); - - //$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']); - - $caseurl = "$caseurl"; - $task['##task.description##'] = str_replace('##processmakercase.url##', $caseurl, $task['##task.description##']); - } - } - } - - } - - - /** - * Summary of plugin_item_get_pdfdata_processmaker - * @param mixed $item - */ - public static function plugin_item_get_pdfdata_processmaker($item) { - if (isset( $item->datas )) { - $config = PluginProcessmakerConfig::getInstance(); - $taskCat = new TaskCategory; - $dbu = new DbUtils; - // save current translations - if (isset( $_SESSION['glpi_dropdowntranslations'] )) { - $trans = $_SESSION['glpi_dropdowntranslations']; - } - // load available translations for this user - $_SESSION['glpi_dropdowntranslations'] = DropdownTranslation::getAvailableTranslations($_SESSION['glpilanguage']); - - $taskCat->getFromDB( $item->datas['taskcategories_id'] ); - $ancestors = $dbu->getAncestorsOf( 'glpi_taskcategories', $item->datas['taskcategories_id']); - if (in_array( $config->fields['taskcategories_id'], $ancestors)) { - $loc_completename = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'completename', $_SESSION['glpilanguage'], $taskCat->fields['completename'] ); - $loc_comment = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskCat->fields['comment'] ); - $item->datas['content'] = $loc_completename."\n\n".str_replace( "##processmaker.taskcomment##", $loc_comment, $item->datas['content']); - $item->datas['content'] = str_replace( "##processmakercase.url##", '', $item->datas['content']); - } - // restore default translations - if (isset( $trans )) { - $_SESSION['glpi_dropdowntranslations'] = $trans; - } else { - unset( $_SESSION['glpi_dropdowntranslations'] ); - } - } - - } - - - /** - * Summary of getProcessesWithCategoryAndProfile - * @param mixed $category - * @param mixed $type - * @param mixed $profile - * @param mixed $entity - */ - public static function getProcessesWithCategoryAndProfile($category, $type, $profile, $entity) { - global $DB; - $dbu = new DbUtils; - $processList = [ ]; - //$entityAncestors = implode( ", ", $dbu->getAncestorsOf( $dbu->getTableForItemType( 'Entity' ), $entity ) ); - $entityAncestors = $dbu->getAncestorsOf( $dbu->getTableForItemType( 'Entity' ), $entity ); - //if (strlen( $entityAncestors ) > 0) { - if ($category > 0) { - $query = [ - 'SELECT DISTINCT' => ['glpi_plugin_processmaker_processes.id' ], - 'FIELDS' => ['glpi_plugin_processmaker_processes.name'], - //'DISTINCT' => true, - 'FROM' => 'glpi_plugin_processmaker_processes', - 'INNER JOIN' => [ - 'glpi_plugin_processmaker_processes_profiles' => [ - 'FKEY' => [ - 'glpi_plugin_processmaker_processes_profiles' => 'plugin_processmaker_processes_id', - 'glpi_plugin_processmaker_processes' => 'id', - ['AND' => [ - 'glpi_plugin_processmaker_processes.itilcategories_id' => ['!=', 0] - ] - ] - ] - ] - ], - 'WHERE' => [ - 'AND' => [ - 'itilcategories_id' => $category, - 'type' => $type, - 'profiles_id' => $profile, - 'entities_id' => $entity - ] - ] - ]; - if (count( $entityAncestors ) > 0) { - //$entityAncestors = " OR (entities_id IN ($entityAncestors) AND is_recursive = 1) "; - $entityAncestors[] = $entity; - $query['WHERE']['AND']['entities_id'] = $entityAncestors; - $query['WHERE']['AND']['is_recursive'] = 1; - } - $res = $DB->request($query); - foreach ($res as $row) { - $processList[] = $row; - } - $processList = array_map("unserialize", array_unique(array_map("serialize", $processList))); - } - //$query ="SELECT DISTINCT glpi_plugin_processmaker_processes.id, glpi_plugin_processmaker_processes.name FROM glpi_plugin_processmaker_processes - // INNER JOIN glpi_plugin_processmaker_processes_profiles ON glpi_plugin_processmaker_processes_profiles.plugin_processmaker_processes_id=glpi_plugin_processmaker_processes.id - // WHERE is_active = 1 AND itilcategories_id = $category AND `type` = $type AND profiles_id = $profile AND (entities_id = $entity $entityAncestors)"; - - //foreach ($DB->request( $query ) as $row) { - - return $processList; - - } - - /** - * Summary of startNewCase - * @param mixed $processes_id integer: GLPI process id - * @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) { - global $DB, $CFG_GLPI; - - $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; - } - - //$impersonateCase = false; - //if (!$users_id) { - // // then we are going to take the item creator to set it as case creator and - // $impersonateCase = true; - - //} - - // get item info to retreive title, description and duedate - $item = new $itemtype; - $item->getFromDB( $items_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($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_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' => $item->fields['entities_id'], - 'plugin_processmaker_processes_id' => $processes_id, - 'plugin_processmaker_cases_id' => 0 - ], - [], true ); - - $this->add1stTask($locCase->getID(), $itemtype, $items_id, $caseInfo, ['userId' => $users_id] ); - } - - return $resultCase; - } - - - /** - * Summary of derivateCase - * in $request must be present - * 'UID', 'APP_UID' and DEL_INDEX' - * - * @param mixed $myCase - * @param mixed $request - * @param mixed $users_id - */ - public function derivateCase($myCase, $request, $users_id = null) { - //$cookies, - global $PM_DB, $CFG_GLPI, $DB; - - $itemtype = $myCase->getField('itemtype'); - $items_id = $myCase->getField('items_id'); - $item = new $itemtype; - $item->getFromDB($items_id); - - //Toolbox::logInFile("processmaker_derivate", Toolbox::backtrace(false) . "derivateCase: myCase = " . print_r($myCase, true) . "\nrequest = " . print_r($request, true) . "\nusers_id = " . print_r($users_id, true) ); - - // save the dynaform variables into the current case - 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']); - //Toolbox::logInFile("processmaker_derivate", "routeCase: pmRouteCaseResponse = " . print_r($pmRouteCaseResponse, true)); - - if ($pmRouteCaseResponse->status_code != 0) { - Session::addMessageAfterRedirect(sprintf(__('Unable to derivate case! Retry in a moment, or ask your administrator.
Error code: %u
Error message: %s
', 'processmaker'), - $pmRouteCaseResponse->status_code, - $pmRouteCaseResponse->message), - true, - ERROR); - return; - } - - $casevariables = ["GLPI_ITEM_TASK_CONTENT", - "GLPI_ITEM_APPEND_TO_TASK", - "GLPI_NEXT_GROUP_TO_BE_ASSIGNED", - "GLPI_ITEM_TASK_GROUP", - "GLPI_ITEM_TITLE", - "GLPI_TICKET_FOLLOWUP_CONTENT", - "GLPI_ITEM_FOLLOWUP_CONTENT", - "GLPI_TICKET_FOLLOWUP_IS_PRIVATE", - "GLPI_ITEM_FOLLOWUP_IS_PRIVATE", - "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID", - "GLPI_ITEM_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_INITIAL_DUE_DATE", - "GLPI_ITEM_DUE_DATE", - "GLPI_SEND_EMAIL", - "GLPI_ITEM_INFORMATION_TASK" - ]; - - // now tries to get some variables to setup content for new task and to append text to solved task - $casevariablevalues = $myCase->getVariables($casevariables); - - $information_task = ''; - if (array_key_exists( 'GLPI_ITEM_INFORMATION_TASK', $casevariablevalues ) && $casevariablevalues[ 'GLPI_ITEM_INFORMATION_TASK' ] != '') { - $information_task = $casevariablevalues[ 'GLPI_ITEM_INFORMATION_TASK' ]; - } - - $sendemail = ''; - if (array_key_exists( 'GLPI_SEND_EMAIL', $casevariablevalues ) && $casevariablevalues[ 'GLPI_SEND_EMAIL' ] != '') { - $sendemail = json_decode($casevariablevalues[ 'GLPI_SEND_EMAIL' ], true); - } - - $itemSetStatus = ''; - 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 )) { - $txtItemTitle = $casevariablevalues[ 'GLPI_ITEM_TITLE' ]; - } - - $txtToAppendToTask = ''; - if (array_key_exists( 'GLPI_ITEM_APPEND_TO_TASK', $casevariablevalues )) { - $txtToAppendToTask = $casevariablevalues[ 'GLPI_ITEM_APPEND_TO_TASK' ]; - } - - $txtTaskContent = ''; - if (array_key_exists( 'GLPI_ITEM_TASK_CONTENT', $casevariablevalues )) { - $txtTaskContent = $casevariablevalues[ 'GLPI_ITEM_TASK_CONTENT' ]; - } - - $groupId = 0; - if (array_key_exists( 'GLPI_NEXT_GROUP_TO_BE_ASSIGNED', $casevariablevalues )) { - $groupId = $casevariablevalues[ 'GLPI_NEXT_GROUP_TO_BE_ASSIGNED' ]; - } - if (array_key_exists( 'GLPI_ITEM_TASK_GROUP', $casevariablevalues )) { - $groupId = $casevariablevalues[ 'GLPI_ITEM_TASK_GROUP' ]; - } - - $taskStartDate = ''; - $taskEndDate = ''; - if (array_key_exists( 'GLPI_ITEM_TASK_ENDDATE', $casevariablevalues )) { - $taskEndDate = $casevariablevalues[ 'GLPI_ITEM_TASK_ENDDATE' ]; - } - if (array_key_exists( 'GLPI_ITEM_TASK_STARTDATE', $casevariablevalues )) { - $taskStartDate = $casevariablevalues[ 'GLPI_ITEM_TASK_STARTDATE' ]; - if ($taskEndDate == '') { - // at least - $taskEndDate = $taskStartDate; - } - } - - $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 )) { - $solvedTaskEndDate = $casevariablevalues[ 'GLPI_ITEM_SOLVED_TASK_ENDDATE' ]; - } - if (array_key_exists( 'GLPI_ITEM_SOLVED_TASK_STARTDATE', $casevariablevalues )) { - $solvedTaskStartDate = $casevariablevalues[ 'GLPI_ITEM_SOLVED_TASK_STARTDATE' ]; - if ($solvedTaskEndDate == '') { - // at least - $solvedTaskEndDate = $solvedTaskStartDate; - } - } - - $solvedTaskSetToInformation = ''; - if (array_key_exists( 'GLPI_ITEM_SOLVED_TASK_SETINFO', $casevariablevalues )) { - $solvedTaskSetToInformation = $casevariablevalues[ 'GLPI_ITEM_SOLVED_TASK_SETINFO' ]; - } - - $createFollowup = false; // by default - if ((array_key_exists( 'GLPI_TICKET_FOLLOWUP_CONTENT', $casevariablevalues ) && $casevariablevalues[ 'GLPI_TICKET_FOLLOWUP_CONTENT' ] != '') - || (array_key_exists( 'GLPI_ITEM_FOLLOWUP_CONTENT', $casevariablevalues ) && $casevariablevalues[ 'GLPI_ITEM_FOLLOWUP_CONTENT' ] != '')) { - $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) { - if (!empty($casevariablevalues[$val])) { - $resetcasevariables[$val] = ''; - } - } - $resultSave = $myCase->sendVariables($resetcasevariables); - - // now manage tasks associated with item - // switch own task to 'done' and create a new one - $glpi_task = $this->solveTask($myCase->getID(), - $request['DEL_INDEX'], - ['txtToAppend' => $txtToAppendToTask, - 'users_id_tech' => $users_id, - 'begin' => $solvedTaskStartDate, - 'end' => $solvedTaskEndDate, - 'toInformation' => $solvedTaskSetToInformation - ] - ); - - // create a followup if requested - if ($createFollowup) { // && $itemtype == 'Ticket') { - $this->addItemFollowup( $itemtype, $items_id, $casevariablevalues ); - } - - if ($txtItemTitle != '') { - // we are going to change the title of current GLPI Item - $this->setItemTitle($itemtype, $items_id, $txtItemTitle); - } - - 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 ) - || array_key_exists( 'GLPI_ITEM_SET_SOLUTION_TYPE_ID', $casevariablevalues ) - || array_key_exists( 'GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION', $casevariablevalues )) { - // case requests to add a solution to ticket - $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 - - // create an information task if requested - if ($information_task != '' && $glpi_task) { - // create an information task and add comment - // $information_task is the content of the task - $pm_process = $myCase->getProcess(); - $taskCat = new TaskCategory; - $taskCat->getFromDB($glpi_task->fields['taskcategories_id']); - // we may replace ##casename## by the name of the case, and ##taskname## by the task name - $search = ['##casename##', - '##taskname##' - ]; - $replace = [$caseInfo->caseName." (".$myCase->getID().")", - DropdownTranslation::getTranslatedValue($glpi_task->fields['taskcategories_id'], 'TaskCategory', 'name', $_SESSION['glpilanguage'], $taskCat->fields['name']) - ]; - $info = str_replace($search, $replace, $information_task); - - $info .= ""; - - // unescape some chars and replace CRLF, CR or LF by
- $info = str_replace(["\\'", '\\"', '\r\n', '\r', '\n'], ["'", '"', '
', '
', '
'], $info); - - $foreignkey = getForeignKeyFieldForItemType($glpi_task->getItilObjectItemType()); - $glpi_task->add([$foreignkey => $glpi_task->fields[$foreignkey], - 'is_private' => 1, - 'taskcategories_id' => $pm_process->fields['taskcategories_id'], - 'content' => $DB->escape($info), - 'users_id' => $this->taskWriter, - 'state' => Planning::INFO, - 'users_id_tech' => Session::getLoginUserID(), - ]); - } - - // now create the new tasks if any - if (property_exists( $pmRouteCaseResponse, 'routing' )) { - - // we may have several task to create - foreach ($pmRouteCaseResponse->routing as $route) { - - // must check if task has started a sub-process - $locTaskCat = new PluginProcessmakerTaskCategory; - if ($locTaskCat->getFromGUID($route->taskId) && $locTaskCat->fields['is_subprocess']) { - // look for APP_UID - $res = $PM_DB->request([ - 'SELECT' => [ - 'APPUID' - ], - 'FROM' => 'SUB_APPLICATION', - 'WHERE' => [ - 'AND' => [ - 'APP_PARENT' => $myCase->fields['case_guid'], - 'DEL_INDEX_PARENT' => $route->delIndex, - 'SA_STATUS' => 'ACTIVE' - ] - ] - ]); - //$res = $PM_DB->query("SELECT APP_UID FROM SUB_APPLICATION WHERE APP_PARENT='{$myCase->fields['case_guid']}' AND DEL_INDEX_PARENT={$route->delIndex} AND SA_STATUS='ACTIVE'"); // AND DEL_THREAD_PARENT={$route->delThread} seems like it is not set to correct threadIndex - //if ($row = $res->next() && $PM_DB->numrows($res) == 1) { - if ($res->numrows() == 1 && $row = $res->next()) { - // then new task is a sub-process, - //$row = $PM_DB->fetch_assoc($res); - - // now need to get the PRO_UID - $sub_caseInfo = self::getCaseInfo($row['APP_UID']); - - $locProc = new PluginProcessmakerProcess; - $locProc->getFromGUID($sub_caseInfo->processId); - $subCase = new PluginProcessmakerCase; - $subCase->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' )) { - // there should be only one task - $sub_route = $sub_caseInfo->currentUsers[0]; - $this->addTask($subCase->getID(), $itemtype, - $items_id, - $sub_caseInfo, - $sub_route->delIndex, - PluginProcessmakerUser::getGLPIUserId($sub_route->userId), - 0, - $sub_route->taskId, - $sub_route->delThread, - [ 'txtTaskContent' => $txtTaskContent, - 'start_date' => $taskStartDate, - 'end_date' => $taskEndDate, - 'reminder' => $taskReminder] - ); - - // if end date was specified, then must change due date of the PM task - if ($taskEndDate != '') { - $PM_DB->update( - 'APP_DELEGATION', - [ - 'DEL_TASK_DUE_DATE' => $taskEndDate - ], - ['AND' => [ - 'APP_UID' => $sub_caseInfo->caseId, - 'DEL_INDEX' => $sub_route->delIndex - ] - ] - ); - //$PM_DB->query( "UPDATE APP_DELEGATION SET DEL_TASK_DUE_DATE='$taskEndDate' WHERE APP_UID='".$sub_caseInfo->caseId."' AND DEL_INDEX=".$sub_route->delIndex); - } - - } - - // must also send to new sub-process some GLPI variables - // like any newly started cases - // get the value of GLPI_ITEM_CAN_BE_SOLVED to transmit it to sub-case - $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; - } - - $glpi_variables = ['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) - 'GLPI_TICKET_TYPE' => $itemtype == 'Ticket' ? $item->fields['type'] : '' - ]; - $subCase->sendVariables($glpi_variables); - - // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED - $subCase->update( [ 'id' => $subCase->getID(), 'case_status' => $sub_caseInfo->caseStatus, 'name' => $sub_caseInfo->caseName ] ); - - } - } else { - - $this->addTask( $myCase->getID(), $itemtype, - $items_id, - $caseInfo, - $route->delIndex, - PluginProcessmakerUser::getGLPIUserId( $route->userId ), - $groupId, - $route->taskId, - $route->delThread, - [ 'txtTaskContent' => $txtTaskContent, - 'start_date' => $taskStartDate, - 'end_date' => $taskEndDate, - 'reminder' => $taskReminder] - ); - // if end date was specified, then must change due date of the PM task - if ($taskEndDate != '') { - $PM_DB->update( - 'APP_DELEGATION', - [ - 'DEL_TASK_DUE_DATE' => $taskEndDate - ], - ['AND' => [ - 'APP_UID' => $caseInfo->caseId, - 'DEL_INDEX' => $route->delIndex - ] - ]); - //$PM_DB->query( "UPDATE APP_DELEGATION SET DEL_TASK_DUE_DATE='$taskEndDate' WHERE APP_UID='".$caseInfo->caseId."' AND DEL_INDEX=".$route->delIndex); - } - } - - } - - } else { - // must check if current case is a sub-process, and if it has ended, then must reflect parent case into the current item. - if ($myCase->fields['plugin_processmaker_cases_id'] != 0) { - // current case is a sub-case of $myCase->fields['plugin_processmaker_cases_id'] - $parentCase = new PluginProcessmakerCase; - $parentCase->getFromDB($myCase->fields['plugin_processmaker_cases_id']); - $parentCaseInfo = $parentCase->getCaseInfo(); - // then create associated task - if (property_exists( $parentCaseInfo, 'currentUsers' )) { - // we may have several new task - foreach ($parentCaseInfo->currentUsers as $open_task) { - // must check if $open_task is not is_subprocess and is not already existing in the item - $locTaskCat = new PluginProcessmakerTaskCategory; - $locTask = new PluginProcessmakerTask($itemtype.'Task'); - - $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->getFromDBByRequest($locTaskRestrict)) { - $this->addTask($parentCase->getID(), $itemtype, - $items_id, - $parentCaseInfo, - $open_task->delIndex, - PluginProcessmakerUser::getGLPIUserId($open_task->userId), - $groupId, - $open_task->taskId, - $open_task->delThread, - [ 'txtTaskContent' => $txtTaskContent, - 'start_date' => $taskStartDate, - 'end_date' => $taskEndDate, - 'reminder' => $taskReminder] - ); - - // if end date was specified, then must change due date of the PM task - if ($taskEndDate != '') { - $PM_DB->update('APP_DELEGATION', ['DEL_TASK_DUE_DATE' => $taskEndDate], ['AND' => ['APP_UID' => $parentCaseInfo->caseId, 'DEL_INDEX' => $open_task->delIndex]]); - //$PM_DB->query( "UPDATE APP_DELEGATION SET DEL_TASK_DUE_DATE='$taskEndDate' WHERE APP_UID='".$sub_caseInfo->caseId."' AND DEL_INDEX=".$open_task->delIndex); - } - } - } - } - // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED - $parentCase->update( [ 'id' => $parentCase->getID(), 'case_status' => $parentCaseInfo->caseStatus, 'name' => $parentCaseInfo->caseName ] ); - } - } - - // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED - $myCase->update( [ 'id' => $myCase->getID(), 'case_status' => $caseInfo->caseStatus, 'name' => $caseInfo->caseName ] ); - - // send email if requested - if (is_array($sendemail)) { - NotificationEvent::raiseEvent('send_email', - $myCase, - ['glpi_send_email' => $sendemail, - 'case' => $myCase - ]); - } - - } - - - /** - * Summary of getPMGroups - * @return array - */ - public static function getPMGroups() { - global $PM_DB; - $pmGroupList = []; - $res = $PM_DB->request( - 'CONTENT', [ - 'AND' => [ - 'CONTENT.CON_CATEGORY' => 'GRP_TITLE', - 'CONTENT.CON_LANG' => 'en' - ] - ]); - //foreach ($PM_DB->request("SELECT * FROM CONTENT WHERE CONTENT.CON_CATEGORY='GRP_TITLE' AND CONTENT.CON_LANG='en'") as $dbgroup) { - foreach ($res as $dbgroup) { - $pmGroupList[$dbgroup['CON_VALUE']] = $dbgroup; - } - return $pmGroupList; - } - - - /** - * Summary of displayMessage - * Show a html message bottom-right of screen - * @param string $html_message message to be shown - * @param string $title if '' then title bar is not shown (default '') - * @param string $msgtype the type of the message (ERROR | WARNING | INFO) - * @return void - **/ - static private function displayMessage($html_message, $title = '', $msgtype = 'info_msg') { - - //set title and css class - switch ($msgtype) { - case ERROR: - $title = __('Error'); - $class = 'err_msg'; - break; - case WARNING: - $title = __('Warning'); - $class = 'warn_msg'; - break; - case INFO: - $title = __('Information'); - $class = 'info_msg'; - break; - } - - echo "
"; - echo $html_message; - echo "
"; - - $scriptblock = " - $(document).ready(function() { - var _of = window; - var _at = 'right-20 bottom-20'; - //calculate relative dialog position - $('.message_after_redirect').each(function() { - var _this = $(this); - if (_this.attr('aria-describedby') != 'message_after_redirect_$msgtype') { - _of = _this; - _at = 'right top-' + (10 + _this.outerHeight()); - } - }); - - $('#message_after_redirect_$msgtype').dialog({ - dialogClass: 'message_after_redirect $class', - minHeight: 40, - minWidth: 200, - position: { - my: 'right bottom', - at: _at, - of: _of, - collision: 'none' - }, - autoOpen: false, - show: { - effect: 'slide', - direction: 'down', - 'duration': 800 - } - }) - .dialog('open');"; - - //do not autoclose errors - if ($msgtype != ERROR) { - $scriptblock .= " - - // close dialog on outside click - $(document.body).on('click', function(e){ - if ($('#message_after_redirect_$msgtype').dialog('isOpen') - && !$(e.target).is('.ui-dialog, a') - && !$(e.target).closest('.ui-dialog').length) { - $('#message_after_redirect_$msgtype').dialog('close'); - // redo focus on initial element - e.target.focus(); - } - });"; - } - - $scriptblock .= " - - }); - "; - - echo Html::scriptBlock($scriptblock); - } - - /** - * Summary of underMaintenance - * Shows a nice(?) under maintenance message - */ - static function showUnderMaintenance() { - global $CFG_GLPI; - echo "
"; - echo Html::image($CFG_GLPI['root_doc'].'/plugins/processmaker/pics/under_maintenance.png'); - echo "

"; - 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); - } - } +$value) { + if (is_array($value)) { + $temp = []; + foreach ($value as $k2 => $val2) { + $temp[ $key.'['.$k2.']' ] = $val2; + } + $vars = array_merge( $vars, http_formdata_flat_hierarchy($temp) ); + } else { + $vars[$key]=$value; + } + } + return $vars; + } + +} + +if (!function_exists('stripcslashes_deep')) { + /** + * Strip c slash for variable & array + * + * @param $value array or string: item to stripslashes (array or string) + * + * @return stripcslashes item + **/ + function stripcslashes_deep($value) { + + $value = is_array($value) ? + array_map('stripcslashes_deep', $value) : + stripcslashes($value); + + return $value; + } +} + +/** + * PluginProcessmakerProcessmaker short summary. + * + * PluginProcessmakerProcessmaker description. + * + * @version 1.0 + * @author MoronO + */ +class PluginProcessmakerProcessmaker extends CommonDBTM { + + var $serverURL; + + var $config; + private $pmSoapClient = null; + private $pmWorkspace = ""; + private $pmAdminSession = false; + + var $taskWriter = 0; + private $pm_group_guid = ''; // guid for default user group in Process Maker is used for all GLPI user synchronization into ProcessMaker + var $lasterror; + var $lang; + + static $rightname = ''; + + const ERROR_CREATING_CASE = 11; + const ERROR_NO_RIGHTS = 14; + const ERROR_CREATING_CASE2 = 100; + + + ///** + //* Return the table used to store this object + //* + //* @return string + //**/ + static function getTable($classname = null) { + + return "glpi_plugin_processmaker_processes"; + } + + + /** + * Summary of getAllTypeArray + * @return string[] + */ + static function getAllPMErrorArray() { + + $tab = [self::ERROR_CREATING_CASE => _x('errors', 'Error creating case!', 'processmaker'), + self::ERROR_NO_RIGHTS => _x('errors', 'Can\'t create case: no rights for it!', 'processmaker'), + self::ERROR_CREATING_CASE2 => _x('errors', 'Error creating case!', 'processmaker')]; + + return $tab; + } + + + /** + * Summary of getProcessTypeName + * @param mixed $value + * @return mixed + */ + static function getPMErrorMessage($value) { + + $tab = static::getAllPMErrorArray(); + // Return $value if not defined + return (isset($tab[$value]) ? $tab[$value] : $value); + } + + + /** + * Summary of addItemFollowup + * @param mixed $itemId + * @param mixed $txtForFollowup + * @param integer $users_id optional, if null will uses logged-in user + */ + public function addItemFollowup($itemtype, $itemId, $txtForFollowup, $users_id = null) { + global $DB; + $fu = new ITILFollowup();//new TicketFollowup(); + //$fu->getEmpty(); // to get default values + $input = $fu->fields; + if (isset( $txtForFollowup['GLPI_TICKET_FOLLOWUP_CONTENT']) && $txtForFollowup['GLPI_TICKET_FOLLOWUP_CONTENT'] != "" ) { + $input['content'] = $DB->escape($txtForFollowup['GLPI_TICKET_FOLLOWUP_CONTENT']); + } + if (isset( $txtForFollowup['GLPI_ITEM_FOLLOWUP_CONTENT']) && $txtForFollowup['GLPI_ITEM_FOLLOWUP_CONTENT'] != "" ) { + $input['content'] = $DB->escape($txtForFollowup['GLPI_ITEM_FOLLOWUP_CONTENT']); + } + if (isset( $txtForFollowup['GLPI_TICKET_FOLLOWUP_IS_PRIVATE'] ) && $txtForFollowup['GLPI_TICKET_FOLLOWUP_IS_PRIVATE'] != "") { + $input['is_private'] = $txtForFollowup['GLPI_TICKET_FOLLOWUP_IS_PRIVATE']; + } + if (isset( $txtForFollowup['GLPI_ITEM_FOLLOWUP_IS_PRIVATE'] ) && $txtForFollowup['GLPI_TICKET_FOLLOWUP_IS_PRIVATE'] != "") { + $input['is_private'] = $txtForFollowup['GLPI_ITEM_FOLLOWUP_IS_PRIVATE']; + } + if (isset( $txtForFollowup['GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID'] ) && $txtForFollowup['GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID'] != "") { + $input['requesttypes_id'] = $txtForFollowup['GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID']; + } + if (isset( $txtForFollowup['GLPI_ITEM_FOLLOWUP_REQUESTTYPES_ID'] ) && $txtForFollowup['GLPI_ITEM_FOLLOWUP_REQUESTTYPES_ID'] != "") { + $input['requesttypes_id'] = $txtForFollowup['GLPI_ITEM_FOLLOWUP_REQUESTTYPES_ID']; + } + $input['items_id'] = $itemId;//$input['tickets_id'] = $itemId; + $input['users_id'] = (isset($users_id) ? $users_id : Session::getLoginUserID( true )); // $this->taskWriter; + $input['itemtype'] = $itemtype; + + $fu->add( $input ); + } + + + /** + * Summary of openSoap + * @return true if open succeeded, and pmSoapClient is initialized + * false otherwise + */ + private function openSoap() { + + try { + if ($this->pmSoapClient == null) { + $this->lang = substr( $_SESSION["glpilanguage"], 0, 2); + if (strlen( $this->lang ) <> 2) { + $this->lang = "en"; // by default + } + $this->config = PluginProcessmakerConfig::getInstance(); + $this->pmWorkspace = $this->config->fields['pm_workspace']; + $this->serverURL = trim($this->config->fields['pm_server_URL'], '/').'/sys'.$this->config->fields['pm_workspace'].'/'.$this->lang.'/'.$this->config->fields['pm_theme']; + $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, + 'keep_alive' => false, + //'trace' => true, + //'exceptions' => false, + //'proxy_host' => 'localhost', + //'proxy_port' => 8889 + ]; + + $this->pmSoapClient = new SoapClient($wsdl, $options); + + } + + return true; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + $this->lasterror = $e; + return false; //null ; + } + } + + + /** + * Summary of getPMSessionID + * @param mixed $case_guid + * @return mixed + */ + function getPMSessionID() { + return $_SESSION["pluginprocessmaker"]["session"]['id']; + } + + /** + * Summary of login + * @param mixed $admin_or_user if true will be admin, otherwise is user name (or user id), or current user + * @return true if login has been correctly done with current GLPI user, or if a PM session was already open + * false if an exception occured (like SOAP error or PM login error) + */ + function login($admin_or_user = false, $case_guid = 'default') { + global $DB, $PM_DB; + try { + $locSession = new stdClass; // by default empty object + if ($this->openSoap( )) { + $cookie_lifetime = ini_get('session.cookie_lifetime'); + if ($cookie_lifetime == 0) { + $cookie_lifetime = 15 * 60; //= 15 minutes + } + if ($admin_or_user === true) { // admin rights has been requested, then force new login + $config = PluginProcessmakerConfig::getInstance(); + $locSession = $this->pmSoapClient->login( [ 'userid' => $config->fields['pm_admin_user'], 'password' => Toolbox::sodiumDecrypt($config->fields['pm_admin_passwd'])] ); + if (is_object( $locSession ) && $locSession->status_code == 0) { + $_SESSION["pluginprocessmaker"]["session"]["admin"] = true; + $_SESSION["pluginprocessmaker"]["session"]["id"] = $locSession->message; + $_SESSION["pluginprocessmaker"]["session"]["date"] = $locSession->timestamp; + $this->pmAdminSession = true; + return true; + } + } else if (empty($_SESSION["pluginprocessmaker"]["session"]["date"]) || ($_SESSION["pluginprocessmaker"]["session"]["admin"] == true) + || $this->pmAdminSession == true + || date_add( date_create( $_SESSION["pluginprocessmaker"]["session"]["date"] ), new DateInterval( "PT".$cookie_lifetime."S" ) ) < date_create( date( "Y-m-d H:i:s" ) ) ) { + // get user from glpi_users table + $gusr = new User; + if (is_numeric($admin_or_user)) { + $gusr->getFromDB($admin_or_user); + } else if ($admin_or_user !== false) { + $gusr->getFromDBbyName($admin_or_user); + } else { + $gusr->getFromDB(Session::getLoginUserID()); + } + if ($gusr) { + // get user from glpi_plugin_processmaker_users table + $pmusr = new PluginProcessmakerUser; + $pmusr->getFromDB($gusr->getID()); + //if (!isset($pmusr->fields['password']) || $pmusr->fields['password'] == "") { + if (is_object($pmusr) && array_key_exists('pm_users_id', $pmusr->fields)) { + $pass = md5(Toolbox::sodiumEncrypt($gusr->getID().$gusr->getName().time())); + //$pmusr->update( array('id' => $pmusr->getID(), 'password' => $pass) ); + // and must be updated also in PM db + $PM_DB->update('RBAC_USERS', ['USR_PASSWORD' => $pass], ['USR_UID' => $pmusr->fields['pm_users_id']]); + //$PM_DB->query("UPDATE RBAC_USERS SET USR_PASSWORD='".$pass."' WHERE USR_UID='".$pmusr->fields['pm_users_id']."' "); + $PM_DB->update('USERS', ['USR_PASSWORD' => $pass], ['USR_UID' => $pmusr->fields['pm_users_id']]); + //$PM_DB->query("UPDATE USERS SET USR_PASSWORD='".$pass."' WHERE USR_UID='".$pmusr->fields['pm_users_id']."' "); + //} + //$locSession = $this->pmSoapClient->login( array( 'userid' => $gusr->fields['name'], 'password' => 'md5:'.$pmusr->fields['password']) ); + $locSession = $this->pmSoapClient->login( ['userid' => $gusr->fields['name'], 'password' => 'md5:'.$pass] ); + if (is_object( $locSession ) && $locSession->status_code == 0) { + $_SESSION["pluginprocessmaker"]["session"]["id"] = $locSession->message; + $_SESSION["pluginprocessmaker"]["session"]["date"] = $locSession->timestamp; + $_SESSION["pluginprocessmaker"]["session"]["admin"] = false; + $this->pmAdminSession = false; + return true; + } + } else { + Toolbox::logDebug( "Processmaker Plugin: $admin_or_user - User not existing in glpi_plugin_processmaker_users table." ); + return false; + } + } else { + Toolbox::logDebug( "Processmaker Plugin: $admin_or_user - User not existing in glpi_users table." ); + return false; + } + } else { + return true; // means a session is already existing in $_SESSION["pluginprocessmaker"]["session"] + } + } + + $this->pmAdminSession = false; + unset($_SESSION["pluginprocessmaker"]["session"]); + Toolbox::logDebug( "Processmaker Plugin: $admin_or_user - Soap problem: ". print_r( $locSession, true ) ); + $this->lasterror = $locSession; + return false; + } catch (Exception $e) { + $this->pmAdminSession = false; + unset($_SESSION["pluginprocessmaker"]["session"]); + Toolbox::logDebug( $e ); + return false; + } + } + + + /** + * Summary of processList + * Returns list of processes + * Embedded processList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#processList.28.29) + * A session must be open before with login() + * Normalizes output to an array, even when only one element is returned by PM + * @return an array of processListStruct objects + */ + function processList() { + try { + $pmProcessList = $this->pmSoapClient->processList( [ 'sessionId' => $this->getPMSessionID()] ); + if (isset( $pmProcessList->processes )) { + if (is_array( $pmProcessList->processes )) { + return $pmProcessList->processes; + } else { + return [ 0 => $pmProcessList->processes ]; + } + } + + return false; + + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of getCaseInfo + * returns information about a given case (as long as the logged in user has privileges to access the case). + * Embedded getCaseInfo() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#getCaseInfo.28.29) + * A session must be open before with login() + * Normalizes output of currentUsers to an array, even when only one element is returned by PM, + * Note: currentUsers field doesn't exist when case is CANCELLED + * @param $caseGuid: The case GUID, which can be obtained with the caseList() function + * @param $delIndex: The delegation index, which is a positive integer to identify the current task of the case. If empty then use current delIndex. + * @return a getCaseInfoResponse object, or false exception occured + */ + function getCaseInfo($caseGuid, $delIndex = '') { + try { + $pmCaseInfo = $this->pmSoapClient->getCaseInfo( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $caseGuid, 'delIndex' => $delIndex] ); + if (property_exists($pmCaseInfo, 'currentUsers')) { + switch ($pmCaseInfo->caseStatus) { + case 'DRAFT' : + case 'TO_DO': + // case 'CANCELLED' : + if (is_object( $pmCaseInfo->currentUsers )) { + $pmCaseInfo->currentUsers = [ 0 => $pmCaseInfo->currentUsers ]; + } + if ($pmCaseInfo->currentUsers[0]->delThreadStatus == 'PAUSE') { + $pmCaseInfo->caseStatus = "PAUSED"; + } + break; + } + } + return $pmCaseInfo; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + + } + + /** + * Summary of routeCase + * routes a case (i.e., moves the case to the next task in the process according to its routing rules). + * Embedded routeCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#routeCase.28.29) + * A session must be open before with login() + * @param $case_guid string The case GUID, which can be obtained with the caseList() function + * @param $delIndex integer The delegation index, which is a positive integer to identify the current task of the case. If empty then use current delIndex. + * @return stdClass|boolean routeCaseResponse object or false when exception occured. routing is normalized to be always an array of routeListStruct + */ + function routeCase($case_guid, $delIndex) { + try { + $pmRouteCaseResponse = $this->pmSoapClient->routeCase( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $case_guid, 'delIndex' => $delIndex] ); + if ($pmRouteCaseResponse->status_code != 0) { + Toolbox::logDebug( 'routeCase res:', $pmRouteCaseResponse ); + } + + if (property_exists( $pmRouteCaseResponse, 'routing' ) && is_object( $pmRouteCaseResponse->routing )) { + $pmRouteCaseResponse->routing = [ 0 => $pmRouteCaseResponse->routing]; + } + + return $pmRouteCaseResponse; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of triggerList + * Returns list of triggers + * Embedded triggerList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#triggerList.28.29) + * A session must be open before with login() + * Normalizes output to an array, even when only one element is returned by PM + * @return an array of triggerListStruct objects, or false when exception occured + */ + function triggerList() { + try { + $pmTriggerList = $this->pmSoapClient->triggerList( [ 'sessionId' => $this->getPMSessionID()] ); + if (is_array( $pmTriggerList->triggers )) { + return $pmTriggerList->triggers; + } else { + return [ 0 => $pmTriggerList->triggers ]; + } + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of taskList + * Returns list of tasks to which the logged-in user is assigned + * Embedded taskList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#taskList.28.29) + * A session must be open before with login() + * Normalizes output to an array, even when only one element is returned by PM + * @return an array of taskListStruct objects, or false when exception occured + */ + function taskList() { + try { + $pmTaskList = $this->pmSoapClient->taskList( [ 'sessionId' => $this->getPMSessionID()] ); + + if (is_array( $pmTaskList->tasks )) { + return $pmTaskList->tasks; + } else { + return [ 0 => $pmTaskList->tasks ]; + } + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + + /** + * Summary of taskCase + * Returns list of tasks to which the logged-in user is assigned + * Embedded taskList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#taskList.28.29) + * A session must be open before with login() + * Normalizes output to an array, even when only one element is returned by PM + * @return array of taskListStruct objects, or false when exception occured + */ + function taskCase($case_guid) { + try { + $pmTaskCase = $this->pmSoapClient->taskCase( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $case_guid ] ); + + if (is_array( $pmTaskCase->taskCases )) { + return $pmTaskCase->taskCases; + } else { + return [ 0 => $pmTaskCase->taskCases ]; + } + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of claimCase + * @param mixed $case_guid + * @param mixed $delIndex + * @return mixed + */ + function claimCase($case_guid, $delIndex) { + try { + $pmClaimCase = $this->pmSoapClient->claimCase( [ 'sessionId' => $this->getPMSessionID(), 'guid' => $case_guid, 'delIndex' => $delIndex] ); + return $pmClaimCase; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of unpauseCase + * Unpauses a specified case. + * Embedded UnpauseCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#UnpauseCase.28.29) + * A session must be open before with login() + * Normalizes output to an array, even when only one element is returned by PM + * @param $caseGuid The unique ID of the case. + * @param $delIndex The delegation index of the current task in the case. + * @param $userGuid The unique ID of the user who will unpause the case. + * @return an array of UnpauseCaseStruct, or false when exception occured + */ + function unpauseCase($caseGuid, $delIndex, $userGuid) { + try { + $pmUnpauseCase = $this->pmSoapClient->unpauseCase( [ 'sessionId' => $this->getPMSessionID(), 'caseUid' => $caseGuid, 'delIndex' => $delIndex, 'userUid' => $userGuid] ); + + if (is_array( $pmUnpauseCase->processes )) { + return $pmUnpauseCase->processes; + } else { + return [ 0 => $pmUnpauseCase->processes ]; + } + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of caseList + * returns a list of the cases for the logged-in user. + * Embedded caseList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#caseList.28.29) + * A session must be open before with login() + * Normalizes output to an array, even when only one element is returned by PM + * @return an array of cases, or false when exception occured + */ + function caseList() { + try { + $pmCaseList = $this->pmSoapClient->caseList( [ 'sessionId' => $this->getPMSessionID()] ); + + if (is_array( $pmCaseList->cases )) { + return $pmCaseList->cases; + } else { + return [ 0 => $pmCaseList->cases ]; + } + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of systemInformation + * returns information about the PM system + * Embedded systemInformation() PM web service call (definition: http://wiki.processmaker.com/index.php/ProcessMaker_WSDL_Web_Services#systemInformation.28.29) + * A session must be open before with login() + * @return an object containing information, or false when exception occured + */ + function systemInformation() { + try { + $pmSystemInfo = $this->pmSoapClient->systemInformation( [ 'sessionId' => $this->getPMSessionID()] ); + return $pmSystemInfo; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of reassignCase + * reassigns a case to a different user. Note that the logged-in user needs to have the PM_REASSIGNCASE permission in his/her role in order to be able to reassign the case. + * Embedded caseList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#reassignCase.28.29) + * A session must be open before with login() + * @param $caseGuid The case GUID, which can be obtained with the caseList() function. + * @param $delIndex The current delegation index number of the case, which can be obtained with the caseList() function. + * @param $userGuidSource The PM user GUID who is currently assigned the case, which can be obtained with the caseList() function. + * @param $userGuidTarget The PM target user GUID who will be newly assigned to the case, which can be obtained with userList(). The case can only be reassigned to a user who is one of the assigned users or ad-hoc users to the current task in the case. + * @return stdClass, a pmResponse object, or false when exception occured + */ + function reassignCase($caseGuid, $delIndex, $userGuidSource, $userGuidTarget) { + try { + $pmResults = $this->pmSoapClient->reassignCase( ['sessionId' => $this->getPMSessionID(), + 'caseId' => $caseGuid, + 'delIndex' => $delIndex, + 'userIdSource' => $userGuidSource, + 'userIdTarget'=> $userGuidTarget] ); + return $pmResults; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + + /** + * Summary of deleteCase + * Deletes a case + * Embedded deleteCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#deleteCase.28.29) + * A session must be open before with login() + * Beware that at any time you may delete a case!!! + * @param $caseUid The case ID, which can be obtained with the caseList() function. + * @return A deleteCaseResponse object, or false when exception occured + */ + function deleteCase($caseUid) { + try { + $deleteCaseResponse = $this->pmSoapClient->deleteCase( [ 'sessionId' => $this->getPMSessionID(), 'caseUid' => $caseUid] ); + return $deleteCaseResponse; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + + /** + * Summary of cancelTask + * Cancels a task + * Embedded cancelCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#cancelCase.28.29) + * A session must be open before with login() + * Beware that this will only cancel the task with delIndex + * in the case of // tasks you must call cancelTask for each running task. + * in the case of one and only one task running, then it will cancel the case + * @param $caseUid The case ID, which can be obtained with the caseList() function. + * @param $delIndex The delegation index of the current task in the case. + * @param $userUid: The unique ID of the user who will unpause the case. + * @return A cancelCaseResponse object, or false when exception occured + */ + function cancelTask($caseUid, $delIndex, $userUid) { + try { + $cancelTaskResponse = $this->pmSoapClient->cancelCase( [ 'sessionId' => $this->getPMSessionID(), 'caseUid' => $caseUid, 'delIndex' => $delIndex, 'userUid' => $userUid] ); + return $cancelTaskResponse; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + + /** + * Summary of cancelCase + * Cancels a case + * Embedded cancelCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#cancelCase.28.29) + * A session must be open before with login() + * Beware that this will cancel all running task + * in the case of // tasks you must call cancelCase for each running task. + * in the case of one and only one task is running, then it will cancel the case + * @param $caseUid The case ID, which can be obtained with the caseList() function. + * @param $delIndex The delegation index of the current task in the case. + * @param $userUid: The unique ID of the user who will unpause the case. + * @return A cancelCaseResponse object, or false when exception occured + */ + function cancelCase($caseUid) { + try { + $pmCaseInfo = $this->getCaseInfo( $caseUid ); + if ($pmCaseInfo->status_code == 0) { + foreach ($pmCaseInfo->currentUsers as $pmUser) { + $pmCancelTask = $this->cancelTask( $caseUid, $pmUser->delIndex, $pmUser->userId ); + if ($pmCancelTask->status_code != 0) { + return $pmCancelTask; + } + } + } + return $pmCancelTask; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + + /** + * Summary of newCaseImpersonate + * Starts a new case under the name of the logged-in user. + * The task that will be started is the default one (=must be unique in process definition)! + * logged-in user must be assigned to this task, otherwise use newCaseImpersonate() to start the case. + * New case is started with DRAFT status. + * Embedded newCaseImpersonate() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#newCaseImpersonate.28.29) + * A session must be open before with login(), in order to call this function. + * @param $processes_id integer: The GLPI ID of the process that must be used to start a new case + * @param $userId The ID of the user who initiates the case, which can be obtained with userList(). + * @param $vars an array of associative variables (name => value) that will be injected into the case as case variables + * @return A newCaseResponse object, or false when exception occured + */ + function newCaseImpersonate($processes_id, $userId, $vars = null) { + try { + $this->getFromDB($processes_id); + + if ($vars !== null) { + $aVars = []; + foreach ($vars as $key => $val) { + $obj = new variableStruct(); + $obj->name = $key; + $obj->value = $val; + $aVars[] = $obj; + } + } else { + $aVars = ''; + } + + $newCaseResponse = $this->pmSoapClient->newCaseImpersonate( [ 'sessionId' => $this->getPMSessionID(), 'processId'=> $this->fields['process_guid'], 'userId' => $userId, 'taskId'=>'', 'variables'=> $aVars] ); + return $newCaseResponse; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of newCase + * Starts a new case under the name of the logged-in user. + * The task that will be started is the default one (=must be unique in process definition)! + * logged-in user must be assigned to this task, otherwise use newCaseImpersonate() to start the case. + * New case is started with DRAFT status. + * Embedded newCase() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#newCase.28.29) + * A session must be open before with login() + * @param $processes_id integer: the GLPI ID of the process which will be instantied into a case + * @param array $vars an array of associative variables (name => value) that will be injected into the case as case variables + * @return boolean|newCaseResponse: false when exception occured + */ + function newCase($processes_id, $vars = []) { + try { + $this->getFromDB($processes_id); + + $aVars = []; + foreach ($vars as $key => $val) { + $obj = new variableStruct(); + $obj->name = $key; + $obj->value = $val; + $aVars[] = $obj; + } + + $newCaseResponse = $this->pmSoapClient->newCase( [ 'sessionId' => $this->getPMSessionID(), 'processId'=> $this->fields['process_guid'], 'taskId'=>'', 'variables'=> $aVars] ); + + return $newCaseResponse; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of sendVariables + * Sends variables to a case. + * Embedded sendVariables() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#sendVariables.28.29) + * A session must be open before with login() + * @param string $caseGuid The GUID of the case + * @param array $vars an array of associative variables (name => value) that will be injected into the case as case variables + * @return A pmResponse object, or false when exception occured + */ + function sendVariables($caseGuid, $vars = []) { + if (count( $vars ) == 0) { // nothing to send + return true; + } + try { + $aVars = []; + foreach ($vars as $key => $val) { + $obj = new variableStruct(); + $obj->name = $key; + if (is_array( $val )) { + $obj->value = join( "|", $val ); + } else { + $obj->value = $val; + } + $aVars[] = $obj; + } + + $pmResponse = $this->pmSoapClient->sendVariables( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $caseGuid, 'variables'=> $aVars] ); + + return $pmResponse; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + + + /** + * Summary of getVariables + * Gets variables from a case. + * Embedded getVariables() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#getVariables.28.29) + * A session must be open before with login() + * @param string $case_guid The uID of the case + * @param array $vars an array of variable name that will be read from the case as case variables Normalizes output to an array, even when only one element is returned by PM Normalizes output to an array, even when only one element is returned by PM + * Normalizes output to an array, even when only one element is returned by PM + * @return array: an associative array (variable_name => value), or false when exception occured. The return array can be empty if requested variables are not found. + */ + function getVariables($case_guid, $vars = []) { + try { + $aVars = []; + foreach ($vars as $key => $name) { + $obj = new getVariableStruct(); + $obj->name = $name; + $aVars[] = $obj; + } + + $pmvariableListResponse = $this->pmSoapClient->getVariables( [ 'sessionId' => $this->getPMSessionID(), 'caseId' => $case_guid, 'variables'=> $aVars] ); + + $variablesArray = []; + + if ($pmvariableListResponse->status_code == 0 && isset( $pmvariableListResponse->variables )) { + if (is_array( $pmvariableListResponse->variables )) { + foreach ($pmvariableListResponse->variables as $variable) { + $variablesArray[$variable->name] = $variable->value; + } } else { + $variablesArray[$pmvariableListResponse->variables->name] = $pmvariableListResponse->variables->value; + } + } + + return $variablesArray; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of groupList + * returns a list of the groups. For privileges to see the list, the logged-in user must have the PM_USERS permission in his/her role. + * Embedded groupList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#groupList.28.29) + * A session must be open before with login() + * Normalizes output to an array, even when only one element is returned by PM + * @return an array of groupListStruct, or false when exception occured + */ + function groupList() { + try { + $pmGroupList = $this->pmSoapClient->groupList( [ 'sessionId' => $this->getPMSessionID()] ); + + if (is_array( $pmGroupList->groups )) { + return $pmGroupList->groups; + } else { + return [ 0 => $pmGroupList->groups ]; + } + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of assignUserToGroup + * assigns a user to a group. For privileges to assign a user, the logged-in user must have the PM_USERS permission in his/her role. + * Embedded assignUserToGroup() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#assignUserToGroup.28.29) + * A session must be open before with login() + * @param $userId a Processmaker user id (see userList()) + * @param $groupId a Processmaker group id (see groupList()) + * @return A pmResponse object, or false when exception occured + */ + function assignUserToGroup($userId, $groupId) { + try { + $pmResults = $this->pmSoapClient->assignUserToGroup([ 'sessionId' => $this->getPMSessionID(), + 'userId' => $userId, + 'groupId' => $groupId + ] ); + return $pmResults; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of createGroup + * creates a new group. For privileges to create a group, the logged-in user must have the PM_USERS permission in his/her role. + * group will be created as 'ACTIVE' + * Embedded createGroup() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#createGroup.28.29) + * A session must be open before with login() + * @param $name: the name of the group to be created + * @return A pmResponse object, or false when exception occured + */ + function createGroup($name) { + try { + $pmResults = $this->pmSoapClient->createGroup([ 'sessionId' => $this->getPMSessionID(), + 'name' => $name ] ); + return $pmResults; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of updateGroup + * updates group directly into Processmaker DB + * @param $group_id: guid of the pm group + * @param $groupStatus: new status to be set to $group_id, could be 'ACTIVE' or 'INACTIVE' + * @return true if group status has been modified, false otherwise + */ + function updateGroup($group_id, $groupStatus) { + global $PM_DB; + $PM_DB->update('GROUPWF', ['GRP_STATUS' => $groupStatus], ['GRP_UID' => $group_id]); + //$query = "UPDATE GROUPWF SET GRP_STATUS='$groupStatus' WHERE GRP_UID='$group_id';"; + //$PM_DB->query( $query ); + if ($PM_DB->affected_rows != 1) { + return false; + } else { + return true; + } + } + + /** + * Summary of userList + * returns a list of the Processmaker users. For privileges to see the list, the logged-in user must have the PM_USERS permission in his/her role. + * Embedded userList() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#userList.28.29) + * A session must be open before with login() + * Normalizes output to an array, even if only one element is returned by PM + * @return an array of userListStruct, or false when exception occured + */ + function userList() { + try { + $pmUserList = $this->pmSoapClient->userList( [ 'sessionId' => $this->getPMSessionID()] ); + + if (is_array( $pmUserList->users )) { + return $pmUserList->users; + } else { + return [ 0 => $pmUserList->users ]; + } + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of createUser + * creates a new user. For privileges to create a user, the logged-in user must have the PM_USERS permission in his/her role. + * Embedded createUser() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#createUser.28.29) + * A session must be open before with login() + * @param $userId The username for the new user. The unique ID for the user will be automatically generated. Is the user Windows login! + * @param $firstname The user's first name. If empty (== null or == "") will default to $userId. + * @param $lastname The user's last name. If empty (== null or == "") will default to $userId. + * @param $email The user's email address. If empty (== null or == "") will default to $userId@DoNotReply.com. + * @param $role The user's role, such as 'PROCESSMAKER_ADMIN', 'PROCESSMAKER_MANAGER' or 'PROCESSMAKER_OPERATOR'. Possible values can be looked up with the roleList() function. + * @param $password The user's password, such as 'Be@gle2'. (It will be automatically converted into an MD5 hash when inserted in the database.) + * @param $status The user's status, such as "ACTIVE", "INACTIVE". + * @return returns a createUserResponse object, or false if exception occurred + */ + function createUser($userId, $firstname, $lastname, $email, $role, $password, $status) { + try { + if ($firstname == null || $firstname == "") { + $firstname = $userId; + } + if ($lastname == null || $lastname == "") { + $lastname = $userId; + } + if ($email == "") { + $email = $userId."@DoNotReply.com"; + } + + $pmResults = $this->pmSoapClient->createUser([ 'sessionId' => $this->getPMSessionID(), + 'userId' => $userId, + 'firstname'=> $firstname, + 'lastname' => $lastname, + 'email' => $email, + 'role' => $role, + 'password' => $password, + 'status' => $status ] ); + return $pmResults; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + + /** + * Summary of updateUser + * updates user information. + * Embedded updateUser() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#updateUser.28.29) + * A session must be open before with login() + * @param $userUid the unique Id for the user (Processmaker user id) + * @param $userName is the user logon. IT IS STRONGLY ADVISE NOT TO CHANGE THIS INFORMATION + * @param $firstname The user's first name. If empty (== null or == "") will default to $userName. + * @param $lastname The user's last name. If empty (== null or == "") will default to $userName. + * @param $status The user's status, such as "ACTIVE", "INACTIVE". + * @return returns a UpdateUserResponse object, or false if exception occurred + */ + function updateUser($userUid, $userName, $firstName, $lastName, $status) { + try { + if ($firstName == null || $firstName == "") { + $firstName = $userName; + } + if ($lastName == null || $lastName == "") { + $lastName = $userName; + } + + $pmResults = $this->pmSoapClient->updateUser([ 'sessionId' => $this->getPMSessionID(), + 'userUid' => $userUid, + 'userName' => $userName, + 'firstName'=> $firstName, + 'lastName' => $lastName, + 'status' => $status + ] ); + return $pmResults; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + /** + * Summary of executeTrigger + * executes a ProcessMaker trigger. + * Note that triggers which are tied to case derivation will be executed automatically, so this function does not need to be called when deriving cases. + * Embedded executeTrigger() PM web service call (definition: http://wiki.processmaker.com/index.php/2.0/ProcessMaker_WSDL_Web_Services#executeTrigger.28.29) + * A session must be open before with login() + * @param $caseId The case ID, which is can be found with caseList(). + * @param $triggerIndex The ID of the trigger to execute, which can be found with triggerList(). + * @param $delIndex The delegation index number of the case, which can be found with caseList(). + * @return A pmResponse object. If successful, the message will contain "executed: ". Otherwise false in case of SOAP error + */ + function executeTrigger($caseId, $triggerIndex, $delIndex) { + try { + $pmResults = $this->pmSoapClient->executeTrigger([ 'sessionId' => $this->getPMSessionID(), 'caseId' => $caseId, 'triggerIndex'=> $triggerIndex, 'delIndex' => $delIndex ] ); + return $pmResults; + } catch (Exception $e) { + Toolbox::logDebug( $e ); + return false; + } + } + + + + /** + * summary of cronInfo + * Gives localized information about 1 cron task + * @param $name of the task + * @return array of strings + */ + static function cronInfo($name) { + switch ($name) { + case 'pmusers' : + return ['description' => __('Syncs GLPI users and groups into ProcessMaker.', 'processmaker')]; + case 'pmorphancases' : + return ['description' => __('Cleaning of orphan cases.', 'processmaker'), 'parameter' => __('Number of days to keep orphan cases', 'processmaker')]; + case 'pmtaskactions' : + return ['description' => __('To apply task actions between cases.', 'processmaker')]; + } + return []; + } + + /** + * summary of cronPMTaskActions + * Execute 1 task managed by the plugin + * @param: $task CronTask class for log / stat + * @return integer + * >0 : done + * <0 : to be run again (not finished) + * 0 : nothing to do + */ + static function cronPMTaskActions($crontask = null) { + global $DB, $PM_DB, $PM_SOAP; + $dbu = new DbUtils; + + // also create a GLPI session with the processmaker task writer + $usr = new User; + $config = PluginProcessmakerConfig::getInstance(); + $usr->getFromDB($config->fields['users_id']); + $save_session = $_SESSION; + $usr->loadMinimalSession(0, true); + $_SESSION['glpiparententities'] = []; + + $actionCode = 0; // by default + $error = false; + if ($crontask) { + $crontask->setVolume(0); // start with zero + } + + $existingpmsession = isset($_SESSION["pluginprocessmaker"]["session"]); + $formerusers_id = 0; + // get the list of taskactions to be done + $locCase = new PluginProcessmakerCase; + //foreach ($DB->request( $dbu->getTableForItemType('PluginProcessmakerCrontaskaction'), ' `state` = '.PluginProcessmakerCrontaskaction::DATA_READY ) as $taskaction) { + foreach ($DB->request( $dbu->getTableForItemType('PluginProcessmakerCrontaskaction'), ['state' => PluginProcessmakerCrontaskaction::DATA_READY] ) as $taskaction) { + if ($locCase->getFromDB($taskaction['plugin_processmaker_cases_id'])) { + // there is an existing case for this crontaskaction. + try { + + $users_id = $taskaction['users_id']; + if ($formerusers_id != $users_id) { + unset($_SESSION["pluginprocessmaker"]["session"]); // to reset previous user login if any + } + + $caselink = new PluginProcessmakerCaselink; + $caselink->getFromDB($taskaction['plugin_processmaker_caselinks_id']); + + // get current task in current case + $PM_SOAP->login(true); + $caseinfo = $locCase->getCaseInfo(); + $currenttask = false; + if (property_exists($caseinfo, 'currentUsers')) { + foreach ($caseinfo->currentUsers as $loctask) { + if ($loctask->taskId == $caselink->fields['targettask_guid']) { + $currenttask = $loctask; + break; + } + } + } + + // if $currenttask is false then it means that the target task MUST not derived + if ($currenttask) { + if ($caselink->fields['is_targettoimpersonate'] && !$taskaction['is_targettoclaim']) { + // 1) get the current assigned user for this task + // then must login with the user assigned to the task, and not with the user who did the current task + if ($currenttask->userId != '') { + // 3) change login: impersonate + $users_id = PluginProcessmakerUser::getGLPIUserId($loctask->userId); + } + } + + $PM_SOAP->login($users_id); + + $postdata = json_decode($taskaction['postdata'], true); + + // must filter arrays as arrays are grids and index must start at 1 instead of 0 like in json + // TODO: to check if it would be possible to do this in a more generic way + foreach ($postdata['form'] as &$field) { + if (is_array($field)) { + if (count($field) > 0) { + // then must reindex the array starting to 1 instead of 0 + array_unshift($field, ''); + unset($field[0]); + } else { + $field[] = ""; + } + } + } + + if ($taskaction['is_targettoclaim'] && !$caselink->fields['is_targettoimpersonate']) { + // must do a claim before solving task + if (!$PM_SOAP->claimCase( $postdata['APP_UID'], $postdata['DEL_INDEX'] )) { + throw new Exception("Can't claim case"); + } + + // do not send notifications + $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); + + // now manage tasks associated with item + $PM_SOAP->claimTask( $postdata['APP_UID'], $postdata['DEL_INDEX'], $users_id ); + + PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); + + } + + $tkaction = new PluginProcessmakerCrontaskaction; + $tkaction->update( ['id' => $taskaction['id'], 'state' => PluginProcessmakerCrontaskaction::DONE] ); + + $PM_SOAP->derivateCase($locCase, $postdata, $users_id ); + + if ($crontask) { + $crontask->addVolume(1); + } + if ($crontask) { + $crontask->log( "Applied task action id: '".$taskaction['id']."'" ); + } + } else { + $tkaction = new PluginProcessmakerCrontaskaction; + $tkaction->update( ['id' => $taskaction['id'], 'state' => PluginProcessmakerCrontaskaction::NOT_DONE] ); + if ($crontask) { + $crontask->log( "Task action id: '".$taskaction['id']."' case task not found or not open!" ); + } + } + + } catch (Exception $e) { + if ($crontask) { + $crontask->log( "Can't apply task action id: '".$taskaction['id']."'" ); + } + $error = true; + } + + $formerusers_id = $users_id; + } + } + + if ($existingpmsession) { + unset($_SESSION["pluginprocessmaker"]["session"]); // reset the one created during the foreach + if (!Session::isCron()) { + $PM_SOAP->login(); // re-log default user + } + } + + // restore previous session + Session::destroy(); + Session::start(); + $_SESSION = $save_session; + + if ($error) { + return -1; + } else { + return $actionCode; + } + + } + + + /** + * summary of cronPMOrphanCases + * Execute 1 task managed by the plugin + * @param: $task CronTask class for log / stat + * @return integer + * >0 : done + * <0 : to be run again (not finished) + * 0 : nothing to do + */ + static function cronPMOrphanCases($task) { + global $PM_DB, $DB, $PM_SOAP; + + //plugin_processmaker_post_init(); + + // get list of case assigned to GLPI items + $draftCases = [0]; + $query = "SELECT id FROM glpi_plugin_processmaker_cases WHERE case_status = 'DRAFT';"; + //foreach ($DB->request( $query ) as $row) { + foreach ($DB->request(['SELECT' => 'id', 'FROM' => 'glpi_plugin_processmaker_cases'], ['case_status' => 'DRAFT']) as $row) { + $draftCases[] = $row['id']; + } + + $actionCode = 0; // by default + $error = false; + $task->setVolume(0); // start with zero + + if (count($draftCases) > 0) { + //$PM_SOAP = new self; + $PM_SOAP->login(true); + $query = "SELECT * FROM APPLICATION + WHERE APP_DATA LIKE '%s:24:\"GLPI_SELFSERVICE_CREATED\";s:1:\"1\"%' + AND APP_STATUS = 'DRAFT' + AND DATEDIFF( NOW(), APP_UPDATE_DATE) > ".$task->fields['param']." + AND APP_NUMBER NOT IN (".implode(',', $draftCases)."); + "; + $res = $PM_DB->request('APPLICATION', ['AND' => [ + 'APP_DATA' => ['LIKE', '%s:24:\"GLPI_SELFSERVICE_CREATED\";s:1:\"1\"%'], + 'APP_STATUS' => 'DRAFT', + 'RAW' => ['DATEDIFF(NOW(), APP_UPDATE_DATE)' => ['>', $task->fields['param']]], + 'NOT' => ['APP_NUMBER' => $draftCases] + ]]); + //foreach ($PM_DB->request( $query ) as $row) { + foreach ($res as $row) { + $ret = $PM_SOAP->deleteCase( $row['APP_UID'] ); + $task->addVolume(1); + if ($ret !== false) { + $task->log( "Deleted case num: '".$row['APP_NUMBER']."'" ); + $actionCode = 1; + } else { + $task->log( "Can't delete case num: '".$row['APP_NUMBER']."'" ); + $error = true; + } + } + } + if ($error) { + return -1; + } else { + return $actionCode; + } + + } + + + /** + * summary of cronPMUsers + * Executes 1 task managed by the plugin + * @param $task CronTask class for log / stat + * @return integer + * >0 : done + * <0 : to be run again (not finished) + * 0 : nothing to do + */ + static function cronPMUsers($task) { + global $DB, $PM_DB, $PM_SOAP; + + //plugin_processmaker_post_init(); + + $actionCode = 0; // by default + $error = false; + $task->setVolume(0); // start with zero + + // start a processmaker session + if (!isset($PM_SOAP)) { + $PM_SOAP = new PluginProcessmakerProcessmaker(); + } + if (!$PM_SOAP->login( true )) { + $task->log( "Error PM: '".print_r($PM_SOAP->lasterror, true)."'" ); + return -1; + } + + $pmGroupList = $PM_SOAP->groupList( ); + $pmGroup = null; + //if($pmgrp_key = array_search($PM_SOAP->pm_group_guid, array_column($pmGroupList, 'guid'))) { + // $pmgroup = $pmGroupList[$pmgrp_key]; + //} + foreach ($pmGroupList as $pmGrp) { + if ($pmGrp->guid == $PM_SOAP->pm_group_guid) { + $pmGroup = $pmGrp; + break; // to get the name :) + } + } + + $pmUserList = []; + foreach ($PM_SOAP->userList() as $pmuser) { + $pmUserList[ strtolower($pmuser->name)] = [ 'name' => $pmuser->name, 'guid' => $pmuser->guid, 'status' => $pmuser->status ]; + } + + // get the complete user list from GLPI DB + $glpiUserList = []; + $res = $DB->request(['SELECT' => ['glpi_users.id', 'glpi_users.name', 'glpi_users.realname', 'glpi_users.firstname', 'glpi_users.is_active', 'glpi_users.is_deleted', 'glpi_plugin_processmaker_users.pm_users_id as pmUserId'], + 'FROM' => 'glpi_users', + 'LEFT JOIN' => ['glpi_plugin_processmaker_users' => ['FKEY' => ['glpi_plugin_processmaker_users' => 'id', 'glpi_users' => 'id']]], + 'WHERE' => ['name' => ['NOT LIKE', '*%']] + ]); + //foreach ($DB->request("SELECT glpi_users.id, glpi_users.name, glpi_users.realname, glpi_users.firstname, glpi_users.is_active, glpi_users.is_deleted, glpi_plugin_processmaker_users.pm_users_id as pmUserId + // FROM glpi_users + // LEFT JOIN glpi_plugin_processmaker_users on glpi_plugin_processmaker_users.id = glpi_users.id + // WHERE name not like '*%'") as $dbgroup) { + foreach ($res as $dbgroup) { + $glpiUserList[ strtolower($dbgroup['name'])] = $dbgroup; + } + + $arrayDiff = array_diff_key( $glpiUserList, $pmUserList ); + + foreach ($arrayDiff as $user) { + if ($user['is_active'] != 0 && $user['is_deleted'] != 1) { + $status = "ACTIVE"; + $task->addVolume(1); + $pass = md5(Toolbox::sodiumEncrypt($user['id'].$user['name'].time())); + $pmResult = $PM_SOAP->createUser($user['name'], $user['firstname'], $user['realname'], "", "PROCESSMAKER_OPERATOR", $pass, $status); + if ($pmResult->status_code == 0) { + $task->log( "Added user: '".$user['name']."'" ); + + // then assign user to group + if($pmGroup) { + $pmResult2 = $PM_SOAP->assignUserToGroup( $pmResult->userUID, $pmGroup->guid ); + if ($pmResult2->status_code == 0) { + $task->log( "Added user: '".$user['name']."' to '".$pmGroup->name."' group" ); + } else { + $task->log( "Error PM: '".$pmResult2->message."'" ); + } + } + // insert into DB the link between glpi users and pm user + $pmuser = new PluginProcessmakerUser; + if ($pmuser->getFromDB( $user['id'] )) { + $pmuser->update( [ 'id' => $user['id'], 'pm_users_id' => $pmResult->userUID ] ); + } else { + $pmuser->add( [ 'id' => $user['id'], 'pm_users_id' => $pmResult->userUID ] ); + } + $actionCode = 1; + + } else { + $task->log( "Error adding user: '".$user['name']."'" ); + $task->log( "Error PM: '".$pmResult->message."'" ); + $actionCode = -1; + $error = true; + } + } else { + unset( $glpiUserList[$user['name']] ); + } + } + + if (!$error) { + + // now should refresh the existing users + $arrayIntersect = array_intersect_key( $glpiUserList, $pmUserList ); + foreach ($arrayIntersect as $user) { + $pmuserlistGuid = $pmUserList[strtolower($user['name'])]['guid']; + if ($user['pmUserId'] == null || ($user['pmUserId'] != $pmuserlistGuid)) { //must be deleted, inserted or updated into DB + $existingID = PluginProcessmakerUser::getGLPIUserId($pmuserlistGuid); + $pmuser = new PluginProcessmakerUser; + if ($existingID && $existingID != $user['id']) { + // there is already an existing record, must delete it before updating or adding + $ret = $pmuser->delete( [ 'id' => $existingID, 'pm_users_id' => $pmuserlistGuid ] ); + } + // insert into DB the link between glpi users and pm user + if ($pmuser->getFromDB( $user['id'] )) { + $ret = $pmuser->update( [ 'id' => $user['id'], 'pm_users_id' => $pmuserlistGuid ] ); + } else { + $ret = $pmuser->add( [ 'id' => $user['id'], 'pm_users_id' => $pmuserlistGuid ] ); + } + + //$query = "REPLACE INTO glpi_plugin_processmaker_users (glpi_users_id, pm_users_id) VALUES (".$user['id'].", '". $pmUserList[strtolower($user['name'])]['guid']."');" ; + //$DB->query( $query ) or + if (!$ret) { + $task->log( "Cannot update user: '".$user['id']."' into glpi_plugin_processmaker_users!" ); + } + + } + if ($user['is_active'] == 0 || $user['is_deleted'] == 1) { + $status = "INACTIVE"; + } else { + $status = "ACTIVE"; + } + if ($status != $pmUserList[strtolower($user['name'])]['status']) { + $task->addVolume(1); + $pmResult = $PM_SOAP->updateUser( $pmUserList[strtolower($user['name'])]['guid'], $user['name'], $user['firstname'], $user['realname'], $status ); + if ($pmResult->status_code == 0) { + $task->log( "Updated user: '".$user['name']."', status: '".$pmUserList[strtolower($user['name'])]['status']."' -> '".$status."'" ); + $actionCode = 1; + } else { + $task->log( "Error updating user: '".$user['name']."'" ); + $task->log( "Error PM: '".$pmResult->message."'" ); + $actionCode = -1; + $error = true; + } + } + + } + } + + // now we should desactivate PM users who are not in glpi user list + //if( !$error ) { + // $status = "INACTIVE" ; + // $arrayDiff = array_diff_key( $pmUserList , $glpiUserList ) ; + // foreach( $arrayDiff as $user ){ + // $task->addVolume(1); + // if( $user['status'] == 'ACTIVE' && $user['name'] != 'admin' && $user['name'] != 'glpi'){ + // $pmResult = $myProcessMaker->updateUser( $user['guid'], $user['name'], null, null, $status ) ; + // if( $pmResult->status_code == 0) { + // $task->log( "Updated user: '".$user['name']."', status: '".$user['status']."' -> '".$status."'" ) ; + // $actionCode = 1 ; + // } else { + // $task->log( "Error updating user: '".$user['name']."'" ) ; + // $task->log( "Error PM: '".$pmResult->message."'" ) ; + // $actionCode = -1 ; + // $error = true ; + // } + // } + // } + //} + + // so now treat GLPI groups + $glpiGroupList = []; + $res = $DB->request(['SELECT' => ['id', 'name', 'is_task', 'is_usergroup'], + 'FROM' => 'glpi_groups', + 'WHERE' => ['AND' => ['is_task' => 1, 'is_usergroup' => 1]] + ]); + //foreach ($DB->request("SELECT id, name, is_task, is_usergroup FROM glpi_groups WHERE is_task=1 AND is_usergroup=1") as $dbgroup) { + foreach ($res as $dbgroup) { + $glpiGroupList[$dbgroup['name']] = $dbgroup; + } + + $pmGroupList = self::getPMGroups(); // array(); + + // here we can compare group lists like done for the users + $arrayDiff = array_diff_key( $glpiGroupList, $pmGroupList ); + + // then for each group we must check if it exists, and if not create a real PM group + foreach ($arrayDiff as $group) { + // it is not existing in PM + // then create + $pmResult = $PM_SOAP->createGroup( $group['name'] ); + if ($pmResult->status_code == 0) { + $task->addVolume(1); + $task->log( "Added group: '".$group['name']."'" ); + } + } + + // review and update all users in each group + $pmGroupList = self::getPMGroups(); // array(); + + // now should refresh the existing users into groups + $arrayDiff = array_intersect_key( $glpiGroupList, $pmGroupList ); + foreach ($arrayDiff as $group) { + // for each group will delete users and re-create them + // not really optimized, but this way we are sure that groups are synchronized + // must be redesigned + $PM_DB->delete('GROUP_USER', ['GROUP_USER.GRP_UID' => $pmGroupList[$group['name']]['CON_ID']]); + //$query = "DELETE FROM GROUP_USER WHERE GROUP_USER.GRP_UID='".$pmGroupList[$group['name']]['CON_ID']."';"; + //$PM_DB->query( $query ); + // and insert all users from real GLPI group + $res = $DB->request(['SELECT' => ['glpi_groups_users.users_id', 'glpi_plugin_processmaker_users.pm_users_id'], + 'FROM' => 'glpi_groups', + 'INNER JOIN' => ['glpi_groups_users' => ['FKEY' => ['glpi_groups_users' => 'groups_id', 'glpi_groups' => 'id']], + 'glpi_plugin_processmaker_users' => ['FKEY' => ['glpi_plugin_processmaker_users' => 'id', 'glpi_groups_users' => 'users_id']]], + 'WHERE' => ['glpi_groups.name' => $group['name']]]); + + //foreach ($DB->request("SELECT glpi_groups_users.users_id, glpi_plugin_processmaker_users.pm_users_id + // FROM glpi_groups + // JOIN glpi_groups_users ON glpi_groups_users.groups_id=glpi_groups.id + // JOIN glpi_plugin_processmaker_users ON glpi_plugin_processmaker_users.id=glpi_groups_users.users_id + // WHERE glpi_groups.name='".$group['name']."'") as $user ) { + foreach ($res as $user) { + //$query = "INSERT INTO GROUP_USER (`GRP_UID`, `USR_UID`) VALUES ( '".$pmGroupList[$group['name']]['CON_ID']."', '".$user['pm_users_id']."' )"; + //$PM_DB->query( $query ); + $PM_DB->insert('GROUP_USER', ['GRP_UID' => $pmGroupList[$group['name']]['CON_ID'], + 'USR_UID' => $user['pm_users_id'] + ] + ); + } + $task->addVolume(1); + $task->log( "Updated users into PM group: '".$group['name']."'" ); + } + + // now should renew the duedate of the users + //$PM_DB->query("UPDATE USERS SET USR_DUE_DATE='2035-12-31' WHERE USR_DUE_DATE<>'2035-12-31'; "); + //$PM_DB->query("UPDATE RBAC_USERS SET USR_DUE_DATE='2035-12-31' WHERE USR_DUE_DATE<>'2035-12-31'; "); + $PM_DB->update('USERS', + ['USR_DUE_DATE' => '2035-12-31'], + ['USR_DUE_DATE' => ['!=', '2035-12-31']] + ); + $PM_DB->update('RBAC_USERS', + ['USR_DUE_DATE' => '2035-12-31'], + ['USR_DUE_DATE' => ['!=', '2035-12-31']] + ); + if ($error) { + return -1; + } else { + return $actionCode; + } + } + + + public static function plugin_pre_item_add_processmaker($parm) { + global $PM_DB; + + if (isset($parm->input['processmaker_caseguid'])) { + // a case is already started for this ticket, then change ticket title and ticket type and ITILCategory + + $myProcessMaker = new PluginProcessmakerProcessmaker( ); + $myProcessMaker->login( ); + $caseInfo = $myProcessMaker->getCaseInfo( $parm->input['processmaker_caseguid'], $parm->input['processmaker_delindex']); + $parm->input['name'] = $PM_DB->escape($caseInfo->caseName ); + + $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 (isset($parm->input['time_to_resolve']) && 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', $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'])) { + $parm->input['type'] = $procDef->fields['type']; + } + + if (isset($parm->input['itilcategories_id'])) { + $parm->input['itilcategories_id'] = $procDef->fields['itilcategories_id']; + } + + } + } + + + /** + * Summary of plugin_item_add_processmaker + * @param mixed $parm + * @return void + */ + public static function plugin_item_add_processmaker($parm) { + global $DB, $GLOBALS, $PM_SOAP; + + if (isset($parm->input['processmaker_caseguid'])) { + // a case is already started for this ticket, then bind them together + $itemtype = $parm->getType(); + $items_id = $parm->fields['id']; + $case_guid = $parm->input['processmaker_caseguid']; + + $caseInfo = $PM_SOAP->getCaseInfo($case_guid);//$parm->input['processmaker_delindex']); + + $myCase = new PluginProcessmakerCase; + $myCase->add(['id' => $parm->input['processmaker_casenum'], + 'itemtype' => $itemtype, + 'items_id' => $items_id, + 'entities_id' => $parm->fields['entities_id'], + 'name' => $caseInfo->caseName, + 'case_guid' => $case_guid, + 'case_status' => $caseInfo->caseStatus, + 'plugin_processmaker_processes_id' => $parm->input['processmaker_processes_id'] + ]); + + // here we create a fake task that will be used to store the creator of the case + // this is due for traceability only + $PM_SOAP->add1stTask($myCase->getID(), $myCase->fields['itemtype'], $myCase->fields['items_id'], $caseInfo, [ 'notif' => false] ); // no notif + + // before routing, send items_id and itemtype + // as this information was not available at case creation + $myCase->sendVariables( [ "GLPI_TICKET_ID" => $items_id, + "GLPI_ITEM_ID" => $items_id, + "GLPI_ITEM_TYPE" => $itemtype, + ] ); + + $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"; + $str = $parm->input['content']; + if (preg_match($ptnProcessToStart, $str, $matches) > 0) { + // and it is requested to start a case of process + $processGuid = $matches[1]; + $hasCase = self::hasCase( 'Ticket', $parm->fields['id'] ); + if ($hasCase === false) { + // check writer + $writer = new User; + $writer->getFromDB( $parm->fields['users_id_recipient'] ); + //$PM_SOAP = new PluginProcessmakerProcessmaker(); + $PM_SOAP->login( $writer->fields['name'] ); + $locProcess = new PluginProcessmakerProcess; + if ($locProcess->getFromGUID( $processGuid )) { + $found = false; + // check rights of writer to start this $processGuid on the Ticket entity + foreach (Profile_User::getUserProfiles( $writer->getID() ) as $profID) { + if (in_array( $parm->fields['entities_id'], PluginProcessmakerProcess::getEntitiesForProfileByProcess( $locProcess->getID(), $profID, true) )) { + $found=true; + break; + } + } + if ($found) { + $PM_SOAP->startNewCase( $locProcess->getID(), 'Ticket', $parm->fields['id'], $writer->getID() ); + } + } + } + } + } + return; + } + + + public static function plugin_pre_item_add_processmaker_followup($parm) { + //global $DB ; + + } + + + /** + * Summary of addWatcher + * add $techId as watcher to $glpi_item when techId has no rights on it + * @param string $itemType is the type of the CommonITILObject + * @param integer $itemId is the id of the ITIL object + * @param integer $techId is the users_id to be added + * @return boolean true if added, + */ + public static function addWatcher($itemType, $itemId, $techId) { + if ($techId && $itemType != '' && $itemId > 0) { + $dbu = new DbUtils; + $glpi_item = $dbu->getItemForItemtype( $itemType ); + $glpi_item->getFromDB( $itemId ); + + // then we should check if this user has rights on the item, if not then we must add it to the watcher list! + $glpi_item = $dbu->getItemForItemtype( $itemType ); + $glpi_item->getFromDB( $itemId ); + if (!$glpi_item->isUser( CommonITILActor::REQUESTER, $techId ) + && !$glpi_item->isUser( CommonITILActor::OBSERVER, $techId ) + && !$glpi_item->isUser( CommonITILActor::ASSIGN, $techId ) ) { + + // then we must add this tech user to watcher list + $glpi_item_user = $dbu->getItemForItemtype( $glpi_item->getType() . "_User" ); + + // do not send notifications + $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); + $glpi_item_user->add( [ $glpi_item::getForeignKeyField() => $glpi_item->getId(), 'users_id' => $techId, 'type' => CommonITILActor::OBSERVER, '_disablenotif' => true ] ); + PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); + return true; + } + } + return false; + } + + + /** + * Summary of addTask + * adds a GLPI task to given item + * @param $cases_id integer the GLPI id of the case + * @param $itemtype string item type to which a task will be added + * @param $items_id integer item id to which a task will be added + * @param $caseInfo mixed getCaseInfoResponse object (see: getCaseInfo() function) + * @param $delIndex integer index of the delegation + * @param $techId integer GLPI user id to which a task must be assigned, if == 0 will use $pmTaskId + * @param $pmTaskId string PM task guid, used when $techID == 0 to dynamically find the group (Self-Service) + * @param $options array of options, default values are + * 'txtTaskContent' => '', + * 'start_date' => '', + * 'end_date' => '', + * 'notif' => true + * @return + */ + public function addTask($cases_id, $itemtype, $items_id, $caseInfo, $delIndex, $techId, $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; + } + } + + $glpi_task = $dbu->getItemForItemtype( "{$itemtype}Task" ); + $glpi_task->getEmpty(); + + $input = []; // will contain all data for the Task + + $input[getForeignKeyFieldForItemType($itemtype)] = $items_id; + // search for task category + // + $pmtaskcat = new PluginProcessmakerTaskCategory; + $pmtaskcat->getFromGUID( $pmTaskId ); + $input['taskcategories_id'] = $pmtaskcat->fields['taskcategories_id']; + // load process information + $pmProcess = new PluginProcessmakerProcess; + $pmProcess->getFromDB( $pmtaskcat->fields['plugin_processmaker_processes_id'] ); + + if ($options['start_date'] == '') { + $options['start_date'] = new DateTime( $_SESSION["glpi_currenttime"] ); + } else { + $options['start_date'] = new DateTime( $options['start_date'] ); + } + + $input['begin'] = $options['start_date']->format("Y-m-d H:i:s"); + + if ($options['end_date'] == '' || $options['end_date'] <= $input['begin']) { + $options['end_date'] = clone $options['start_date']; + $options['end_date']->add( new DateInterval('PT15M') ); + } else { + $options['end_date'] = new DateTime( $options['end_date'] ); + } + $input['end'] = $options['end_date']->format("Y-m-d H:i:s"); + $input['plan']['begin'] = $input['begin']; + $temp = $options['start_date']->diff( $options['end_date'] ); + $input['plan']['_duration'] = $temp->d * DAY_TIMESTAMP + $temp->h * HOUR_TIMESTAMP + $temp->i * MINUTE_TIMESTAMP + $temp->s; + if ($input['plan']['_duration'] == 0) { + $input['plan']['_duration'] = 60; // at least + } + + $input['users_id'] = $this->taskWriter; + + // manage groups + if ($techId == 0) { + // then we must look-up DB to get the group that will be assigned to the task + $groups_id_tech = $this->getGLPIGroupIdForSelfServiceTask($caseInfo->caseId, $pmTaskId); + } else { + // adds the user tech to ticket watcher if neccessary + self::addWatcher( $itemtype, $items_id, $techId ); + } + + // manage task description + $input['content'] = ""; // by default empty :) + + if ($pmProcess->fields["insert_task_comment"]) { + $input['content'] .= "##processmaker.taskcomment##\n"; + } + + if ($options['txtTaskContent'] != '') { + $input['content'] .= $options['txtTaskContent']."\n"; + } else if (!$pmProcess->fields["hide_case_num_title"]) { + $input['content'] .= __('Case title: ', 'processmaker').$caseInfo->caseName."\n"; + } + + $input['content'] .= "##processmakercase.url##"; + + $input['is_private'] = 0; + $input['actiontime'] = 0; + $input['state'] = Planning::TODO; // == TO_DO + $input['users_id_tech'] = 0; // by default as it can't be empty + if ($techId) { + $input['users_id_tech'] = $techId; + } else if (is_array($groups_id_tech)) { + $input['groups_id_tech'] = $groups_id_tech['id']; + } + + if ($options['reminder'] != '' && $techId) { + $input['_planningrecall'] = ['before_time' => $options['reminder'], + 'itemtype' => get_class($glpi_task), + 'items_id' => '', + 'users_id' => $techId, + 'field' => 'begin']; + } + + $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); // do not send notification yet as the PluginProcessmakerTask is not yet added to DB + $glpi_task->add( Toolbox::addslashes_deep( $input ) ); + PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); + + // to prevent error message for overlapping planning + if (isset($_SESSION["MESSAGE_AFTER_REDIRECT"][WARNING])) { + unset($_SESSION["MESSAGE_AFTER_REDIRECT"][WARNING]); + } + + if ($glpi_task->getId() > 0) { + // stores link to task in DB + //$tmp = new PluginProcessmakerTask($glpi_task->getType()); + //$tmp->add([ 'itemtype' => $glpi_task->getType(), + // 'items_id' => $glpi_task->getId(), + // 'plugin_processmaker_cases_id' => $cases_id, + // 'del_index' => $delIndex + // ], [], false); + $DB->insert('glpi_plugin_processmaker_tasks', + [ + 'items_id' => $glpi_task->getId(), + 'itemtype' => $glpi_task->getType(), + 'plugin_processmaker_cases_id' => $cases_id, + 'plugin_processmaker_taskcategories_id' => $pmtaskcat->fields['id'], + 'del_index' => $delIndex, + 'del_thread' => $delThread + ]); + //$query = "INSERT INTO glpi_plugin_processmaker_tasks (items_id, itemtype, plugin_processmaker_cases_id, plugin_processmaker_taskcategories_id, del_index, del_thread) + // VALUES ({$glpi_task->getId()}, '{$glpi_task->getType()}', $cases_id, {$pmtaskcat->fields['id']}, $delIndex, $delThread);"; + //$DB->query( $query ); + //} + + // send notification if needed for new task as now we have the PluginProcessmakerTask in the DB + $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState($options['notif']); + + // send notification now! + $pm_task = new PluginProcessmakerTask($glpi_task->getType()); + $pm_task->getFromDB($glpi_task->getId()); + $glpi_item = new $itemtype; + $glpi_item->getFromDB($items_id); + $pm_task->sendNotification('task_add', $glpi_task, $glpi_item); + + PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); + } + + } + + + /** + * Summary of getGLPIGroupId + * returns GLPI group id from pm group name + * returns false when not found + * @param string $pmGroupName + * @return bool|integer + */ + static function getGLPIGroupId(string $pmGroupName) { + global $DB; + if ($pmGroupName != '') { + $query = "SELECT id AS glpi_group_id FROM glpi_groups WHERE name LIKE '$pmGroupName';"; + $res = $DB->query($query); + if ($DB->numrows($res) > 0) { + $row = $DB->fetch_array($res); + return $row['glpi_group_id']; + } + } + return false; + } + + /** + * Summary of add1stTask + * adds a GLPI task to ticket + * @param $cases_id integer the GLPI id of the case + * @param $itemType string itemtype of object (Ticket, Problem, ....) + * @param $itemId integer item id to which a task will be added + * @param $caseInfo mixed getCaseInfoResponse object (see: getCaseInfo() function) + * @param $options array of options, defaults are: + * 'txtTaskContent' => '', is content of the task + * 'userId' => false, is user id to be assigned to task + * 'notif' => true, if true notifications will be sent + * @return + */ + public function add1stTask ($cases_id, $itemType, $itemId, $caseInfo, $options = []) { + + $default_options = [ + 'txtTaskContent' => '', + 'userId' => false, + 'notif' => true + ]; + foreach ($default_options as $key => $opt) { + if (!isset($options[$key])) { + $options[$key] = $opt; + } + } + $start_date = new DateTime( $_SESSION["glpi_currenttime"] ); + $official_date_time = $_SESSION["glpi_currenttime"]; + $_SESSION["glpi_currenttime"] = $start_date->sub(new DateInterval("PT1S"))->format("Y-m-d H:i:s"); + $userId = $options['userId'] ? $options['userId'] : Session::getLoginUserID(); + unset($options['userId']); // unset it as it's not in the options of addTask + + $this->addTask( $cases_id, + $itemType, + $itemId, + $caseInfo, + $caseInfo->currentUsers[0]->delIndex, + $userId, + $caseInfo->currentUsers[0]->taskId, + $caseInfo->currentUsers[0]->delThread, + $options + ); + $_SESSION["glpi_currenttime"] = $official_date_time; + } + + + /** + * Summary of setItemStatus + * @param mixed $itemtype + * @param mixed $itemId + * @param mixed $newstatus + */ + public function setItemStatus($itemtype, $itemId, $newstatus) { + $dbu = new DbUtils; + $item = $dbu->getItemForItemtype( $itemtype ); + if ($item->getFromDB( $itemId )) { //&& $itemtype::isAllowedStatus( $item->fields['status'], $newstatus )) { + //$item->fields['status'] = $newstatus ; + $item->update( ['id' => $itemId, 'status' => $newstatus] ); + } + } + + + /** + * Summary of setItemTitle + * @param mixed $itemtype + * @param mixed $itemId + * @param mixed $newtitle + */ + public function setItemTitle($itemtype, $itemId, $newtitle) { + global $DB; + + $dbu = new DbUtils; + $item = $dbu->getItemForItemtype( $itemtype ); + if ($item->getFromDB( $itemId )) { + $item->update( ['id' => $itemId, 'name' => $DB->escape($newtitle)] ); + } + } + + + /** + * 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 + * @param mixed $itemId + * @param mixed $casevariablevalues + */ + public function setItemSolution($itemType, $itemId, $casevariablevalues) { + global $DB; + + $dbu = new DbUtils; + $item = $dbu->getItemForItemtype( $itemType ); + if ($item->getFromDB( $itemId )) { + // default values + $solutiontemplates_id = 0; + $solutiontypes_id = 0; + $solution = ''; + $to_update = false; + + // check solution template + if (array_key_exists( 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID', $casevariablevalues ) + && $casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID' ] != '' + && $casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID' ] != 0) { + // get template + $template = new SolutionTemplate; + $template->getFromDB($casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TEMPLATE_ID' ]); + $entities = $template->isRecursive() ? $dbu->getSonsOf(Entity::getTable(), $template->getEntityID()) : [$template->getEntityID()]; + // and check entities + if (in_array($item->getEntityID(), $entities)) { + $solutiontemplates_id = $template->getID(); + $solutiontypes_id = $template->fields['solutiontypes_id']; + $solution = $template->fields['content']; + $to_update = true; + } + } + + // check solution type + if (array_key_exists( 'GLPI_ITEM_SET_SOLUTION_TYPE_ID', $casevariablevalues ) + && $casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TYPE_ID' ] != '' + && $casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TYPE_ID' ] != 0) { + // get solution type + $type = new SolutionType; + $type->getFromDB($casevariablevalues[ 'GLPI_ITEM_SET_SOLUTION_TYPE_ID' ]); + $entities = $type->isRecursive() ? $dbu->getSonsOf(Entity::getTable(), $type->getEntityID()) : [$type->getEntityID()]; + // and check entities + if (in_array($item->getEntityID(), $entities)) { + $solutiontypes_id = $type->getID(); + $to_update = true; + } + } + + // Check solution description + if (array_key_exists( 'GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION', $casevariablevalues ) + && $casevariablevalues[ 'GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION' ] != '') { + if ($solution != '') { + $solution .= "\n"; + } + $solution .= $DB->escape($casevariablevalues[ 'GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION' ]); + $to_update = true; + } + + if ($to_update) { + $item->update( ['id' => $itemId, 'solutiontemplates_id' => $solutiontemplates_id, 'solutiontypes_id' => $solutiontypes_id, 'solution' => $solution] ); + } + } + } + + + /** + * Summary of computeTaskDuration + * @param mixed $task + * @param mixed $entity + * @return mixed + */ + function computeTaskDuration($begin, $end, $entity) { + + $calendars_id = Entity::getUsedConfig('calendars_id', $entity); + $calendar = new Calendar(); + + // Using calendar + if ($calendars_id>0 && $calendar->getFromDB($calendars_id)) { + return max(0, $calendar->getActiveTimeBetween($begin, $end)); + } + // Not calendar defined + return max(0, strtotime($end) - strtotime($begin)); + } + + + + /** + * Summary of solveTask + * @param string $cases_id GLPI case id + * @param int $delIndex + * @param array $options + * 'txtToAppend' => '' : text to append to solved task + * 'notif' => true : if true will send notifications + * 'users_id_tech' => is the users_id of the tech that solved the task + * 'begin' => is the new begin date of the task + * 'end' => is the new end date of the task + * 'toInformation' => is the new status of the task (usually set to INFORMATION) + * @return false|object the solved task, when found + */ + public function solveTask($cases_id, $delIndex, $options = []) { + global $DB; + + //$query = "SELECT * FROM glpi_plugin_processmaker_tasks WHERE plugin_processmaker_cases_id=$cases_id and del_index=$delIndex; "; + //$res = $DB->query($query); + $res = $DB->request('glpi_plugin_processmaker_tasks', ['AND' => ['plugin_processmaker_cases_id' => $cases_id, 'del_index' => $delIndex]]); + //if ($DB->numrows($res) > 0) { + if ($row = $res->next()) { + $dbu = new DbUtils; + //$row = $DB->fetch_array( $res ); + + $glpi_task = new $row['itemtype']; + $glpi_task->getFromDB( $row['items_id'] ); + $hostItem = $dbu->getItemForItemtype( $glpi_task->getItilObjectItemType() ); + $itemFKField = getForeignKeyFieldForItemType( $glpi_task->getItilObjectItemType() ); + $hostItem->getFromDB( $glpi_task->fields[ $itemFKField ] ); + + // change current glpi_currenttime to be sure that date_mode for solved task will not be identical than date_mode of the newly started task + $saved_date_time = $_SESSION["glpi_currenttime"]; + $_SESSION["glpi_currenttime"] = (new DateTime($saved_date_time))->sub(new DateInterval("PT1S"))->format("Y-m-d H:i:s"); + + $default_options = [ + 'txtToAppend' => '', + 'notif' => true, + 'users_id_tech' => null, + 'begin' => $glpi_task->fields['begin'] > $_SESSION["glpi_currenttime"] ? + (new DateTime($_SESSION["glpi_currenttime"]))->sub(new DateInterval("PT1S"))->format("Y-m-d H:i:s") : + $glpi_task->fields['begin'], + 'end' => $_SESSION["glpi_currenttime"], + 'toInformation' => false + ]; + foreach ($default_options as $key => $opt) { + if (!isset($options[$key]) || ($options[$key] === '')) { + $options[$key] = $opt; + } + } + + $duration = $this->computeTaskDuration($options['begin'], $options['end'], $hostItem->fields['entities_id']); + if ($options['txtToAppend'] != "") { + $options['txtToAppend'] = "\n
".$options['txtToAppend']; + } + $params = ['id' => $row['items_id'], + 'state' => $options['toInformation'] ? Planning::INFO : Planning::DONE, + 'begin' => $options['begin'], + 'end' => $options['end'], + $itemFKField => $hostItem->getID(), + 'actiontime' => $duration, + 'users_id_tech' => (isset($options['users_id_tech']) ? $options['users_id_tech'] : Session::getLoginUserID()), + //'groups_id_tech' => 0, + 'content' => $DB->escape($glpi_task->fields[ 'content' ].$options['txtToAppend']) + ]; + + $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState(false); // do not send notification yet + $glpi_task->update($params); + PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); + + // Close the task + //$DB->query("UPDATE glpi_plugin_processmaker_tasks SET del_thread_status = '".PluginProcessmakerTask::CLOSED."' WHERE id = {$row['id']}"); + $DB->update('glpi_plugin_processmaker_tasks', ['del_thread_status' => PluginProcessmakerTask::CLOSED], ['id' => $row['id']]); + + // send notification if needed for new task as now the PluginProcessmakerTask has been updated in the DB + $donotif = PluginProcessmakerNotificationTargetProcessmaker::saveNotificationState($options['notif']); + + // send notification now! + $pm_task = new PluginProcessmakerTask($glpi_task->getType()); + $pm_task->getFromDB($glpi_task->getId()); + $pm_task->sendNotification('task_done', $glpi_task, $hostItem); + + PluginProcessmakerNotificationTargetProcessmaker::restoreNotificationState($donotif); + + // restore current glpi time + $_SESSION["glpi_currenttime"] = $saved_date_time; + + return $glpi_task; + } + + return false; + } + + /** + * Summary of claimTask + * will unassign group, and assign tech + * @param mixed $cases_id GLPI case id + * @param mixed $delIndex + * @param mixed $users_id_tech optional is the id of the tech + * who's claimed the task, default current logged-in user + */ + public function claimTask($cases_id, $delIndex, $users_id_tech = null) { + global $DB; + $res = $DB->request('glpi_plugin_processmaker_tasks', ['AND' => ['plugin_processmaker_cases_id' => $cases_id, 'del_index' => $delIndex]]); + //$query = "SELECT * FROM glpi_plugin_processmaker_tasks WHERE plugin_processmaker_cases_id='$cases_id' and del_index=$delIndex; "; + //$res = $DB->query($query); + //if ($DB->numrows($res) > 0) { + if ($row = $res->next()) { + $dbu = new DbUtils; + //$row = $DB->fetch_array( $res ); + $glpi_task = new $row['itemtype']; + $glpi_task->getFromDB( $row['items_id'] ); + + $itemType = str_replace( 'Task', '', $row['itemtype'] ); + $glpi_item = $dbu->getItemForItemtype( $itemType ); + $glpi_item->getFromDB( $glpi_task->fields[ getForeignKeyFieldForItemType( $itemType ) ] ); + + $glpi_task->update( [ 'id' => $row['items_id'], + $glpi_item->getForeignKeyField() => $glpi_item->getId(), + 'users_id_tech' => (isset($users_id_tech)?$users_id_tech: Session::getLoginUserID()), + 'groups_id_tech' => 0, + 'update' => true]); + } + } + + + // /** + // * Summary of getCaseIdFromItem + // * get case id for an id item_id of type item_type (if a case if attached to it) + // * @param string $item_type, the type for the item ("Ticket", "Problem", ...) + // * @param integer $item_id, the id for the item + // * @return string the case guid, false if no case is attached to item, or if an error occurred + // */ + //public static function getCaseIdFromItem ($item_type, $item_id) { + // global $DB; + // $res = $DB->request('glpi_plugin_processmaker_cases', ['AND' => ['itemtype' => $item_type, 'items_id' => $item_id]]); + // //$query = "SELECT * FROM glpi_plugin_processmaker_cases WHERE `itemtype` = '$item_type' AND `items_id` = $item_id ;"; + // // $res = $DB->query($query); + // //if ($DB->numrows($res) > 0) { + // // // case is existing for this item + // // // then get info from db + // // $row = $DB->fetch_array($res); + // if ($row = $res->next()) { + // return $row['id']; + // } + + // return false; + //} + + /** + * Summary of hasCase + * returns true if cases are attached to item, false otherwise + * @param string $item_type, the type for the item ("Ticket", "Problem", ...) + * @param integer $item_id, the id for the item + * @return boolean true if at least one case is attached, otherwise false + */ + public static function hasCase($item_type, $item_id) { + global $DB; + $res = $DB->request('glpi_plugin_processmaker_cases', ['AND' => ['itemtype' => $item_type, 'items_id' => $item_id]]); + if ($res->numrows() > 0) { + return true; + } + + return false; + } + + + ///** + // * Summary of getCaseGuidFromItem + // * get case id for an id item_id of type item_type (if a case if attached to it) + // * @param string $item_type, the type for the item ("Ticket", "Problem", ...) + // * @param integer $item_id, the id for the item + // * @return string the case guid, false if no case is attached to item, or if an error occurred + // */ + //public static function getCaseGuidFromItem ($item_type, $item_id) { + // global $DB; + // $res = $DB->request('glpi_plugin_processmaker_cases', ['AND' => ['itemtype' => $item_type, 'items_id' => $item_id]]); + // //$query = "SELECT * FROM glpi_plugin_processmaker_cases WHERE `itemtype` = '$item_type' AND `items_id` = $item_id ;"; + // //$res = $DB->query($query); + // //if ($DB->numrows($res) > 0) { + // // // case is existing for this item + // // // then get info from db + // // $row = $DB->fetch_array($res); + // if ($row = $res->next()) { + // return $row['case_guid']; + // } + + // return false; + //} + + // /** + // * Summary of getCaseFromItem + // * get case infos for an id item_id of type item_type (if a case if attached to it) + // * @param string $item_type, the type for the item ("Ticket", "Problem", ...) + // * @param integer $item_id, the id for the item + // * @return getCaseInfoResponse object, false if no case is attached to item, or if an error occurred + // */ + //public function getCaseFromItem($item_type, $item_id) { + // global $DB; + + // $caseId = self::getCaseGuidFromItem( $item_type, $item_id ); + // if ($caseId !== false) { + // $caseInfo = $this->getCaseInfo( $caseId ); + // if ($caseInfo !== false && $caseInfo->status_code == 0) { + // return $caseInfo; + // } else { + // return false; // means any error + // } + // } else { + // return false; // means no case + // } + //} + + /** + * Summary of multiexplode + * @param $delimiters + * @param $string + * @return + */ + static function multiexplode($delimiters, $string) { + + $ready = str_replace($delimiters, $delimiters[0], $string); + $launch = explode($delimiters[0], $ready); + return $launch; + } + + /** + * Summary of pre_show_item_processmaker + * @param $params + */ + public static function pre_show_item_processmaker($params) { + + if (!is_array($params['item']) && is_subclass_of($params['item'], 'CommonITILTask')) { + // must check if Task is bound to a PM task + $pmTask = new PluginProcessmakerTask($params['item']->getType()); + $is_pmtask = $pmTask->getFromDB($params['item']->getId()); + if (!$is_pmtask && $params['item']->fields['state'] == Planning::INFO) { + // look if it is a meta task for this process + // means a re-assign or an un-claim task info + $pm_process = new PluginProcessmakerProcess; + $restrict=[ + 'WHERE' => [ + 'taskcategories_id' => $params['item']->fields['taskcategories_id'] + ], + ]; + //if ($pm_process->getFromDBByQuery( " WHERE `taskcategories_id` = ".$params['item']->fields['taskcategories_id'])) { + if ($pm_process->getFromDBByRequest($restrict)) { + // then look into content to get case id + $re = '//'; + if (preg_match($re, $params['item']->fields['content'], $matches)) { + // here we get the case id and the task id + $is_pmtask = $pmTask->getFromDB($matches['taskid']); + } + } + } + if ($is_pmtask) { + $params['item']->fields['can_edit'] = false; // to prevent task edition + + // replace ##ticket.url##_PluginProcessmakerCase$processmakercases by a setActiveTab to the Case panel + $taskCat = new TaskCategory; + $taskCat->getFromDB( $params['item']->fields['taskcategories_id'] ); + $taskComment = isset($taskCat->fields['comment']) ? $taskCat->fields['comment'] : ''; + if (Session::haveTranslations('TaskCategory', 'comment')) { + $params['item']->fields['content'] = str_replace( '##processmaker.taskcomment##', + DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskComment ), $params['item']->fields['content'] ); + } else { + $params['item']->fields['content'] = str_replace( '##processmaker.taskcomment##', $taskComment, $params['item']->fields['content'] ); + } + $taskJSId = strtolower("viewitem".$params['item']->getType().$params['item']->getId()); //.$params['options']['rand']); + + $tmpCase = new PluginProcessmakerCase; + $tmpCase->getFromDB($pmTask->fields['plugin_processmaker_cases_id']); + $urlLink = $tmpCase->getLinkURL().'&forcetab=PluginProcessmakerTask$'.$pmTask->fields['items_id']; + + echo Html::scriptBlock( " + function $taskJSId(ev) { + //debugger; + if ($(ev.target).parent('.read_more').length == 0) { + document.location='$urlLink'; + } + }; + $('#$taskJSId').find('.item_content').on('click', $taskJSId).css('cursor', 'pointer'); + $('#$taskJSId').find('.read_more').css('cursor', 'auto'); + $('tr[id=\"$taskJSId\"]').children().on('click', $taskJSId).css('cursor', 'pointer'); + "); + + $params['item']->fields['content'] = str_replace( ["\n##processmakercase.url##", '\n##processmakercase.url##', '##processmakercase.url##'], "", $params['item']->fields['content'] ); + + // in order to set NavigationList + Session::initNavigateListItems('PluginProcessmakerCase', + //TRANS : %1$s is the itemtype name, + // %2$s is the name of the item (used for headings of a list) + sprintf('%1$s = %2$s', + $params['options']['parent']->getTypeName(1), $params['options']['parent']->fields["name"])); + } + } + } + + + /** + * Summary of pre_show_tab_arbehaviours + * @param array $params info about tab to be shown + * @return void + */ + static function pre_show_tab_processmaker($params) { + //global $pmHideSolution; + $plugin = new Plugin(); + $itemtype = $params['item']->getType(); + if (in_array($itemtype, ['Ticket', 'Problem', 'Change']) + && $params['options']['id'] + && $params['options']['itemtype'] == $itemtype + && $params['options']['tabnum'] == 1 + && !PluginProcessmakerCase::canSolve($params) + && Session::getCurrentInterface() == "central") { + // then we are in an ITIL Object + // tabnum 1 : Processing Ticket + // a case may be solved or not (ex: PIR tasks for Change Management) + + // don't display message if arbehaviours is install and activated + $itemtype = strtolower($itemtype); + if ((!$plugin->isInstalled('arbehaviours') || !$plugin->isActivated('arbehaviours')) + && isset($_SESSION['glpiactiveprofile'][$itemtype.'_status'])) { + + echo Html::scriptBlock(" + //$('head').append(''); +debugger; + $('li.solution').css({pointerEvents: 'none', opacity: 0.3}); + + "); + + self::displayMessage(__('At least one \'Process case\' is running!
Adding a solution is currently disabled!', 'processmaker'), false, INFO); + + ////backup current $_SESSION['glpiactiveprofile'][$itemtype.'_status'] + //$_SESSION['glpiactiveprofile'][$itemtype.'_status_pm_save'] = $_SESSION['glpiactiveprofile'][$itemtype.'_status']; + + //// for all $params['options']['itemtype'].status, we must disable solved (life cycles) + //foreach ($_SESSION['glpiactiveprofile'][$itemtype.'_status'] as $key => $value) { + // //$_SESSION['glpiactiveprofile'][$itemtype.'_status'][$key][CommonITILObject::SOLVED] = 0; + //} + } + } + } + + + //public static function post_show_tab_processmaker($params) { + + // //$itemtype = strtolower($params['item']->getType()); + // //if (isset($_SESSION['glpiactiveprofile'][$itemtype.'_status_pm_save'])) { + // // // we must restore rigths + // // // replace $_SESSION['glpiactiveprofile'][$itemtype.'_status'] with saved value + + // // $_SESSION['glpiactiveprofile'][$itemtype.'_status'] = $_SESSION['glpiactiveprofile'][$itemtype.'_status_pm_save']; + // // unset($_SESSION['glpiactiveprofile'][$itemtype.'_status_save']); + // //} + + //} + + + /** + * Summary of getItemUsers + * returns an array of glpi ids and pm ids for each user type assigned to given ticket + * @param string $itemtype + * @param integer $itemId is the ID of the titem + * @param integer $userType is 1 for ticket requesters, 2 for ticket technicians, and if needed, 3 for watchers + * @return array of users in the returned array + */ + public static function getItemUsers($itemtype, $itemId, $userType) { + global $DB; + $dbu = new DbUtils; + $users = [ ]; + + //$itemtable = $dbu->getTableForItemType( $itemtype ) ; + $item = new $itemtype(); + $item_users = $item->userlinkclass; + $item_userstable = $dbu->getTableForItemType( $item_users ); + $itemlink = getForeignKeyFieldForItemType( $itemtype ); + $res = $DB->request([ + 'SELECT' => ['glpi_plugin_processmaker_users.pm_users_id as pm_users_id', 'glpi_plugin_processmaker_users.id as id'], + 'FROM' => $item_userstable, + 'LEFT JOIN' => ['glpi_plugin_processmaker_users' => ['FKEY' => ['glpi_plugin_processmaker_users' => 'id', $item_userstable => 'users_id']]], + 'WHERE' => ['AND' => ["$item_userstable.$itemlink" => $itemId, "$item_userstable.type" => $userType]], + 'ORDER' => ['ORDER' => $item_userstable.'.id'] + ]); + //$query = "select glpi_plugin_processmaker_users.pm_users_id as pm_users_id, glpi_plugin_processmaker_users.id as id from $item_userstable + // left join glpi_plugin_processmaker_users on glpi_plugin_processmaker_users.id = $item_userstable.users_id + // where $item_userstable.$itemlink = $itemId and $item_userstable.type = $userType + // order by $item_userstable.id"; + //foreach ($DB->request( $query ) as $dbuser) { + foreach ($res as $dbuser) { + $users[] = [ 'glpi_id' => $dbuser['id'], 'pm_id' => $dbuser['pm_users_id'] ]; + } + + return $users; + } + + /** + * Summary of saveForm + * This function posts dynaform variables to PM, using the CURL module. + * @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) { + + $logtrace = false; //isset($_SESSION['glpi_use_mode']) && ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE); + $request = stripcslashes_deep( $request ); + + $ch = curl_init(); + + //to be able to trace network traffic with a local proxy + // curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1 ); + // curl_setopt($ch, CURLOPT_PROXY, "localhost:8888"); + + //curl_setopt($ch, CURLINFO_HEADER_OUT, 1); + //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + if ($logtrace) { + curl_setopt($ch, CURLOPT_VERBOSE, 1); + $curl_log = fopen('L:/inetpub/wwwroot/glpi/files/_log/curl.log', 'a'); + Toolbox::logInFile( "pmtrace", "curl log file open: ".$curl_log ); + fprintf($curl_log, "Test\n"); + fflush($curl_log); + curl_setopt($ch, CURLOPT_STDERR, $curl_log); + } + + curl_setopt($ch, CURLOPT_HTTPHEADER, ["Expect:"]); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->config->fields['ssl_verify']); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $this->config->fields['ssl_verify']); + + //curl_setopt($ch, CURLOPT_HEADERFUNCTION, "HandleHeaderLine"); + // to store cookies in memory + // ( replace HandleHeaderLine function ) + curl_setopt($ch, CURLOPT_COOKIEFILE, ""); + + // ### first call to open case and get cookies GET ### + curl_setopt($ch, CURLOPT_URL, $this->serverURL."/cases/cases_Open?sid=".$this->getPMSessionID()."&APP_UID=".$request['APP_UID']."&DEL_INDEX=".$request['DEL_INDEX']."&action=TO_DO" ); + if ($logtrace) { + Toolbox::logInFile( "pmtrace", "Before curl_exec: ".$this->serverURL."/cases/cases_Open?sid=".$this->getPMSessionID()."&APP_UID=".$request['APP_UID']."&DEL_INDEX=".$request['DEL_INDEX']."&action=TO_DO" ); + } + $response = curl_exec($ch); + if ($logtrace) { + Toolbox::logInFile( "pmtrace", "URL:\n".$this->serverURL."/cases/cases_Open?sid=".$this->getPMSessionID()."\nResponse:\n".$response."\n\n\n" ); + } + + // change option to indicate that the next call will be POST + curl_setopt($ch, CURLOPT_POST, 1); + // get and format post values + $data = http_formdata_flat_hierarchy( $request ); + // check if any files are in the $_FILES global array + // and add them to the curl POST + $fileForm = isset($_FILES['form']['name']) ? $_FILES['form']['name'] : null; + if (isset($fileForm) && !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]); + $data["form[$key][$row][$control]"] = $cfile; + } + } + } else { + $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); + curl_setopt($ch, CURLOPT_HTTPHEADER, ["Expect:"]); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // inject POST values + // add agent and referer params + //$agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'; + //$referer = $this->getSiteURL(); + //curl_setopt($ch, CURLOPT_USERAGENT, $agent); + //curl_setopt($ch, CURLOPT_REFERER, $referer); + + // ### 2nd call to save Data POST ### + curl_setopt($ch, CURLOPT_URL, $this->serverURL."/cases/cases_SaveData?UID=".$request['UID']."&APP_UID=".$request['APP_UID'] ); + $response = curl_exec ($ch); + if ($response === false) { + //throw new Exception(curl_error($ch), curl_errno($ch)); + Toolbox::logInFile( "pmtrace", curl_error($ch).":".curl_errno($ch)."\n" ); + } + curl_close ($ch); + if ($logtrace) { + Toolbox::logInFile( "pmtrace", "URL:\n".$this->serverURL."/cases/cases_SaveData?UID=".$request['UID']."&APP_UID=".$request['APP_UID']."\nData:\n".print_r($data, true )."\nResponse:\n".$response."\n\n\n" ); + fclose($curl_log); + } + + return ($response ? true : false); + } + + /** + * Function to get current site url with protocol ( http or https ) + * @return string + */ + function getSiteURL() { + $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; + $domainName = $_SERVER['HTTP_HOST']; + return $protocol.$domainName; + } + + /** + * Summary of initCaseAndShowTab + * Is used to workaround a SESSION issue in PM server + * PM server stores case context in SESSION variables, + * which leads to issues when viewing two different cases + * in two different tabs of the same browser. + * This workaround will artificially load cases_Open page to force + * initialization of those SESSION variables to prevent mix of values + * when viewing tabs like map, change log, history, and dynaforms + * + * it will also manage the glpi_domain parameter + * + * @param mixed $currentCase array that contains APP_UID, DEL_INDEX + * @param mixed $iFrameUrl string which is the url of the tab panel + * @param mixed $rand integer + */ + public function initCaseAndShowTab($currentCase, $iFrameUrl, $rand) { + $iFrameUrl = urlencode($iFrameUrl); + + echo "
"; + + // will use ajax to be sure that cases_Open page is fully loaded before load of the $iFrameUrl + // this mechanism is mandatory to have correct management of cookies, as cookies transport the session id, + // and such the SESSION variables that contain the case context + echo ""; + + } + + /** + * Summary of plugin_item_get_data_processmaker + * @param mixed $item + */ + public static function plugin_item_get_data_processmaker($item) { + global $_SESSION, $CFG_GLPI; + if (isset( $item->data ) && isset( $item->data['tasks'] )) { + $pmtask_itemtype = $item->obj->getType().'Task'; + $pmtask = new PluginProcessmakerTask($pmtask_itemtype); + foreach ($item->data['tasks'] as &$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 + $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 + } + + $task['##task.description##'] = str_replace( '##processmaker.taskcomment##', $task['##task.categorycomment##'], $task['##task.description##'] ); + $task['##task.description##'] = Html::nl2br_deep($task['##task.description##']); + + //$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']); + + $caseurl = "$caseurl"; + $task['##task.description##'] = str_replace('##processmakercase.url##', $caseurl, $task['##task.description##']); + } + } + } + + } + + + /** + * Summary of plugin_item_get_pdfdata_processmaker + * @param mixed $item + */ + public static function plugin_item_get_pdfdata_processmaker($item) { + if (isset( $item->datas )) { + $config = PluginProcessmakerConfig::getInstance(); + $taskCat = new TaskCategory; + $dbu = new DbUtils; + // save current translations + if (isset( $_SESSION['glpi_dropdowntranslations'] )) { + $trans = $_SESSION['glpi_dropdowntranslations']; + } + // load available translations for this user + $_SESSION['glpi_dropdowntranslations'] = DropdownTranslation::getAvailableTranslations($_SESSION['glpilanguage']); + + $taskCat->getFromDB( $item->datas['taskcategories_id'] ); + $ancestors = $dbu->getAncestorsOf( 'glpi_taskcategories', $item->datas['taskcategories_id']); + if (in_array( $config->fields['taskcategories_id'], $ancestors)) { + $loc_completename = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'completename', $_SESSION['glpilanguage'], $taskCat->fields['completename'] ); + $loc_comment = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskCat->fields['comment'] ); + $item->datas['content'] = $loc_completename."\n\n".str_replace( "##processmaker.taskcomment##", $loc_comment, $item->datas['content']); + $item->datas['content'] = str_replace( "##processmakercase.url##", '', $item->datas['content']); + } + // restore default translations + if (isset( $trans )) { + $_SESSION['glpi_dropdowntranslations'] = $trans; + } else { + unset( $_SESSION['glpi_dropdowntranslations'] ); + } + } + + } + + + /** + * Summary of getProcessesWithCategoryAndProfile + * @param mixed $category + * @param mixed $type + * @param mixed $profile + * @param mixed $entity + */ + public static function getProcessesWithCategoryAndProfile($category, $type, $profile, $entity) { + global $DB; + $dbu = new DbUtils; + $processList = [ ]; + //$entityAncestors = implode( ", ", $dbu->getAncestorsOf( $dbu->getTableForItemType( 'Entity' ), $entity ) ); + $entityAncestors = $dbu->getAncestorsOf( $dbu->getTableForItemType( 'Entity' ), $entity ); + //if (strlen( $entityAncestors ) > 0) { + if ($category > 0) { + $query = [ + 'FIELDS' => ['glpi_plugin_processmaker_processes.id', 'glpi_plugin_processmaker_processes.name'], + 'DISTINCT' => true, + 'FROM' => 'glpi_plugin_processmaker_processes', + 'INNER JOIN' => [ + 'glpi_plugin_processmaker_processes_profiles' => [ + 'FKEY' => [ + 'glpi_plugin_processmaker_processes_profiles' => 'plugin_processmaker_processes_id', + 'glpi_plugin_processmaker_processes' => 'id', + ['AND' => [ + 'glpi_plugin_processmaker_processes.itilcategories_id' => ['!=', 0] + ] + ] + ] + ] + ], + 'WHERE' => [ + 'AND' => [ + 'itilcategories_id' => $category, + 'type' => $type, + 'profiles_id' => $profile, + 'entities_id' => $entity + ] + ] + ]; + if (count( $entityAncestors ) > 0) { + //$entityAncestors = " OR (entities_id IN ($entityAncestors) AND is_recursive = 1) "; + $entityAncestors[] = $entity; + $query['WHERE']['AND']['entities_id'] = $entityAncestors; + $query['WHERE']['AND']['is_recursive'] = 1; + } + $res = $DB->request($query); + foreach ($res as $row) { + $processList[] = $row; + } + $processList = array_map("unserialize", array_unique(array_map("serialize", $processList))); + } + //$query ="SELECT DISTINCT glpi_plugin_processmaker_processes.id, glpi_plugin_processmaker_processes.name FROM glpi_plugin_processmaker_processes + // INNER JOIN glpi_plugin_processmaker_processes_profiles ON glpi_plugin_processmaker_processes_profiles.plugin_processmaker_processes_id=glpi_plugin_processmaker_processes.id + // WHERE is_active = 1 AND itilcategories_id = $category AND `type` = $type AND profiles_id = $profile AND (entities_id = $entity $entityAncestors)"; + + //foreach ($DB->request( $query ) as $row) { + + return $processList; + + } + + /** + * Summary of startNewCase + * @param mixed $processes_id integer: GLPI process id + * @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) { + global $DB, $CFG_GLPI; + + $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; + } + + //$impersonateCase = false; + //if (!$users_id) { + // // then we are going to take the item creator to set it as case creator and + // $impersonateCase = true; + + //} + + // get item info to retreive title, description and duedate + $item = new $itemtype; + $item->getFromDB( $items_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($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_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' => $item->fields['entities_id'], + 'plugin_processmaker_processes_id' => $processes_id, + 'plugin_processmaker_cases_id' => 0 + ], + [], true ); + + $this->add1stTask($locCase->getID(), $itemtype, $items_id, $caseInfo, ['userId' => $users_id] ); + } + + return $resultCase; + } + + + /** + * Summary of derivateCase + * in $request must be present + * 'UID', 'APP_UID' and DEL_INDEX' + * + * @param mixed $myCase + * @param mixed $request + * @param mixed $users_id + */ + public function derivateCase($myCase, $request, $users_id = null) { + //$cookies, + global $PM_DB, $CFG_GLPI, $DB; + + $logtrace = false; //isset($_SESSION['glpi_use_mode']) && ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE); + + + $itemtype = $myCase->getField('itemtype'); + $items_id = $myCase->getField('items_id'); + $item = new $itemtype; + $item->getFromDB($items_id); + + if ($logtrace) { + Toolbox::logInFile("pmtrace", Toolbox::backtrace(false) . "derivateCase: myCase = " . print_r($myCase, true) . "\nrequest = " . print_r($request, true) . "\nusers_id = " . print_r($users_id, true) ); + } + // save the dynaform variables into the current case + 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 ($logtrace) { + Toolbox::logInFile("pmtrace", "routeCase: pmRouteCaseResponse = " . print_r($pmRouteCaseResponse, true)); + } + + if ($pmRouteCaseResponse->status_code != 0) { + Session::addMessageAfterRedirect(sprintf(__('Unable to derivate case! Retry in a moment, or ask your administrator.
Error code: %u
Error message: %s
', 'processmaker'), + $pmRouteCaseResponse->status_code, + $pmRouteCaseResponse->message), + true, + ERROR); + return; + } + + $casevariables = ["GLPI_ITEM_TASK_CONTENT", + "GLPI_ITEM_APPEND_TO_TASK", + //"GLPI_NEXT_GROUP_TO_BE_ASSIGNED", + //"GLPI_ITEM_TASK_GROUP", + "GLPI_ITEM_TITLE", + "GLPI_TICKET_FOLLOWUP_CONTENT", + "GLPI_ITEM_FOLLOWUP_CONTENT", + "GLPI_TICKET_FOLLOWUP_IS_PRIVATE", + "GLPI_ITEM_FOLLOWUP_IS_PRIVATE", + "GLPI_TICKET_FOLLOWUP_REQUESTTYPES_ID", + "GLPI_ITEM_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_INITIAL_DUE_DATE", + "GLPI_ITEM_DUE_DATE", + "GLPI_SEND_EMAIL", + "GLPI_ITEM_INFORMATION_TASK" + ]; + + // now tries to get some variables to setup content for new task and to append text to solved task + $casevariablevalues = $myCase->getVariables($casevariables); + + $information_task = ''; + if (array_key_exists( 'GLPI_ITEM_INFORMATION_TASK', $casevariablevalues ) && $casevariablevalues[ 'GLPI_ITEM_INFORMATION_TASK' ] != '') { + $information_task = $casevariablevalues[ 'GLPI_ITEM_INFORMATION_TASK' ]; + } + + $sendemail = ''; + if (array_key_exists( 'GLPI_SEND_EMAIL', $casevariablevalues ) && $casevariablevalues[ 'GLPI_SEND_EMAIL' ] != '') { + $sendemail = json_decode($casevariablevalues[ 'GLPI_SEND_EMAIL' ], true); + } + + $itemSetStatus = ''; + 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 )) { + $txtItemTitle = $casevariablevalues[ 'GLPI_ITEM_TITLE' ]; + } + + $txtToAppendToTask = ''; + if (array_key_exists( 'GLPI_ITEM_APPEND_TO_TASK', $casevariablevalues )) { + $txtToAppendToTask = $casevariablevalues[ 'GLPI_ITEM_APPEND_TO_TASK' ]; + } + + $txtTaskContent = ''; + if (array_key_exists( 'GLPI_ITEM_TASK_CONTENT', $casevariablevalues )) { + $txtTaskContent = $casevariablevalues[ 'GLPI_ITEM_TASK_CONTENT' ]; + } + + //$groupId = 0; + //if (array_key_exists( 'GLPI_NEXT_GROUP_TO_BE_ASSIGNED', $casevariablevalues )) { + // $groupId = $casevariablevalues[ 'GLPI_NEXT_GROUP_TO_BE_ASSIGNED' ]; + //} + //if (array_key_exists( 'GLPI_ITEM_TASK_GROUP', $casevariablevalues )) { + // $groupId = $casevariablevalues[ 'GLPI_ITEM_TASK_GROUP' ]; + //} + + $taskStartDate = ''; + $taskEndDate = ''; + if (array_key_exists( 'GLPI_ITEM_TASK_ENDDATE', $casevariablevalues )) { + $taskEndDate = $casevariablevalues[ 'GLPI_ITEM_TASK_ENDDATE' ]; + } + if (array_key_exists( 'GLPI_ITEM_TASK_STARTDATE', $casevariablevalues )) { + $taskStartDate = $casevariablevalues[ 'GLPI_ITEM_TASK_STARTDATE' ]; + if ($taskEndDate == '') { + // at least + $taskEndDate = $taskStartDate; + } + } + + $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 )) { + $solvedTaskEndDate = $casevariablevalues[ 'GLPI_ITEM_SOLVED_TASK_ENDDATE' ]; + } + if (array_key_exists( 'GLPI_ITEM_SOLVED_TASK_STARTDATE', $casevariablevalues )) { + $solvedTaskStartDate = $casevariablevalues[ 'GLPI_ITEM_SOLVED_TASK_STARTDATE' ]; + if ($solvedTaskEndDate == '') { + // at least + $solvedTaskEndDate = $solvedTaskStartDate; + } + } + + $solvedTaskSetToInformation = ''; + if (array_key_exists( 'GLPI_ITEM_SOLVED_TASK_SETINFO', $casevariablevalues )) { + $solvedTaskSetToInformation = $casevariablevalues[ 'GLPI_ITEM_SOLVED_TASK_SETINFO' ]; + } + + $createFollowup = false; // by default + if ((array_key_exists( 'GLPI_TICKET_FOLLOWUP_CONTENT', $casevariablevalues ) && $casevariablevalues[ 'GLPI_TICKET_FOLLOWUP_CONTENT' ] != '') + || (array_key_exists( 'GLPI_ITEM_FOLLOWUP_CONTENT', $casevariablevalues ) && $casevariablevalues[ 'GLPI_ITEM_FOLLOWUP_CONTENT' ] != '')) { + $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) { + if (!empty($casevariablevalues[$val])) { + $resetcasevariables[$val] = ''; + } + } + $resultSave = $myCase->sendVariables($resetcasevariables); + + // now manage tasks associated with item + // switch own task to 'done' and create a new one + $glpi_task = $this->solveTask($myCase->getID(), + $request['DEL_INDEX'], + ['txtToAppend' => $txtToAppendToTask, + 'users_id_tech' => $users_id, + 'begin' => $solvedTaskStartDate, + 'end' => $solvedTaskEndDate, + 'toInformation' => $solvedTaskSetToInformation + ] + ); + + // create a followup if requested + if ($createFollowup) { // && $itemtype == 'Ticket') { + $this->addItemFollowup( $itemtype, $items_id, $casevariablevalues ); + } + + if ($txtItemTitle != '') { + // we are going to change the title of current GLPI Item + $this->setItemTitle($itemtype, $items_id, $txtItemTitle); + } + + 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 ) + || array_key_exists( 'GLPI_ITEM_SET_SOLUTION_TYPE_ID', $casevariablevalues ) + || array_key_exists( 'GLPI_ITEM_APPEND_TO_SOLUTION_DESCRIPTION', $casevariablevalues )) { + // case requests to add a solution to ticket + $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 + + // create an information task if requested + if ($information_task != '' && $glpi_task) { + // create an information task and add comment + // $information_task is the content of the task + $pm_process = $myCase->getProcess(); + $taskCat = new TaskCategory; + $taskCat->getFromDB($glpi_task->fields['taskcategories_id']); + // we may replace ##casename## by the name of the case, and ##taskname## by the task name + $search = ['##casename##', + '##taskname##' + ]; + $replace = [$caseInfo->caseName." (".$myCase->getID().")", + DropdownTranslation::getTranslatedValue($glpi_task->fields['taskcategories_id'], 'TaskCategory', 'name', $_SESSION['glpilanguage'], $taskCat->fields['name']) + ]; + $info = str_replace($search, $replace, $information_task); + + $info .= ""; + + // unescape some chars and replace CRLF, CR or LF by
+ $info = str_replace(["\\'", '\\"', '\r\n', '\r', '\n'], ["'", '"', '
', '
', '
'], $info); + + $foreignkey = getForeignKeyFieldForItemType($glpi_task->getItilObjectItemType()); + $glpi_task->add([$foreignkey => $glpi_task->fields[$foreignkey], + 'is_private' => 1, + 'taskcategories_id' => $pm_process->fields['taskcategories_id'], + 'content' => $DB->escape($info), + 'users_id' => $this->taskWriter, + 'state' => Planning::INFO, + 'users_id_tech' => Session::getLoginUserID(), + ]); + } + + // now create the new tasks if any + if (property_exists( $pmRouteCaseResponse, 'routing' )) { + + // we may have several task to create + foreach ($pmRouteCaseResponse->routing as $route) { + + // must check if task has started a sub-process + $locTaskCat = new PluginProcessmakerTaskCategory; + if ($locTaskCat->getFromGUID($route->taskId) && $locTaskCat->fields['is_subprocess']) { + // look for APP_UID + $res = $PM_DB->request([ + 'SELECT' => [ + 'APPUID' + ], + 'FROM' => 'SUB_APPLICATION', + 'WHERE' => [ + 'AND' => [ + 'APP_PARENT' => $myCase->fields['case_guid'], + 'DEL_INDEX_PARENT' => $route->delIndex, + 'SA_STATUS' => 'ACTIVE' + ] + ] + ]); + //$res = $PM_DB->query("SELECT APP_UID FROM SUB_APPLICATION WHERE APP_PARENT='{$myCase->fields['case_guid']}' AND DEL_INDEX_PARENT={$route->delIndex} AND SA_STATUS='ACTIVE'"); // AND DEL_THREAD_PARENT={$route->delThread} seems like it is not set to correct threadIndex + //if ($row = $res->next() && $PM_DB->numrows($res) == 1) { + if ($res->numrows() == 1 && $row = $res->next()) { + // then new task is a sub-process, + //$row = $PM_DB->fetch_assoc($res); + + // now need to get the PRO_UID + $sub_caseInfo = self::getCaseInfo($row['APP_UID']); + + $locProc = new PluginProcessmakerProcess; + $locProc->getFromGUID($sub_caseInfo->processId); + $subCase = new PluginProcessmakerCase; + $subCase->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' )) { + // there should be only one task + $sub_route = $sub_caseInfo->currentUsers[0]; + $this->addTask($subCase->getID(), $itemtype, + $items_id, + $sub_caseInfo, + $sub_route->delIndex, + PluginProcessmakerUser::getGLPIUserId($sub_route->userId), + $sub_route->taskId, + $sub_route->delThread, + [ 'txtTaskContent' => $txtTaskContent, + 'start_date' => $taskStartDate, + 'end_date' => $taskEndDate, + 'reminder' => $taskReminder] + ); + + // if end date was specified, then must change due date of the PM task + if ($taskEndDate != '') { + $PM_DB->update( + 'APP_DELEGATION', + [ + 'DEL_TASK_DUE_DATE' => $taskEndDate + ], + ['AND' => [ + 'APP_UID' => $sub_caseInfo->caseId, + 'DEL_INDEX' => $sub_route->delIndex + ] + ] + ); + //$PM_DB->query( "UPDATE APP_DELEGATION SET DEL_TASK_DUE_DATE='$taskEndDate' WHERE APP_UID='".$sub_caseInfo->caseId."' AND DEL_INDEX=".$sub_route->delIndex); + } + + } + + // must also send to new sub-process some GLPI variables + // like any newly started cases + // get the value of GLPI_ITEM_CAN_BE_SOLVED to transmit it to sub-case + $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; + } + + $glpi_variables = ['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) + 'GLPI_TICKET_TYPE' => $itemtype == 'Ticket' ? $item->fields['type'] : '' + ]; + $subCase->sendVariables($glpi_variables); + + // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED + $subCase->update( [ 'id' => $subCase->getID(), 'case_status' => $sub_caseInfo->caseStatus, 'name' => $sub_caseInfo->caseName ] ); + + } + } else { + $this->addTask($myCase->getID(), + $itemtype, + $items_id, + $caseInfo, + $route->delIndex, + PluginProcessmakerUser::getGLPIUserId($route->userId), + $route->taskId, + $route->delThread, + ['txtTaskContent' => $txtTaskContent, + 'start_date' => $taskStartDate, + 'end_date' => $taskEndDate, + 'reminder' => $taskReminder] + ); + // if end date was specified, then must change due date of the PM task + if ($taskEndDate != '') { + $PM_DB->update( + 'APP_DELEGATION', + [ + 'DEL_TASK_DUE_DATE' => $taskEndDate + ], + ['AND' => [ + 'APP_UID' => $caseInfo->caseId, + 'DEL_INDEX' => $route->delIndex + ] + ]); + //$PM_DB->query( "UPDATE APP_DELEGATION SET DEL_TASK_DUE_DATE='$taskEndDate' WHERE APP_UID='".$caseInfo->caseId."' AND DEL_INDEX=".$route->delIndex); + } + } + + } + + } else { + // must check if current case is a sub-process, and if it has ended, then must reflect parent case into the current item. + if ($myCase->fields['plugin_processmaker_cases_id'] != 0) { + // current case is a sub-case of $myCase->fields['plugin_processmaker_cases_id'] + $parentCase = new PluginProcessmakerCase; + $parentCase->getFromDB($myCase->fields['plugin_processmaker_cases_id']); + $parentCaseInfo = $parentCase->getCaseInfo(); + // then create associated task + if (property_exists( $parentCaseInfo, 'currentUsers' )) { + // we may have several new task + foreach ($parentCaseInfo->currentUsers as $open_task) { + // must check if $open_task is not is_subprocess and is not already existing in the item + $locTaskCat = new PluginProcessmakerTaskCategory; + $locTask = new PluginProcessmakerTask($itemtype.'Task'); + + $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->getFromDBByRequest($locTaskRestrict)) { + $this->addTask($parentCase->getID(), $itemtype, + $items_id, + $parentCaseInfo, + $open_task->delIndex, + PluginProcessmakerUser::getGLPIUserId($open_task->userId), + $open_task->taskId, + $open_task->delThread, + [ 'txtTaskContent' => $txtTaskContent, + 'start_date' => $taskStartDate, + 'end_date' => $taskEndDate, + 'reminder' => $taskReminder] + ); + + // if end date was specified, then must change due date of the PM task + if ($taskEndDate != '') { + $PM_DB->update('APP_DELEGATION', ['DEL_TASK_DUE_DATE' => $taskEndDate], ['AND' => ['APP_UID' => $parentCaseInfo->caseId, 'DEL_INDEX' => $open_task->delIndex]]); + //$PM_DB->query( "UPDATE APP_DELEGATION SET DEL_TASK_DUE_DATE='$taskEndDate' WHERE APP_UID='".$sub_caseInfo->caseId."' AND DEL_INDEX=".$open_task->delIndex); + } + } + } + } + // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED + $parentCase->update( [ 'id' => $parentCase->getID(), 'case_status' => $parentCaseInfo->caseStatus, 'name' => $parentCaseInfo->caseName ] ); + } + } + + // evolution of case status: DRAFT, TO_DO, COMPLETED, CANCELLED + $myCase->update( [ 'id' => $myCase->getID(), 'case_status' => $caseInfo->caseStatus, 'name' => $caseInfo->caseName ] ); + + // send email if requested + if (is_array($sendemail)) { + NotificationEvent::raiseEvent('send_email', + $myCase, + ['glpi_send_email' => $sendemail, + 'case' => $myCase + ]); + } + + } + + + /** + * Summary of getPMGroups + * @return array + */ + public static function getPMGroups() { + global $PM_DB; + $pmGroupList = []; + $res = $PM_DB->request( + 'CONTENT', [ + 'AND' => [ + 'CONTENT.CON_CATEGORY' => 'GRP_TITLE', + 'CONTENT.CON_LANG' => 'en' + ] + ]); + //foreach ($PM_DB->request("SELECT * FROM CONTENT WHERE CONTENT.CON_CATEGORY='GRP_TITLE' AND CONTENT.CON_LANG='en'") as $dbgroup) { + foreach ($res as $dbgroup) { + $pmGroupList[$dbgroup['CON_VALUE']] = $dbgroup; + } + return $pmGroupList; + } + + + /** + * Summary of displayMessage + * Show a html message bottom-right of screen + * @param string $html_message message to be shown + * @param string $title if '' then title bar is not shown (default '') + * @param string $msgtype the type of the message (ERROR | WARNING | INFO) + * @return void + **/ + static private function displayMessage($html_message, $title = '', $msgtype = 'info_msg') { + + //set title and css class + switch ($msgtype) { + case ERROR: + $title = __s('Error'); + $class = 'err_msg'; + break; + case WARNING: + $title = __s('Warning'); + $class = 'warn_msg'; + break; + case INFO: + $title = _sn('Information', 'Information', 1); + $class = 'info_msg'; + break; + } + + echo "
"; + echo $html_message; + echo "
"; + + $scriptblock = " + $(function() { + var _of = window; + var _at = 'right-20 bottom-20'; + //calculate relative dialog position + $('.message_after_redirect').each(function() { + var _this = $(this); + if (_this.attr('aria-describedby') != 'message_after_redirect_$msgtype') { + _of = _this; + _at = 'right top-' + (10 + _this.outerHeight()); + } + }); + + $('#message_after_redirect_$msgtype').dialog({ + dialogClass: 'message_after_redirect $class', + minHeight: 40, + minWidth: 200, + position: { + my: 'right bottom', + at: _at, + of: _of, + collision: 'none' + }, + autoOpen: false, + show: { + effect: 'slide', + direction: 'down', + 'duration': 800 + } + }) + .dialog('open');"; + + //do not autoclose errors + if ($msgtype != ERROR) { + $scriptblock .= " + + // close dialog on outside click + $(document.body).on('click', function(e){ + if ($('#message_after_redirect_$msgtype').dialog('isOpen') + && !$(e.target).is('.ui-dialog, a') + && !$(e.target).closest('.ui-dialog').length) { + $('#message_after_redirect_$msgtype').dialog('close'); + // redo focus on initial element + e.target.focus(); + } + });"; + } + + $scriptblock .= " + + }); + "; + + echo Html::scriptBlock($scriptblock); + } + + /** + * Summary of underMaintenance + * Shows a nice(?) under maintenance message + */ + static function showUnderMaintenance() { + global $CFG_GLPI; + echo "
"; + echo Html::image($CFG_GLPI['root_doc'].'/plugins/processmaker/pics/under_maintenance.png'); + echo "

"; + 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); + } + } + + + /** + * Summary of getGLPIGroupIDForSelfServiceTask + * Gets GLPI group ID that is assigned to a task for a case when task is Self-Service + * @param string $caseId is the UID of the case + * @param string $pmTaskId is the UID of the task must be currently in SELF-SERVICE + * @return bool|array false if not found, otherwise is an array containing the 'name', GLPI 'id' and the PM 'uid' of the group + */ + public function getGLPIGroupIdForSelfServiceTask ($caseId, $pmTaskId) { + global $PM_DB; + + $groupname = NULL; + + // we must differentiate if rule assignement is self-service or self-service value based + //$query = "SELECT TAS_GROUP_VARIABLE + // FROM TASK + // WHERE TAS_UID='$pmTaskId' + // AND TAS_ASSIGN_TYPE='SELF_SERVICE';"; + $query = ['SELECT' => 'TAS_GROUP_VARIABLE', + 'FROM' => 'TASK', + 'WHERE' => ['TAS_UID' => '$pmTaskId', + 'TAS_ASSIGN_TYPE' => 'SELF_SERVICE']]; + //$req = $PM_DB->query($query); + //$row = $PM_DB->fetchAssoc($req); + foreach ($PM_DB->request($query) as $row) { + // there is only one row + + if ($row['TAS_GROUP_VARIABLE'] == '') { + // Assignement is Self-Service + // the group title can be found in the GROUPWF table when the assignement rule is Self-Service + // TU_RELATION=2 is groups and TU_TYPE=1 means normal (= not adhoc) + $queryname = "SELECT GROUPWF.GRP_TITLE AS 'GRP_TITLE', GROUPWF.GRP_UID AS 'GRP_UID' FROM TASK_USER + JOIN GROUPWF ON GROUPWF.GRP_UID = TASK_USER.USR_UID + WHERE TASK_USER.TAS_UID = '$pmTaskId' + AND TASK_USER.TU_RELATION = 2 + AND TASK_USER.TU_TYPE = 1 + LIMIT 1;"; + } else { + // Assignement is Self-Service Value Based + // in this case we must retreive the group from the case variable which is in if the TASK table + $casevariable = substr($row['TAS_GROUP_VARIABLE'], 2); + $vars = $this->getVariables($caseId, [$casevariable]); + if (array_key_exists($casevariable, $vars) && $vars[$casevariable] != '') { + // here is the UID of the group that needs to be assigned to the task + // then we need the name of the group + // the group title can be found in the GROUPWF table + $queryname = "SELECT GRP_TITLE, GRP_UID + FROM GROUPWF + WHERE GRP_UID = '{$vars[$casevariable]}';"; + } + } + } + + // as there is a LIMIT of 1 + // or + // as there is only one group per guid + // then we should have at maximun 1 record + foreach ($PM_DB->request($queryname) as $onlyrec) { + $groupname = $onlyrec; + } + + if (isset($groupname)) { + return ['name' => $groupname['GRP_TITLE'], + 'id' => self::getGLPIGroupId($groupname['GRP_TITLE']), + 'uid' => $groupname['GRP_UID'] + ]; + } + + return false; + } + } \ No newline at end of file diff --git a/inc/task.class.php b/inc/task.class.php index c501117..e7e38f6 100644 --- a/inc/task.class.php +++ b/inc/task.class.php @@ -1,529 +1,530 @@ -itemtype = $itemtype; - } - - - const OPEN = 'OPEN'; - const CLOSED = 'CLOSED'; - - /** - * Name of the type - * - * @param $nb : number of item in the type (default 0) - **/ - static function getTypeName($nb = 0) { - return _n('Process case task', 'Process case tasks', $nb, 'processmaker'); - } - - function getItilObjectItemType() { - return str_replace('Task', '', $this->itemtype); - } - /** - * Summary of getFromDB - * @param mixed $items_id - * @param mixed $itemtype - * @return bool - */ - function getFromDB($items_id) { - global $DB; - - //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 - $task->fields['items_id'] = $this->fields['id']; - $task->fields['itemtype'] = $this->fields['itemtype']; - unset( $this->fields['id'] ); - unset( $this->fields['items_id'] ); - unset( $this->fields['itemtype'] ); - foreach ($this->fields as $field => $val) { - $task->fields[ $field ] = $val; - } - $this->fields = $task->fields; - return true; - } - } - - return false; - } - - - /** - * Summary of getPMTaskID - * @return mixed - */ - function getPMTaskID() { - return $this->fields['items_id']; - } - - /** - * Summary of getToDoTasks - * returns all 'to do' tasks associated with this case - * @param mixed $case_id - */ - public static function getToDoTasks($case_id, $itemtype) { - global $DB; - $ret = []; - $dbu = new DbUtils; - $selfTable = $dbu->getTableForItemType( __CLASS__); - //$itemTypeTaskTable = getTableForItemType( $itemtype ); - - $res = $DB->request([ - 'SELECT' => $selfTable.'.items_id AS taskID', - 'FROM' => $selfTable, - 'WHERE' => [ - 'AND' => [ - $selfTable.'del_thread_status' => self::OPEN, - $selfTable.'plugin_processmaker_cases_id' =>$case_id - ] - ] - ]); - //$query = "SELECT `$selfTable`.`items_id` as taskID from $selfTable - // WHERE `$selfTable`.`del_thread_status` = '".self::OPEN."' AND `$selfTable`.`plugin_processmaker_cases_id` = '$case_id';"; - - //$query = "SELECT $itemTypeTaskTable.id as taskID from $itemTypeTaskTable - // INNER JOIN $selfTable on $selfTable.items_id=$itemTypeTaskTable.id - // WHERE $itemTypeTaskTable.state=1 and $selfTable.plugin_processmaker_cases_id='$case_id';"; - //foreach ($DB->request($query) as $row) { - foreach ($res as $row) { - $ret[$row['taskID']]=$row['taskID']; - } - return $ret; - } - - static function canView() { - return true; - } - - static function populatePlanning($params) { - //global $CFG_GLPI; - - $events = []; - - if (isset($params['start'])) { - $params['begin'] = '2000-01-01 00:00:00'; - if ($params['type'] == 'group') { - $params['who_group'] = $params['who']; - $params['whogroup'] = $params['who']; - $params['who'] = 0; - } - - $objects = ['TicketTask', 'ChangeTask', 'ProblemTask']; - //foreach ($objects as $itemtype) { - foreach ($_SESSION['glpi_plannings']['filters'] as $tasktype => $iteminfo) { - if (!$iteminfo['display'] || !in_array($tasktype, $objects)) { - continue; - } - $ret = CommonITILTask::genericPopulatePlanning($tasktype, $params); - - foreach ($ret as $key => $event) { - // if todo or done but need to show them (=planning) - if ($event['state'] == Planning::TODO || $event['state'] == Planning::INFO || ($params['display_done_events'] == 1 && $event['state'] == Planning::DONE)) { - // check if task is one within a case - $pmTask = new PluginProcessmakerTask($tasktype); - if ($pmTask->getFromDB($event[strtolower($tasktype).'s_id'])) { // $pmTask->getFromDBByQuery( " WHERE itemtype = 'TicketTask' AND items_id = ". $event['tickettasks_id'] ) ) { - $event['editable'] = false; - //$event['url'] .= '&forcetab=PluginProcessmakerCase$processmakercases'; - $tmpCase = new PluginProcessmakerCase; - $tmpCase->getFromDB($pmTask->fields['plugin_processmaker_cases_id']); - $event['url'] = $tmpCase->getLinkURL().'&forcetab=PluginProcessmakerTask$'.$pmTask->fields['items_id']; - - $taskCat = new TaskCategory; - $taskCat->getFromDB( $pmTask->fields['taskcategories_id'] ); - $taskComment = isset($taskCat->fields['comment']) ? $taskCat->fields['comment'] : ''; - if (Session::haveTranslations('TaskCategory', 'comment')) { - $taskComment = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskComment ); - } - - $event['content'] = str_replace( '##processmaker.taskcomment##', $taskComment, $event['content'] ); - $event['content'] = str_replace( ['\n##processmakercase.url##', '##processmakercase.url##'], "", $event['content'] ); //"."Click to manage task"." - //if( $event['state'] == 1 && $event['end'] < $params['start'] ) { // if todo and late - // $event['name'] = $event['end'].' '.$event['name'] ; //$event['begin'].' to '.$event['end'].' '.$event['name'] ; - // $event['end'] = $params['start'].' 24:00:00'; //.$CFG_GLPI['planning_end']; - //} - $events[$key] = $event; - } - } - } - } - } - return $events; - } - - - function getTabNameForItem(CommonGLPI $case, $withtemplate = 0) { - global $DB, $PM_DB; - - $tab = []; - - $caseInfo = $case->getCaseInfo(); - - if (property_exists($caseInfo, 'currentUsers')) { - $dbu = new DbUtils; - $GLPICurrentPMUserId = PluginProcessmakerUser::getPMUserId(Session::getLoginUserID()); - - // get all tasks that are OPEN for this case - $tasks = []; - $res = $DB->request( - 'glpi_plugin_processmaker_tasks', [ - 'AND' => [ - 'plugin_processmaker_cases_id' => $case->fields['id'], - 'del_thread_status' => 'OPEN' - ] - ] - ); - //$query = "SELECT * FROM `glpi_plugin_processmaker_tasks` WHERE `plugin_processmaker_cases_id`={$case->fields['id']} AND `del_thread_status`='OPEN'"; - //foreach ($DB->request($query) as $task) { - foreach ($res as $task) { - $tasks[$task['del_index']] = $task; - } - - //// get all tasks that are OPEN for any sub-case of this case - //$sub_cases = []; - //$query = "SELECT `glpi_plugin_processmaker_tasks`.* FROM `glpi_plugin_processmaker_tasks` - // JOIN `glpi_plugin_processmaker_cases` on `glpi_plugin_processmaker_cases`.`id`=`glpi_plugin_processmaker_tasks`.`plugin_processmaker_cases_id` - // WHERE `glpi_plugin_processmaker_cases`.`plugin_processmaker_cases_id`={$case->fields['id']} AND `del_thread_status`='OPEN'"; - //foreach($DB->request($query) as $task) { - // $sub_cases[$task['plugin_processmaker_cases_id']][$task['del_index']] = $task; - //} - - $caseInfo->currentUsers = $case->sortTasks($caseInfo->currentUsers, $GLPICurrentPMUserId); - - $main_tasks = []; //will contains the tasks that are main-processes - foreach ($caseInfo->currentUsers as $caseUser) { - $title = $caseUser->taskName; - if (isset($tasks[$caseUser->delIndex])) { - $hide_claim_button = false; - if ($caseUser->userId == '') { // task to be claimed - $itemtask = $dbu->getItemForItemtype($tasks[$caseUser->delIndex]['itemtype']); - $itemtask->getFromDB($tasks[$caseUser->delIndex]['items_id']); - // check if this group can be found in the current user's groups - if (!isset($_SESSION['glpigroups']) || !in_array( $itemtask->fields['groups_id_tech'], $_SESSION['glpigroups'] )) { - $hide_claim_button = true; - } - } - $tab[$tasks[$caseUser->delIndex]['id']] = ($caseUser->userId != '' && $caseUser->userId != $GLPICurrentPMUserId) || $hide_claim_button ? "$title" : $title; - } else { - $main_tasks[$caseUser->delIndex] = $caseUser; - } - } - - foreach ($main_tasks as $task) { - $res = $PM_DB->request([ - 'SELECT' => 'APP_UID', - 'FROM' => 'SUB_APPLICATION', - 'WHERE' => [ - 'AND' => [ - 'APP_PARENT' => $case->fields['case_guid'], - 'DEL_INDEX_PARENT' => $task->delIndex, - 'SA_STATUS' => 'ACTIVE' - ] - ] - ]); - //$res = $PM_DB->query("SELECT APP_UID FROM SUB_APPLICATION WHERE APP_PARENT='{$case->fields['case_guid']}' AND DEL_INDEX_PARENT={$task->delIndex} AND SA_STATUS='ACTIVE'"); - //if ($res && $PM_DB->numrows($res) == 1) { - if ($res->numrows() == 1 && $row = $res->next()) { - //$row = $PM_DB->fetch_assoc($res); - $loc_case = new PluginProcessmakerCase; - $loc_case->getFromGUID($row['APP_UID']); - $tab[$loc_case->getID()."-".$task->delIndex] = "> ".$task->taskName.""; - } - } - //$sub_case = new PluginProcessmakerCase; - //foreach ($sub_cases as $sub_cases_id => $sub_tasks) { - // $sub_case->getFromDB($sub_cases_id); - // $sub_case_info = $sub_case->getCaseInfo(); - // $sub_case_info->currentUsers = $sub_case->sortTasks($sub_case_info->currentUsers, $GLPICurrentPMUserId); - // foreach ($sub_case_info->currentUsers as $caseUser) { - // $title = $caseUser->taskName; - // if (isset($sub_tasks[$caseUser->delIndex])) { - // $hide_claim_button = false; - // if ($caseUser->userId == '') { // task to be claimed - // $itemtask = getItemForItemtype($sub_tasks[$caseUser->delIndex]['itemtype']); - // $itemtask->getFromDB($sub_tasks[$caseUser->delIndex]['items_id']); - // // check if this group can be found in the current user's groups - // if (!isset($_SESSION['glpigroups']) || !in_array( $itemtask->fields['groups_id_tech'], $_SESSION['glpigroups'] )) { - // $hide_claim_button = true; - // } - // } - // $tab["$sub_cases_id-".$sub_tasks[$caseUser->delIndex]['id']] = ($caseUser->userId != '' && $caseUser->userId != $GLPICurrentPMUserId) || $hide_claim_button ? "> $title" : "> $title"; - // } - // } - //} - - } - - return $tab; - - } - - - /** - * Summary of displayTabContentForItem - * @param CommonGLPI $case the PluginProcessmakerCase - * @param integer $tabnum contains the PluginProcessmakerTask id - * @param mixed $withtemplate - */ - static function displayTabContentForItem(CommonGLPI $case, $tabnum = 1, $withtemplate = 0) { - global $CFG_GLPI, $PM_SOAP, $DB, $PM_DB; - $dbu = new DbUtils; - - // check if we are going to view a sub-task, then redirect to sub-case itself - if (preg_match('/^(?\'cases_id\'\d+)-(\d+)$/', $tabnum, $matches)) { - // Show sub-task list - - // get all tasks that are OPEN for any sub-case of this case - $sub_tasks = []; - $res = $DB->request( - 'glpi_plugin_processmaker_tasks AS ppt', - ['AND' => [ - 'ppt.plugin_processmaker_cases_id' => $matches['cases_id'], - 'del_thread_status' => 'OPEN'] - ] - ); - //$query = "SELECT `glpi_plugin_processmaker_tasks`.* FROM `glpi_plugin_processmaker_tasks` - // WHERE `glpi_plugin_processmaker_tasks`.`plugin_processmaker_cases_id`={$matches['cases_id']} AND `del_thread_status`='OPEN'"; - //foreach ($DB->request($query) as $task) { - foreach ($res as $task) { - $sub_tasks[$task['plugin_processmaker_cases_id']][$task['del_index']] = $task; - } - $sub_case = new PluginProcessmakerCase; - $sub_case->getFromDB($matches['cases_id']); - $sub_case_url = $sub_case->getLinkURL().'&forcetab=PluginProcessmakerTask$'; - - $res = $PM_DB->request([ - 'SELECT' => ['DEL_INDEX', 'DEL_DELEGATE_DATE'], - 'FROM' => 'APP_DELEGATION', - 'WHERE' => [ - 'APP_UID' => $sub_case->fields['case_guid'] - ] - ]); - //$query = "SELECT `DEL_INDEX`, `DEL_DELEGATE_DATE` FROM `APP_DELEGATION` WHERE `APP_UID`='{$sub_case->fields['case_guid']}'"; - $sub_tasks_pm = []; - //foreach ($PM_DB->request($query) as $row) { - foreach ($res as $row) { - $sub_tasks_pm[$row['DEL_INDEX']] = $row['DEL_DELEGATE_DATE']; - } - - $sub_case_info = $sub_case->getCaseInfo(); - echo "
"; - echo ""; - - echo ""; - - if (property_exists($sub_case_info, 'currentUsers') && count($sub_case_info->currentUsers) > 0) { - - echo " - - - - - "; - - foreach ($sub_case_info->currentUsers as $currentTask) { - echo ""; - $sub_case_url .= $sub_tasks[$matches['cases_id']][$currentTask->delIndex]['id']; - echo ""; - echo ""; - if ($currentTask->userName == '') { - echo ""; - } else { - echo ""; - } - echo ""; - echo ""; - } - } else { - echo ""; - } - - echo "
".__('Sub-case task(s)', 'processmaker')."
".__('Task', 'processmaker')."".__('Task guid', 'processmaker')."".__('Current user', 'processmaker')."".__('Task delegation date', 'processmaker')."
".$currentTask->taskName."".$currentTask->taskId."".__('To be claimed', 'processmaker')."".$currentTask->userName."".$sub_tasks_pm[$currentTask->delIndex]."
".__('None')."
"; - - echo "
"; - - return; - } - - $hide_claim_button = false; - $config = $PM_SOAP->config; - $rand = rand(); - - // get infos for the current task - $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(); - $currentUser = null; - foreach ($caseInfo->currentUsers as $locTask) { - if ($locTask->delIndex == $task[$tabnum]['del_index']) { - $currentUser = $locTask; - break; - } - } - - if (isset($currentUser)) { - if ($task[$tabnum]['del_index']) { - // to load users for task re-assign only when task is not a sub-case - - echo "
".__('Loading...')."
"; - - // try to get users whom can't be assigned to this task - // already assigned user can't be assigned again to this task - $current_assigned_user = PluginProcessmakerUser::getGLPIUserId($currentUser->userId); - // and then any forbiden users defined from the case itself - $casevariablevalues = $case->getVariables(['GLPI_TASK_PREVENT_REASSIGN']); - $prevent_assign = []; - if (array_key_exists( 'GLPI_TASK_PREVENT_REASSIGN', $casevariablevalues ) && $casevariablevalues[ 'GLPI_TASK_PREVENT_REASSIGN' ] != '') { - $prevent_assign = json_decode($casevariablevalues[ 'GLPI_TASK_PREVENT_REASSIGN' ], true); - } - - - $used_users = []; - $used_users[] = $current_assigned_user; - if (array_key_exists($currentUser->taskId, $prevent_assign)) { - if (!is_array($prevent_assign[$currentUser->taskId])) { - $prevent_assign[$currentUser->taskId] = [$prevent_assign[$currentUser->taskId]]; - } - foreach ($prevent_assign[$currentUser->taskId] as $pmuser) { - $usr_id = PluginProcessmakerUser::getGlpiIdFromAny($pmuser); - if ($usr_id) { - $used_users[] = $usr_id; - } - } - } - - $data = "{ - cases_id : {$case->getID()}, - items_id : {$case->fields['items_id']}, - itemtype : '{$case->fields['itemtype']}', - tasktype : '{$task[$tabnum]['itemtype']}', - tasks_id : {$task[$tabnum]['items_id']}, - users_id : {$current_assigned_user}, - taskGuid : '{$currentUser->taskId}', - delIndex : {$task[$tabnum]['del_index']}, - delThread : {$currentUser->delThread}, - used : [".join(',', array_unique($used_users))."] - }"; - echo html::scriptBlock("$('#divUsers-{$task[$tabnum]['del_index']}').load('".$CFG_GLPI["root_doc"]."/plugins/processmaker/ajax/task_users.php', $data);"); - } - - if (!$currentUser->userId || !$task[$tabnum]['del_index']) { - // manages the claim - // current task is to be claimed - // get the assigned group to the item task - $itemtask = $dbu->getItemForItemtype( $task[$tabnum]['itemtype'] ); - $itemtask->getFromDB( $task[$tabnum]['items_id'] ); - // check if this group can be found in the current user's groups - if (!isset($_SESSION['glpigroups']) || !in_array( $itemtask->fields['groups_id_tech'], $_SESSION['glpigroups'] )) { - $hide_claim_button=true; - } - } - } - - $PM_SOAP->echoDomain(); - echo ""; - - $csrf = Session::getNewCSRFToken(); - - $url = $PM_SOAP->serverURL - ."/cases/cases_Open?sid=".$PM_SOAP->getPMSessionID() - ."&APP_UID=".$case->fields['case_guid'] - ."&DEL_INDEX=".$task[$tabnum]['del_index'] - ."&action=TO_DO" - ."&rand=$rand" - ."&glpi_domain={$config->fields['domain']}"; - - $encoded_url = urlencode($url); - - echo ""; - - echo Html::scriptBlock(" - $('#tabspanel').next('div[id^=\"tabs\"]').on( 'tabsbeforeactivate', function(event, ui) { - function urldecode(url) { - return decodeURIComponent(url.replace(/\+/g, ' ')); - } - var iframe_id = 'caseiframe-task-{$task[$tabnum]['del_index']}'; - var iframe = ui.newPanel.children('iframe[id=\"' + iframe_id + '\"]'); - if (iframe.length != 0) { - var str = urldecode('$encoded_url'); - $.ajax( { url: str, - xhrFields: { withCredentials: true }, - success: function (jqXHR) { - //debugger; - }, - error: function (jqXHR) { - // debugger; - }, - cache: false, - crossDomain: true - } - ); - } - }); - "); - } - - - /** - * Summary of sendNotification - * Will send either dedicated notification, or standard one - * @param string $type is 'task_add', 'task_reassign', 'task_done', 'task_reminder' - * @param CommonITILTask $task is the task (TicketTask,...) - * @param CommonITILObject $item is the ITIL item (Ticket,...) - * @param PluginProcessmakerCase $case is the case - */ - function sendNotification(string $type, CommonITILTask $task, CommonITILObject $item, PluginProcessmakerCase $case = null) { - // Notification management - // search if at least one active notification is existing for that pm task with that event 'task_update_'.$glpi_task->fields['taskcategories_id'] - $res = PluginProcessmakerNotificationTargetTask::getNotifications($type, $task->fields['taskcategories_id'], $item->fields['entities_id']); - if ($res['notifications'] && count($res['notifications']) > 0) { - NotificationEvent::raiseEvent($res['event'], - $this, - ['plugin_processmaker_cases_id' => $this->fields['plugin_processmaker_cases_id'], - 'itemtype' => $item->getType(), - 'task_id' => $task->getID(), - 'old_users_id_tech' => isset($task->oldvalues['users_id_tech']) ? $task->oldvalues['users_id_tech'] : 0, - 'is_private' => isset($task->fields['is_private']) ? $task->fields['is_private'] : 0, - 'entities_id' => $item->fields['entities_id'], - 'case' => $case, - 'obj' => $item - ]); - } else { - NotificationEvent::raiseEvent(PluginProcessmakerNotificationTargetTask::getDefaultGLPIEvents($type), - $item, - ['plugin_processmaker_cases_id' => $this->fields['plugin_processmaker_cases_id'], - 'itemtype' => $item->getType(), - 'task_id' => $task->getID(), - 'is_private' => isset($task->fields['is_private']) ? $task->fields['is_private'] : 0 - ]); - } - - } - - -} +itemtype = $itemtype; + } + + + const OPEN = 'OPEN'; + const CLOSED = 'CLOSED'; + + /** + * Name of the type + * + * @param $nb : number of item in the type (default 0) + **/ + static function getTypeName($nb = 0) { + return _n('Process case task', 'Process case tasks', $nb, 'processmaker'); + } + + function getItilObjectItemType() { + return str_replace('Task', '', $this->itemtype); + } + /** + * Summary of getFromDB + * @param mixed $items_id + * @param mixed $itemtype + * @return bool + */ + function getFromDB($items_id) { + global $DB; + + //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 + $task->fields['items_id'] = $this->fields['id']; + $task->fields['itemtype'] = $this->fields['itemtype']; + unset( $this->fields['id'] ); + unset( $this->fields['items_id'] ); + unset( $this->fields['itemtype'] ); + foreach ($this->fields as $field => $val) { + $task->fields[ $field ] = $val; + } + $this->fields = $task->fields; + return true; + } + } + + return false; + } + + + /** + * Summary of getPMTaskID + * @return mixed + */ + function getPMTaskID() { + return $this->fields['items_id']; + } + + /** + * Summary of getToDoTasks + * returns all 'to do' tasks associated with this case + * @param mixed $case_id + */ + public static function getToDoTasks($case_id, $itemtype) { + global $DB; + $ret = []; + $dbu = new DbUtils; + $selfTable = $dbu->getTableForItemType( __CLASS__); + //$itemTypeTaskTable = getTableForItemType( $itemtype ); + + $res = $DB->request([ + 'SELECT' => $selfTable.'.items_id AS taskID', + 'FROM' => $selfTable, + 'WHERE' => [ + 'AND' => [ + $selfTable.'del_thread_status' => self::OPEN, + $selfTable.'plugin_processmaker_cases_id' =>$case_id + ] + ] + ]); + //$query = "SELECT `$selfTable`.`items_id` as taskID from $selfTable + // WHERE `$selfTable`.`del_thread_status` = '".self::OPEN."' AND `$selfTable`.`plugin_processmaker_cases_id` = '$case_id';"; + + //$query = "SELECT $itemTypeTaskTable.id as taskID from $itemTypeTaskTable + // INNER JOIN $selfTable on $selfTable.items_id=$itemTypeTaskTable.id + // WHERE $itemTypeTaskTable.state=1 and $selfTable.plugin_processmaker_cases_id='$case_id';"; + //foreach ($DB->request($query) as $row) { + foreach ($res as $row) { + $ret[$row['taskID']]=$row['taskID']; + } + return $ret; + } + + static function canView() { + return true; + } + + static function populatePlanning($params = []) :array { + //global $CFG_GLPI; + + $events = []; + + if (isset($params['start'])) { + $params['begin'] = '2000-01-01 00:00:00'; + if ($params['type'] == 'group') { + $params['who_group'] = $params['who']; + $params['whogroup'] = $params['who']; + $params['who'] = 0; + } + + $objects = ['TicketTask', 'ChangeTask', 'ProblemTask']; + //foreach ($objects as $itemtype) { + foreach ($_SESSION['glpi_plannings']['filters'] as $tasktype => $iteminfo) { + if (!$iteminfo['display'] || !in_array($tasktype, $objects)) { + continue; + } + $ret = CommonITILTask::genericPopulatePlanning($tasktype, $params); + + foreach ($ret as $key => $event) { + // if todo or done but need to show them (=planning) + if ($event['state'] == Planning::TODO || $event['state'] == Planning::INFO || ($params['display_done_events'] == 1 && $event['state'] == Planning::DONE)) { + // check if task is one within a case + $pmTask = new PluginProcessmakerTask($tasktype); + if ($pmTask->getFromDB($event[strtolower($tasktype).'s_id'])) { // $pmTask->getFromDBByQuery( " WHERE itemtype = 'TicketTask' AND items_id = ". $event['tickettasks_id'] ) ) { + $event['editable'] = false; + //$event['url'] .= '&forcetab=PluginProcessmakerCase$processmakercases'; + $tmpCase = new PluginProcessmakerCase; + $tmpCase->getFromDB($pmTask->fields['plugin_processmaker_cases_id']); + $event['url'] = $tmpCase->getLinkURL().'&forcetab=PluginProcessmakerTask$'.$pmTask->fields['items_id']; + + $taskCat = new TaskCategory; + $taskCat->getFromDB( $pmTask->fields['taskcategories_id'] ); + $taskComment = isset($taskCat->fields['comment']) ? $taskCat->fields['comment'] : ''; + if (Session::haveTranslations('TaskCategory', 'comment')) { + $taskComment = DropdownTranslation::getTranslatedValue( $taskCat->getID(), 'TaskCategory', 'comment', $_SESSION['glpilanguage'], $taskComment ); + } + + $event['content'] = str_replace( '##processmaker.taskcomment##', $taskComment, $event['content'] ); + $event['content'] = str_replace( ['\n##processmakercase.url##', '##processmakercase.url##'], "", $event['content'] ); //"."Click to manage task"." + //if( $event['state'] == 1 && $event['end'] < $params['start'] ) { // if todo and late + // $event['name'] = $event['end'].' '.$event['name'] ; //$event['begin'].' to '.$event['end'].' '.$event['name'] ; + // $event['end'] = $params['start'].' 24:00:00'; //.$CFG_GLPI['planning_end']; + //} + $events[$key] = $event; + } + } + } + } + } + return $events; + } + + + function getTabNameForItem(CommonGLPI $case, $withtemplate = 0) { + global $DB, $PM_DB; + + $tab = []; + + $caseInfo = $case->getCaseInfo(); + + if (property_exists($caseInfo, 'currentUsers')) { + $dbu = new DbUtils; + $GLPICurrentPMUserId = PluginProcessmakerUser::getPMUserId(Session::getLoginUserID()); + + // get all tasks that are OPEN for this case + $tasks = []; + $res = $DB->request( + 'glpi_plugin_processmaker_tasks', [ + 'AND' => [ + 'plugin_processmaker_cases_id' => $case->fields['id'], + 'del_thread_status' => 'OPEN' + ] + ] + ); + //$query = "SELECT * FROM `glpi_plugin_processmaker_tasks` WHERE `plugin_processmaker_cases_id`={$case->fields['id']} AND `del_thread_status`='OPEN'"; + //foreach ($DB->request($query) as $task) { + foreach ($res as $task) { + $tasks[$task['del_index']] = $task; + } + + //// get all tasks that are OPEN for any sub-case of this case + //$sub_cases = []; + //$query = "SELECT `glpi_plugin_processmaker_tasks`.* FROM `glpi_plugin_processmaker_tasks` + // JOIN `glpi_plugin_processmaker_cases` on `glpi_plugin_processmaker_cases`.`id`=`glpi_plugin_processmaker_tasks`.`plugin_processmaker_cases_id` + // WHERE `glpi_plugin_processmaker_cases`.`plugin_processmaker_cases_id`={$case->fields['id']} AND `del_thread_status`='OPEN'"; + //foreach($DB->request($query) as $task) { + // $sub_cases[$task['plugin_processmaker_cases_id']][$task['del_index']] = $task; + //} + + $caseInfo->currentUsers = $case->sortTasks($caseInfo->currentUsers, $GLPICurrentPMUserId); + + $main_tasks = []; //will contains the tasks that are main-processes + foreach ($caseInfo->currentUsers as $caseUser) { + $title = $caseUser->taskName; + if (isset($tasks[$caseUser->delIndex])) { + $hide_claim_button = false; + if ($caseUser->userId == '') { // task to be claimed + $itemtask = $dbu->getItemForItemtype($tasks[$caseUser->delIndex]['itemtype']); + $itemtask->getFromDB($tasks[$caseUser->delIndex]['items_id']); + // check if this group can be found in the current user's groups + if (!isset($_SESSION['glpigroups']) || !in_array( $itemtask->fields['groups_id_tech'], $_SESSION['glpigroups'] )) { + $hide_claim_button = true; + } + } + $tab[$tasks[$caseUser->delIndex]['id']] = ($caseUser->userId != '' && $caseUser->userId != $GLPICurrentPMUserId) || $hide_claim_button ? "$title" : $title; + } else { + $main_tasks[$caseUser->delIndex] = $caseUser; + } + } + + foreach ($main_tasks as $task) { + $res = $PM_DB->request([ + 'SELECT' => 'APP_UID', + 'FROM' => 'SUB_APPLICATION', + 'WHERE' => [ + 'AND' => [ + 'APP_PARENT' => $case->fields['case_guid'], + 'DEL_INDEX_PARENT' => $task->delIndex, + 'SA_STATUS' => 'ACTIVE' + ] + ] + ]); + //$res = $PM_DB->query("SELECT APP_UID FROM SUB_APPLICATION WHERE APP_PARENT='{$case->fields['case_guid']}' AND DEL_INDEX_PARENT={$task->delIndex} AND SA_STATUS='ACTIVE'"); + //if ($res && $PM_DB->numrows($res) == 1) { + if ($res->numrows() == 1 && $row = $res->next()) { + //$row = $PM_DB->fetch_assoc($res); + $loc_case = new PluginProcessmakerCase; + $loc_case->getFromGUID($row['APP_UID']); + $tab[$loc_case->getID()."-".$task->delIndex] = "> ".$task->taskName.""; + } + } + //$sub_case = new PluginProcessmakerCase; + //foreach ($sub_cases as $sub_cases_id => $sub_tasks) { + // $sub_case->getFromDB($sub_cases_id); + // $sub_case_info = $sub_case->getCaseInfo(); + // $sub_case_info->currentUsers = $sub_case->sortTasks($sub_case_info->currentUsers, $GLPICurrentPMUserId); + // foreach ($sub_case_info->currentUsers as $caseUser) { + // $title = $caseUser->taskName; + // if (isset($sub_tasks[$caseUser->delIndex])) { + // $hide_claim_button = false; + // if ($caseUser->userId == '') { // task to be claimed + // $itemtask = getItemForItemtype($sub_tasks[$caseUser->delIndex]['itemtype']); + // $itemtask->getFromDB($sub_tasks[$caseUser->delIndex]['items_id']); + // // check if this group can be found in the current user's groups + // if (!isset($_SESSION['glpigroups']) || !in_array( $itemtask->fields['groups_id_tech'], $_SESSION['glpigroups'] )) { + // $hide_claim_button = true; + // } + // } + // $tab["$sub_cases_id-".$sub_tasks[$caseUser->delIndex]['id']] = ($caseUser->userId != '' && $caseUser->userId != $GLPICurrentPMUserId) || $hide_claim_button ? "> $title" : "> $title"; + // } + // } + //} + + } + + return $tab; + + } + + + /** + * Summary of displayTabContentForItem + * @param CommonGLPI $case the PluginProcessmakerCase + * @param integer $tabnum contains the PluginProcessmakerTask id + * @param mixed $withtemplate + */ + static function displayTabContentForItem(CommonGLPI $case, $tabnum = 1, $withtemplate = 0) { + global $CFG_GLPI, $PM_SOAP, $DB, $PM_DB; + $dbu = new DbUtils; + + // check if we are going to view a sub-task, then redirect to sub-case itself + if (preg_match('/^(?\'cases_id\'\d+)-(\d+)$/', $tabnum, $matches)) { + // Show sub-task list + + // get all tasks that are OPEN for any sub-case of this case + $sub_tasks = []; + $res = $DB->request( + 'glpi_plugin_processmaker_tasks AS ppt', + ['AND' => [ + 'ppt.plugin_processmaker_cases_id' => $matches['cases_id'], + 'del_thread_status' => 'OPEN'] + ] + ); + //$query = "SELECT `glpi_plugin_processmaker_tasks`.* FROM `glpi_plugin_processmaker_tasks` + // WHERE `glpi_plugin_processmaker_tasks`.`plugin_processmaker_cases_id`={$matches['cases_id']} AND `del_thread_status`='OPEN'"; + //foreach ($DB->request($query) as $task) { + foreach ($res as $task) { + $sub_tasks[$task['plugin_processmaker_cases_id']][$task['del_index']] = $task; + } + $sub_case = new PluginProcessmakerCase; + $sub_case->getFromDB($matches['cases_id']); + $sub_case_url = $sub_case->getLinkURL().'&forcetab=PluginProcessmakerTask$'; + + $res = $PM_DB->request([ + 'SELECT' => ['DEL_INDEX', 'DEL_DELEGATE_DATE'], + 'FROM' => 'APP_DELEGATION', + 'WHERE' => [ + 'APP_UID' => $sub_case->fields['case_guid'] + ] + ]); + //$query = "SELECT `DEL_INDEX`, `DEL_DELEGATE_DATE` FROM `APP_DELEGATION` WHERE `APP_UID`='{$sub_case->fields['case_guid']}'"; + $sub_tasks_pm = []; + //foreach ($PM_DB->request($query) as $row) { + foreach ($res as $row) { + $sub_tasks_pm[$row['DEL_INDEX']] = $row['DEL_DELEGATE_DATE']; + } + + $sub_case_info = $sub_case->getCaseInfo(); + echo "
"; + echo ""; + + echo ""; + + if (property_exists($sub_case_info, 'currentUsers') && count($sub_case_info->currentUsers) > 0) { + + echo " + + + + + "; + + foreach ($sub_case_info->currentUsers as $currentTask) { + echo ""; + $sub_case_url .= $sub_tasks[$matches['cases_id']][$currentTask->delIndex]['id']; + echo ""; + echo ""; + if ($currentTask->userName == '') { + echo ""; + } else { + echo ""; + } + echo ""; + echo ""; + } + } else { + echo ""; + } + + echo "
".__('Sub-case task(s)', 'processmaker')."
".__('Task', 'processmaker')."".__('Task guid', 'processmaker')."".__('Current user', 'processmaker')."".__('Task delegation date', 'processmaker')."
".$currentTask->taskName."".$currentTask->taskId."".__('To be claimed', 'processmaker')."".$currentTask->userName."".$sub_tasks_pm[$currentTask->delIndex]."
".__('None')."
"; + + echo "
"; + + return; + } + + $hide_claim_button = false; + $config = $PM_SOAP->config; + $rand = rand(); + + // get infos for the current task + $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(); + $currentUser = null; + foreach ($caseInfo->currentUsers as $locTask) { + if ($locTask->delIndex == $task[$tabnum]['del_index']) { + $currentUser = $locTask; + break; + } + } + + if (isset($currentUser)) { + if ($task[$tabnum]['del_index']) { + // to load users for task re-assign only when task is not a sub-case + + echo "
".__('Loading...')."
"; + + // try to get users whom can't be assigned to this task + // already assigned user can't be assigned again to this task + $current_assigned_user = PluginProcessmakerUser::getGLPIUserId($currentUser->userId); + // and then any forbiden users defined from the case itself + $casevariablevalues = $case->getVariables(['GLPI_TASK_PREVENT_REASSIGN']); + $prevent_assign = []; + if (array_key_exists( 'GLPI_TASK_PREVENT_REASSIGN', $casevariablevalues ) && $casevariablevalues[ 'GLPI_TASK_PREVENT_REASSIGN' ] != '') { + $prevent_assign = json_decode($casevariablevalues[ 'GLPI_TASK_PREVENT_REASSIGN' ], true); + } + + + $used_users = []; + $used_users[] = $current_assigned_user; + if (array_key_exists($currentUser->taskId, $prevent_assign)) { + if (!is_array($prevent_assign[$currentUser->taskId])) { + $prevent_assign[$currentUser->taskId] = [$prevent_assign[$currentUser->taskId]]; + } + foreach ($prevent_assign[$currentUser->taskId] as $pmuser) { + $usr_id = PluginProcessmakerUser::getGlpiIdFromAny($pmuser); + if ($usr_id) { + $used_users[] = $usr_id; + } + } + } + + $data = "{ + cases_id : {$case->getID()}, + items_id : {$case->fields['items_id']}, + itemtype : '{$case->fields['itemtype']}', + tasktype : '{$task[$tabnum]['itemtype']}', + tasks_id : {$task[$tabnum]['items_id']}, + users_id : {$current_assigned_user}, + caseGuid : '{$case->fields['case_guid']}', + taskGuid : '{$currentUser->taskId}', + delIndex : {$task[$tabnum]['del_index']}, + delThread : {$currentUser->delThread}, + used : [".join(',', array_unique($used_users))."] + }"; + echo html::scriptBlock("$('#divUsers-{$task[$tabnum]['del_index']}').load('".$CFG_GLPI["root_doc"]."/plugins/processmaker/ajax/task_users.php', $data);"); + } + + if (!$currentUser->userId || !$task[$tabnum]['del_index']) { + // manages the claim + // current task is to be claimed + // get the assigned group to the item task + $itemtask = $dbu->getItemForItemtype( $task[$tabnum]['itemtype'] ); + $itemtask->getFromDB( $task[$tabnum]['items_id'] ); + // check if this group can be found in the current user's groups + if (!isset($_SESSION['glpigroups']) || !in_array( $itemtask->fields['groups_id_tech'], $_SESSION['glpigroups'] )) { + $hide_claim_button=true; + } + } + } + + $PM_SOAP->echoDomain(); + echo ""; + + $csrf = Session::getNewCSRFToken(); + + $url = $PM_SOAP->serverURL + ."/cases/cases_Open?sid=".$PM_SOAP->getPMSessionID() + ."&APP_UID=".$case->fields['case_guid'] + ."&DEL_INDEX=".$task[$tabnum]['del_index'] + ."&action=TO_DO" + ."&rand=$rand" + ."&glpi_domain={$config->fields['domain']}"; + + $encoded_url = urlencode($url); + + echo ""; + + echo Html::scriptBlock(" + $('#tabspanel').next('div[id^=\"tabs\"]').on( 'tabsbeforeactivate', function(event, ui) { + function urldecode(url) { + return decodeURIComponent(url.replace(/\+/g, ' ')); + } + var iframe_id = 'caseiframe-task-{$task[$tabnum]['del_index']}'; + var iframe = ui.newPanel.children('iframe[id=\"' + iframe_id + '\"]'); + if (iframe.length != 0) { + var str = urldecode('$encoded_url'); + $.ajax( { url: str, + xhrFields: { withCredentials: true }, + success: function (jqXHR) { + //debugger; + }, + error: function (jqXHR) { + // debugger; + }, + cache: false, + crossDomain: true + } + ); + } + }); + "); + } + + + /** + * Summary of sendNotification + * Will send either dedicated notification, or standard one + * @param string $type is 'task_add', 'task_reassign', 'task_done', 'task_reminder' + * @param CommonITILTask $task is the task (TicketTask,...) + * @param CommonITILObject $item is the ITIL item (Ticket,...) + * @param PluginProcessmakerCase $case is the case + */ + function sendNotification(string $type, CommonITILTask $task, CommonITILObject $item, PluginProcessmakerCase $case = null) { + // Notification management + // search if at least one active notification is existing for that pm task with that event 'task_update_'.$glpi_task->fields['taskcategories_id'] + $res = PluginProcessmakerNotificationTargetTask::getNotifications($type, $task->fields['taskcategories_id'], $item->fields['entities_id']); + if ($res['notifications'] && count($res['notifications']) > 0) { + NotificationEvent::raiseEvent($res['event'], + $this, + ['plugin_processmaker_cases_id' => $this->fields['plugin_processmaker_cases_id'], + 'itemtype' => $item->getType(), + 'task_id' => $task->getID(), + 'old_users_id_tech' => isset($task->oldvalues['users_id_tech']) ? $task->oldvalues['users_id_tech'] : 0, + 'is_private' => isset($task->fields['is_private']) ? $task->fields['is_private'] : 0, + 'entities_id' => $item->fields['entities_id'], + 'case' => $case, + 'obj' => $item + ]); + } else { + NotificationEvent::raiseEvent(PluginProcessmakerNotificationTargetTask::getDefaultGLPIEvents($type), + $item, + ['plugin_processmaker_cases_id' => $this->fields['plugin_processmaker_cases_id'], + 'itemtype' => $item->getType(), + 'task_id' => $task->getID(), + 'is_private' => isset($task->fields['is_private']) ? $task->fields['is_private'] : 0 + ]); + } + + } + + +} diff --git a/inc/taskcategory.class.php b/inc/taskcategory.class.php index 6305ca0..f138a66 100644 --- a/inc/taskcategory.class.php +++ b/inc/taskcategory.class.php @@ -1,385 +1,385 @@ -getType() == 'TaskCategory') { - $pmtaskcat = new PluginProcessmakerTaskCategory; - if ($pmtaskcat->getFromDBbyCategory($item->fields['id'])) { - return __('Process task', 'processmaker'); - } else { - return ''; // means no tab - } - } - return __('Task list', 'processmaker'); - } - - - static function displayTabContentForProcess(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - global $DB, $CFG_GLPI; - - self::title($item); - - echo "

"; - echo ""; - echo "". - "" . - "" . - "" . - "" . - "" . - "" . - ""; - - $res = $DB->request([ - 'SELECT' => [ - 'pm.pm_task_guid', - 'pm.taskcategories_id', - 'pm.is_start', - 'gl.name', - 'gl.completename', - 'gl.comment', - 'pm.is_active', - 'pm.is_subprocess' - ], - 'FROM' => 'glpi_plugin_processmaker_taskcategories AS pm', - 'LEFT JOIN' => [ - 'glpi_taskcategories AS gl' => [ - 'FKEY' => [ - 'gl' => 'id', - 'pm' => 'taskcategories_id' - ] - ] - ], - 'WHERE' => [ - 'pm.plugin_processmaker_processes_id' => $item->getId() - ] - ]); - //$query = "SELECT pm.pm_task_guid, pm.taskcategories_id, pm.`is_start`, gl.name, gl.completename, gl.`comment`, pm.is_active, pm.is_subprocess FROM glpi_plugin_processmaker_taskcategories AS pm - // LEFT JOIN glpi_taskcategories AS gl ON pm.taskcategories_id=gl.id - // WHERE pm.plugin_processmaker_processes_id=".$item->getID().";"; - - //foreach ($DB->request($query) as $taskCat) { - foreach ($res as $taskCat) { - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - } - echo "
".__('Task List', 'processmaker')."
".__('Task name', 'processmaker')."".__('Complete name')."".__('Start', 'processmaker')."".__('Task GUID', 'processmaker')."".__('Comments')."".__('Active')."".__('Sub-process', 'processmaker')."
" . $taskCat['name']; - if ($_SESSION["glpiis_ids_visible"]) { - echo " (" . $taskCat['taskcategories_id'] . ")"; - } - echo "" . $taskCat['completename'] . ""; - if ($taskCat['is_start']) { - echo "\""."; - } - echo "".$taskCat['pm_task_guid']."".$taskCat['comment'].""; - if ($taskCat['is_active']) { - echo "\""."; - } - echo ""; - if ($taskCat['is_subprocess']) { - echo "\""."; - } - echo "
"; - - return true; - } - - - /** - * Summary of displayTabContentForTaskCategory - * @param CommonGLPI $item - * @param mixed $tabnum - * @param mixed $withtemplate - * @return boolean - */ - static function displayTabContentForTaskCategory(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - global $DB, $CFG_GLPI; - - $is_taskcat = false; - $processes_id = 0; - $pmtaskcat = new PluginProcessmakerTaskCategory; - $is_taskcat = $pmtaskcat->getFromDBbyCategory($item->fields['id']); - $processes_id = $pmtaskcat->fields['plugin_processmaker_processes_id']; - - echo "

"; - - echo ""; - echo ""; - echo ""; - - echo "" . - "" . - "" . - "" . - "" . - "" . - ""; - - $query = "SELECT pm.pm_task_guid, pm.taskcategories_id, pm.`is_start`, glp.name as 'pname', gl.name, gl.completename, gl.`comment`, pm.is_active, pm.is_subprocess FROM glpi_plugin_processmaker_taskcategories AS pm - LEFT JOIN glpi_taskcategories AS gl ON pm.taskcategories_id=gl.id - LEFT JOIN glpi_taskcategories AS glp ON glp.id=gl.taskcategories_id - WHERE pm.taskcategories_id=".$item->getID().";"; - - foreach ($DB->request($query) as $taskCat) { - echo ""; - - echo ""; - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - - echo ""; - } - echo "
".__('Process task', 'processmaker')."
".__('Process name', 'processmaker')."".__('Task name', 'processmaker')."".__('Complete name')."".__('Start', 'processmaker')."".__('Task GUID', 'processmaker')."".__('Comments')."".__('Active')."".__('Sub-process', 'processmaker')."
" . $taskCat['pname']; - if ($_SESSION["glpiis_ids_visible"]) { - echo " (" . $processes_id . ")"; - } - echo ""; - echo $taskCat['name']; - - if ($_SESSION["glpiis_ids_visible"]) { - echo " (" . $taskCat['taskcategories_id'] . ")"; - } - echo "" . $taskCat['completename'] . ""; - if ($taskCat['is_start']) { - echo "\""."; - } - echo "".$taskCat['pm_task_guid']."".$taskCat['comment'].""; - if ($taskCat['is_active']) { - echo "\""."; - } - echo ""; - if ($taskCat['is_subprocess']) { - echo "\""."; - } - echo "
"; - - return true; - } - - - /** - * Summary of displayTabContentForItem - * @param CommonGLPI $item - * @param mixed $tabnum - * @param mixed $withtemplate - * @return boolean - */ - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - $ret = false; - switch ($item->getType()) { - case 'PluginProcessmakerProcess': - $ret = self::displayTabContentForProcess($item, $tabnum, $withtemplate); - break; - case 'TaskCategory': - $ret = self::displayTabContentForTaskCategory($item, $tabnum, $withtemplate); - break; - } - return $ret; - } - - /** - * 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; - - if (Session::haveRight('plugin_processmaker_config', UPDATE)) { - $title = __('Synchronize Task List', 'processmaker'); - $buttons = ["process.form.php?refreshtask=1&id=".$item->getID() => $title]; - $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); - } - } - - - /** - * 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; - - $res = $DB->request( - $this->getTable(), - [ - 'pm_task_guid' => $task_guid - ] - ); - if ($res) { - if ($res->numrows() != 1) { - return false; - } - $this->fields = $res->next(); - if (is_array($this->fields) && count($this->fields)) { - return true; - } - } - - //$query = "SELECT * - // FROM `".$this->getTable()."` - // WHERE `pm_task_guid` = '$task_guid'"; - - //if ($result = $DB->query($query)) { - // if ($DB->numrows($result) != 1) { - // return false; - // } - // $this->fields = $DB->fetch_assoc($result); - // if (is_array($this->fields) && count($this->fields)) { - // return true; - // } - //} - return false; - } - - /** - * Retrieve a TaskCat from the database using its category id (unique index): taskcategories_id - * - * @param $catid string task category id - * - * @return true if succeed else false - **/ - function getFromDBbyCategory($catid) { - global $DB; - - $res = $DB->request( - $this->getTable(), - [ - 'taskcategories_id' => $catid - ] - ); - //$query = "SELECT * - // FROM `".$this->getTable()."` - // WHERE `taskcategories_id` = $catid"; - if ($res) { - if ($res->numrows() != 1) { - return false; - } - $this->fields = $res->next(); - if (is_array($this->fields) && count($this->fields)) { - return true; - } - } - //if ($result = $DB->query($query)) { - // if ($DB->numrows($result) != 1) { - // return false; - // } - // $this->fields = $DB->fetch_assoc($result); - // if (is_array($this->fields) && count($this->fields)) { - // return true; - // } - //} - return false; - } - - ///** - // * Summary of dropdown - // * @param mixed $options - // * @return mixed - // */ - //static function dropdown($options=array()) { - // global $CFG_GLPI; - // if (isset($options['value'])) { - // $that = new self; - // $that->getFromDB($options['value']); - // $options['value'] = $that->fields['taskcategories_id']; - // } - - // $options['url'] = $CFG_GLPI["root_doc"].'/plugins/processmaker/ajax/dropdownTaskcategories.php'; - // return Dropdown::show( 'TaskCategory', $options ); - - //} - - ///** - // * Execute the query to select ProcesssmakerTaskcategories - // * - // * @param $count true if execute an count(*), - // * @param $search pattern - // * - // * @return mysql result set. - // **/ - //static function getSqlSearchResult ($count=true, $search='') { - // global $DB, $CFG_GLPI; - - // $orderby = ''; - - // $where = ' WHERE glpi_plugin_processmaker_taskcategories.is_active=1 '; - - // $join = ' LEFT JOIN glpi_taskcategories ON glpi_taskcategories.id = glpi_plugin_processmaker_taskcategories.taskcategories_id'; - - // if ($count) { - // $fields = " COUNT(DISTINCT glpi_plugin_processmaker_taskcategories.id) AS cpt "; - // } else { - // $fields = " DISTINCT glpi_taskcategories.id, glpi_taskcategories.completename AS name "; - // $orderby = " ORDER BY glpi_taskcategories.completename ASC"; - // } - - // if (strlen($search)>0 && $search!=$CFG_GLPI["ajax_wildcard"]) { - // $where .= " AND (glpi_taskcategories.completename $search - // OR glpi_taskcategories.comment $search) "; - // } - - // $query = "SELECT $fields FROM glpi_plugin_processmaker_taskcategories $join ".$where." ".$orderby.";"; - - // return $DB->query($query); - //} - - -} +getType() == 'TaskCategory') { + $pmtaskcat = new PluginProcessmakerTaskCategory; + if ($pmtaskcat->getFromDBbyCategory($item->fields['id'])) { + return __('Process task', 'processmaker'); + } else { + return ''; // means no tab + } + } + return __('Task list', 'processmaker'); + } + + + static function displayTabContentForProcess(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { + global $DB, $CFG_GLPI; + + self::title($item); + + echo "

"; + echo ""; + echo "". + "" . + "" . + "" . + "" . + "" . + "" . + ""; + + $res = $DB->request([ + 'SELECT' => [ + 'pm.pm_task_guid', + 'pm.taskcategories_id', + 'pm.is_start', + 'gl.name', + 'gl.completename', + 'gl.comment', + 'pm.is_active', + 'pm.is_subprocess' + ], + 'FROM' => 'glpi_plugin_processmaker_taskcategories AS pm', + 'LEFT JOIN' => [ + 'glpi_taskcategories AS gl' => [ + 'FKEY' => [ + 'gl' => 'id', + 'pm' => 'taskcategories_id' + ] + ] + ], + 'WHERE' => [ + 'pm.plugin_processmaker_processes_id' => $item->getId() + ] + ]); + //$query = "SELECT pm.pm_task_guid, pm.taskcategories_id, pm.`is_start`, gl.name, gl.completename, gl.`comment`, pm.is_active, pm.is_subprocess FROM glpi_plugin_processmaker_taskcategories AS pm + // LEFT JOIN glpi_taskcategories AS gl ON pm.taskcategories_id=gl.id + // WHERE pm.plugin_processmaker_processes_id=".$item->getID().";"; + + //foreach ($DB->request($query) as $taskCat) { + foreach ($res as $taskCat) { + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + } + echo "
".__('Task list', 'processmaker')."
".__('Task name', 'processmaker')."".__('Complete name')."".__('Start', 'processmaker')."".__('Task guid', 'processmaker')."".__('Comments')."".__('Active')."".__('Sub-process', 'processmaker')."
" . $taskCat['name']; + if ($_SESSION["glpiis_ids_visible"]) { + echo " (" . $taskCat['taskcategories_id'] . ")"; + } + echo "" . $taskCat['completename'] . ""; + if ($taskCat['is_start']) { + echo "\""."; + } + echo "".$taskCat['pm_task_guid']."".$taskCat['comment'].""; + if ($taskCat['is_active']) { + echo "\""."; + } + echo ""; + if ($taskCat['is_subprocess']) { + echo "\""."; + } + echo "
"; + + return true; + } + + + /** + * Summary of displayTabContentForTaskCategory + * @param CommonGLPI $item + * @param mixed $tabnum + * @param mixed $withtemplate + * @return boolean + */ + static function displayTabContentForTaskCategory(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { + global $DB, $CFG_GLPI; + + $is_taskcat = false; + $processes_id = 0; + $pmtaskcat = new PluginProcessmakerTaskCategory; + $is_taskcat = $pmtaskcat->getFromDBbyCategory($item->fields['id']); + $processes_id = $pmtaskcat->fields['plugin_processmaker_processes_id']; + + echo "

"; + + echo ""; + echo ""; + echo ""; + + echo "" . + "" . + "" . + "" . + "" . + "" . + ""; + + $query = "SELECT pm.pm_task_guid, pm.taskcategories_id, pm.`is_start`, glp.name as 'pname', gl.name, gl.completename, gl.`comment`, pm.is_active, pm.is_subprocess FROM glpi_plugin_processmaker_taskcategories AS pm + LEFT JOIN glpi_taskcategories AS gl ON pm.taskcategories_id=gl.id + LEFT JOIN glpi_taskcategories AS glp ON glp.id=gl.taskcategories_id + WHERE pm.taskcategories_id=".$item->getID().";"; + + foreach ($DB->request($query) as $taskCat) { + echo ""; + + echo ""; + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + + echo ""; + } + echo "
".__('Process task', 'processmaker')."
".__('Process name', 'processmaker')."".__('Task name', 'processmaker')."".__('Complete name')."".__('Start', 'processmaker')."".__('Task guid', 'processmaker')."".__('Comments')."".__('Active')."".__('Sub-process', 'processmaker')."
" . $taskCat['pname']; + if ($_SESSION["glpiis_ids_visible"]) { + echo " (" . $processes_id . ")"; + } + echo ""; + echo $taskCat['name']; + + if ($_SESSION["glpiis_ids_visible"]) { + echo " (" . $taskCat['taskcategories_id'] . ")"; + } + echo "" . $taskCat['completename'] . ""; + if ($taskCat['is_start']) { + echo "\""."; + } + echo "".$taskCat['pm_task_guid']."".$taskCat['comment'].""; + if ($taskCat['is_active']) { + echo "\""."; + } + echo ""; + if ($taskCat['is_subprocess']) { + echo "\""."; + } + echo "
"; + + return true; + } + + + /** + * Summary of displayTabContentForItem + * @param CommonGLPI $item + * @param mixed $tabnum + * @param mixed $withtemplate + * @return boolean + */ + static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { + $ret = false; + switch ($item->getType()) { + case 'PluginProcessmakerProcess': + $ret = self::displayTabContentForProcess($item, $tabnum, $withtemplate); + break; + case 'TaskCategory': + $ret = self::displayTabContentForTaskCategory($item, $tabnum, $withtemplate); + break; + } + return $ret; + } + + /** + * 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; + + if (Session::haveRight('plugin_processmaker_config', UPDATE)) { + $title = __('Synchronize Task List', 'processmaker'); + $buttons = ["process.form.php?refreshtask=1&id=".$item->getID() => $title]; + $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); + } + } + + + /** + * 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; + + $res = $DB->request( + $this->getTable(), + [ + 'pm_task_guid' => $task_guid + ] + ); + if ($res) { + if ($res->numrows() != 1) { + return false; + } + $this->fields = $res->next(); + if (is_array($this->fields) && count($this->fields)) { + return true; + } + } + + //$query = "SELECT * + // FROM `".$this->getTable()."` + // WHERE `pm_task_guid` = '$task_guid'"; + + //if ($result = $DB->query($query)) { + // if ($DB->numrows($result) != 1) { + // return false; + // } + // $this->fields = $DB->fetch_assoc($result); + // if (is_array($this->fields) && count($this->fields)) { + // return true; + // } + //} + return false; + } + + /** + * Retrieve a TaskCat from the database using its category id (unique index): taskcategories_id + * + * @param $catid string task category id + * + * @return true if succeed else false + **/ + function getFromDBbyCategory($catid) { + global $DB; + + $res = $DB->request( + $this->getTable(), + [ + 'taskcategories_id' => $catid + ] + ); + //$query = "SELECT * + // FROM `".$this->getTable()."` + // WHERE `taskcategories_id` = $catid"; + if ($res) { + if ($res->numrows() != 1) { + return false; + } + $this->fields = $res->next(); + if (is_array($this->fields) && count($this->fields)) { + return true; + } + } + //if ($result = $DB->query($query)) { + // if ($DB->numrows($result) != 1) { + // return false; + // } + // $this->fields = $DB->fetch_assoc($result); + // if (is_array($this->fields) && count($this->fields)) { + // return true; + // } + //} + return false; + } + + ///** + // * Summary of dropdown + // * @param mixed $options + // * @return mixed + // */ + //static function dropdown($options=array()) { + // global $CFG_GLPI; + // if (isset($options['value'])) { + // $that = new self; + // $that->getFromDB($options['value']); + // $options['value'] = $that->fields['taskcategories_id']; + // } + + // $options['url'] = $CFG_GLPI["root_doc"].'/plugins/processmaker/ajax/dropdownTaskcategories.php'; + // return Dropdown::show( 'TaskCategory', $options ); + + //} + + ///** + // * Execute the query to select ProcesssmakerTaskcategories + // * + // * @param $count true if execute an count(*), + // * @param $search pattern + // * + // * @return mysql result set. + // **/ + //static function getSqlSearchResult ($count=true, $search='') { + // global $DB, $CFG_GLPI; + + // $orderby = ''; + + // $where = ' WHERE glpi_plugin_processmaker_taskcategories.is_active=1 '; + + // $join = ' LEFT JOIN glpi_taskcategories ON glpi_taskcategories.id = glpi_plugin_processmaker_taskcategories.taskcategories_id'; + + // if ($count) { + // $fields = " COUNT(DISTINCT glpi_plugin_processmaker_taskcategories.id) AS cpt "; + // } else { + // $fields = " DISTINCT glpi_taskcategories.id, glpi_taskcategories.completename AS name "; + // $orderby = " ORDER BY glpi_taskcategories.completename ASC"; + // } + + // if (strlen($search)>0 && $search!=$CFG_GLPI["ajax_wildcard"]) { + // $where .= " AND (glpi_taskcategories.completename $search + // OR glpi_taskcategories.comment $search) "; + // } + + // $query = "SELECT $fields FROM glpi_plugin_processmaker_taskcategories $join ".$where." ".$orderby.";"; + + // return $DB->query($query); + //} + + +} diff --git a/inc/user.class.php b/inc/user.class.php index dda13e0..57483fa 100644 --- a/inc/user.class.php +++ b/inc/user.class.php @@ -1,354 +1,333 @@ - 'GROUP_USER.USR_UID AS pm_user_id', + 'FROM' => 'TASK_USER', + 'INNER JOIN' => [ + 'GROUP_USER' => [ + 'FKEY' => [ + 'GROUP_USER' => 'GRP_UID', + 'TASK_USER' => 'USR_UID', + ['AND' => [ + 'TASK_USER.TU_RELATION' => 2, + 'TASK_USER.TU_TYPE' => $tu_type + ] + ] + ] + ] + ], + 'WHERE' => [ + 'TAS_UID' => $tags['taskGuid'], + ] + ]); + $res2 = new QuerySubQuery([ + 'SELECT' => 'TASK_USER.USR_UID AS pm_user_id', + 'FROM' => 'TASK_USER', + 'WHERE' => [ + 'AND' => [ + 'TAS_UID' => $tags['taskGuid'], + 'TASK_USER.TU_RELATION' => 1, + 'TASK_USER.TU_TYPE' => $tu_type + ] + ] + ]); + + $subqueries = [$res1, $res2]; + + if ($tags['grpGuid'] != 0) { + // then add the user for the selfservice value based assignement + $res3 = new QuerySubQuery([ + 'SELECT' => 'GROUP_USER.USR_UID AS pm_user_id', + 'FROM' => 'GROUP_USER', + 'WHERE' => ['GROUP_USER.GRP_UID' => $tags['grpGuid']] + + ]); + + $subqueries[] = $res3; + } + + $union = new QueryUnion($subqueries); + + $res = $PM_DB->request([ + 'FROM' => $union + ]); + $pmUsers = [ ]; + foreach ($res as $pmUser) { + $pmUsers[ ] = $pmUser[ 'pm_user_id' ]; + } + + $joinprofile = false; + + switch ($right) { + case "id" : + $used[] = Session::getLoginUserID(); + $query['WHERE']['AND']['glpi_users.id'] = Session::getLoginUserID(); + break; + + case "all" : + $query['WHERE']['AND']['glpi_users.id'] = ['>', 0]; + break; + } + + $query['WHERE']['AND']['glpi_plugin_processmaker_users.pm_users_id'] = $pmUsers; + $query['WHERE']['AND']['glpi_users.is_deleted'] = 0; + $query['WHERE']['AND']['glpi_users.is_active'] = 1; + + if ((is_numeric($value) && $value) + || count($used)) { + + if (is_numeric($value)) { + $used[] = $value; + } + } + + if ($count) { + $query['FIELDS'] = 'glpi_users.id'; + $query['COUNT'] = 'cpt'; + $query['DISTINCT'] = true; + + } else { + $query['FIELDS'] = ['glpi_users.id', 'glpi_users.realname', 'glpi_users.firstname', 'glpi_users.name', 'glpi_useremails.email']; + $query['DISTINCT'] = true; + + } + $query['FROM'] = 'glpi_plugin_processmaker_users'; + $query['FROM'] = 'glpi_plugin_processmaker_users'; + $query['INNER JOIN'] = [ + 'glpi_users' => [ + 'FKEY' => [ + 'glpi_users' => 'id', + 'glpi_plugin_processmaker_users' => 'id' + ] + ] + ]; + + $query['LEFT JOIN'] = [ + 'glpi_useremails' => [ + 'FKEY' => [ + 'glpi_users' => 'id', + 'glpi_useremails' => 'users_id', [ + 'AND' => [ + 'glpi_useremails.is_default' => 1 + ] + ] + ] + ], + 'glpi_profiles_users' => [ + 'FKEY' => [ + 'glpi_users' => 'id', + 'glpi_profiles_users' => 'users_id' + ] + ] + ]; + + if ($joinprofile) { + $query['LEFT JOIN'] = [ + 'glpi_profiles' => [ + 'FKEY' => [ + 'glpi_profiles' => 'id', + 'glpi_profiles_user' => 'profiles_id' + ] + ] + ]; + } + + if ($count) { + $query['WHERE']['AND']['NOT']['glpi_users.id'] = $used; + } else { + if (strlen($search)>0 && $search!=$CFG_GLPI["ajax_wildcard"]) { + $txt_search = Search::makeTextSearchValue($search); -/** - * user short summary. - * - * user description. - * - * @version 2.0 - * @author MoronO - */ -class PluginProcessmakerUser extends CommonDBTM { - - - /** - * Execute the query to select box with all glpi users where select key = name - * - * Internaly used by showGroup_Users, dropdownUsers and ajax/dropdownUsers.php - * - * @param $count true if execute an count(*), - * @param $right limit user who have specific right - * @param $entity_restrict Restrict to a defined entity - * @param $value default value - * @param $used array: Already used items ID: not to display in dropdown - * @param $search pattern - * - * @return DBmysqlIterator - **/ - static function getSqlSearchResult ($taskId, $count = true, $right = "all", $entity_restrict = -1, $value = 0, - $used = [], $search = '', $limit = '') { - global $DB, $PM_DB, $CFG_GLPI; - // first need to get all users from $taskId - $adhoc_users = Session::haveRight('plugin_processmaker_case', ADHOC_REASSIGN) ? 2 : -1; - // TU_TYPE in (1, 2) means 1 is normal, 2 is for adhoc - // TU_RELATION is 1 for user, and 2 for group - $res1 = new QuerySubQuery([ - 'SELECT' => 'GROUP_USER.USR_UID AS pm_user_id', - 'FROM' => 'TASK_USER', - 'INNER JOIN' => [ - 'GROUP_USER' => [ - 'FKEY' => [ - 'GROUP_USER' => 'GRP_UID', - 'TASK_USER' => 'USR_UID', - ['AND' => [ - 'TASK_USER.TU_RELATION' => 2, - 'TASK_USER.TU_TYPE' => [1, $adhoc_users] - ] - ] - ] - ] - ], - 'WHERE' => [ - 'TAS_UID' => $taskId, - ] - ]); - $res2 = new QuerySubQuery([ - 'SELECT' => 'TASK_USER.USR_UID AS pm_user_id', - 'FROM' => 'TASK_USER', - 'WHERE' => [ - 'AND' => [ - 'TAS_UID' => $taskId, - 'TASK_USER.TU_RELATION' => 1, - 'TASK_USER.TU_TYPE' => [1, $adhoc_users] - ] - ] - ]); - $union = new QueryUnion([$res1, $res2]); - $res = $PM_DB->request([ - 'FROM' => $union - ]); - //$db_pm = PluginProcessmakerConfig::getInstance()->getProcessMakerDB(); - //$pmQuery = "SELECT GROUP_USER.USR_UID AS pm_user_id FROM TASK_USER - // JOIN GROUP_USER ON GROUP_USER.GRP_UID=TASK_USER.USR_UID AND TASK_USER.TU_RELATION = 2 AND TASK_USER.TU_TYPE=1 - // WHERE TAS_UID = '$taskId' - // UNION - // SELECT TASK_USER.USR_UID AS pm_user_id FROM TASK_USER - // WHERE TAS_UID = '$taskId' AND TASK_USER.TU_RELATION = 1 AND TASK_USER.TU_TYPE=1 ; "; - $pmUsers = [ ]; - //foreach ($PM_DB->request( $pmQuery ) as $pmUser) { - foreach ($res as $pmUser) { - $pmUsers[ ] = $pmUser[ 'pm_user_id' ]; - } - - //$where = ''; - $joinprofile = false; - - switch ($right) { - case "id" : - $used[] = Session::getLoginUserID(); - //$where = " `glpi_users`.`id` = '".Session::getLoginUserID()."' "; - $query2['WHERE']['AND']['glpi_users.id'] = Session::getLoginUserID(); - break; - - case "all" : - //$where = " `glpi_users`.`id` > '0' "; - $query2['WHERE']['AND']['glpi_users.id'] = ['>', 0]; - break; - } - - //$where .= " AND glpi_plugin_processmaker_users.pm_users_id IN ('".join("', '", $pmUsers)."') "; - - //$where .= " AND `glpi_users`.`is_deleted` = '0' - // AND `glpi_users`.`is_active` = '1' "; - - $query2['WHERE']['AND']['glpi_plugin_processmaker_users.pm_users_id'] = $pmUsers; - $query2['WHERE']['AND']['glpi_users.is_deleted'] = 0; - $query2['WHERE']['AND']['glpi_users.is_active'] = 1; - - if ((is_numeric($value) && $value) - || count($used)) { - - //$where .= " AND `glpi_users`.`id` NOT IN ("; - if (is_numeric($value)) { - //$first = false; - //$where .= $value; - $used[] = $value; - //$query2['WHERE']['AND']['NOT']['glpi_users.id'] = $value; - } else { - //$first = true; - } - //$query2['WHERE']['AND']['NOT']['glpi_users.id'] = $used; - //foreach ($used as $val) { - // if ($first) { - // $first = false; - // } else { - // $where .= ","; - // } - // $where .= $val; - //} - //$where .= ")"; - } - - if ($count) { - //$query = "SELECT COUNT(DISTINCT glpi_users.id ) AS cpt "; - $query2['SELECT'] = ['COUNT DISTINCT' => 'glpi_users.id AS cpt']; - - } else { - //$query = "SELECT DISTINCT glpi_users.id , `glpi_users`.`realname`, `glpi_users`.`firstname`, `glpi_users`.`name`, `glpi_useremails`.`email` "; - $query2['SELECT DISTINCT'] = 'glpi_users.id'; - $query2['FIELDS'] = ['glpi_users.realname', 'glpi_users.firstname', 'glpi_users.name', 'glpi_useremails.email']; - } - $query2['FROM'] = 'glpi_plugin_processmaker_users'; - //$query .= "FROM glpi_plugin_processmaker_users - // JOIN glpi_users ON glpi_users.id=glpi_plugin_processmaker_users.id "; - $query2['FROM'] = 'glpi_plugin_processmaker_users'; - $query2['INNER JOIN'] = [ - 'glpi_users' => [ - 'FKEY' => [ - 'glpi_users' => 'id', - 'glpi_plugin_processmaker_users' => 'id' - ] - ] - ]; - - //$query .= " LEFT JOIN `glpi_useremails` - // ON (`glpi_users`.`id` = `glpi_useremails`.`users_id` AND `glpi_useremails`.is_default = 1)"; - $query2['LEFT JOIN'] = [ - 'glpi_useremails' => [ - 'FKEY' => [ - 'glpi_users' => 'id', - 'glpi_useremails' => 'users_id', [ - 'AND' => [ - 'glpi_useremails.is_default' => 1 - ] - ] - ] - ], - 'glpi_profiles_users' => [ - 'FKEY' => [ - 'glpi_users' => 'id', - 'glpi_profiles_users' => 'users_id' - ] - ] - ]; - //$query .= " LEFT JOIN `glpi_profiles_users` - // ON (`glpi_users`.`id` = `glpi_profiles_users`.`users_id`)"; - - if ($joinprofile) { - $query2['LEFT JOIN'] = [ - 'glpi_profiles' => [ - 'FKEY' => [ - 'glpi_profiles' => 'id', - 'glpi_profiles_user' => 'profiles_id' - ] - ] - ]; - //$query .= " LEFT JOIN `glpi_profiles` - // ON (`glpi_profiles`.`id` = `glpi_profiles_users`.`profiles_id`) "; - } - - if ($count) { - $query2['WHERE']['AND']['NOT']['glpi_users.id'] = $used; - //$query .= " WHERE $where "; - } else { - if (strlen($search)>0 && $search!=$CFG_GLPI["ajax_wildcard"]) { - $query2['WHERE']['AND'] = [ - 'glpi_users.name' => ['LIKE',Search::makeTextSearchValue($search)], - 'OR' => [ - 'glpi_users.realname' => ['LIKE',Search::makeTextSearchValue($search)], - 'glpi_users.firstname' => ['LIKE',Search::makeTextSearchValue($search)], - 'glpi_users.phone' => ['LIKE',Search::makeTextSearchValue($search)], - 'glpi_useremails.email' => ['LIKE',Search::makeTextSearchValue($search)], - 'RAW' => [ - "CONCAT(`glpi_users`.`realname`,' ',`glpi_users`.`firstname`)".Search::makeTextSearch($search) - ] - ] - ]; - //$where .= " AND (`glpi_users`.`name` ".Search::makeTextSearch($search)." - // OR `glpi_users`.`realname` ".Search::makeTextSearch($search)." - // OR `glpi_users`.`firstname` ".Search::makeTextSearch($search)." - // OR `glpi_users`.`phone` ".Search::makeTextSearch($search)." - // OR `glpi_useremails`.`email` ".Search::makeTextSearch($search)." - // OR CONCAT(`glpi_users`.`realname`,' ',`glpi_users`.`firstname`) ". - // Search::makeTextSearch($search).")"; - } - $query2['WHERE']['AND']['NOT']['glpi_users.id'] = $used; - //$query .= " WHERE $where "; - - if ($_SESSION["glpinames_format"] == User::FIRSTNAME_BEFORE) { - //$query.=" ORDER BY `glpi_users`.`firstname`, - // `glpi_users`.`realname`, - // `glpi_users`.`name` "; - $query2['ORDER'] = ['glpi_users.firstname', 'glpi_users.realname', 'glpi_users.name']; - } else { - //$query.=" ORDER BY `glpi_users`.`realname`, - // `glpi_users`.`firstname`, - // `glpi_users`.`name` "; - $query2['ORDER'] = ['glpi_users.realname', 'glpi_users.firstname', 'glpi_users.name']; - } - - if ($search != $CFG_GLPI["ajax_wildcard"]) { - //$query .= " $limit"; - $query2['LIMIT'] = 200; - } - } - - return $DB->request($query2); - //return $DB->query($query); - } - - - /** - * Make a select box with all glpi users where select key = name - * - * Parameters which could be used in options array : - * - name : string / name of the select (default is users_id) - * - right : string / limit user who have specific right : - * id -> only current user (default case); - * interface -> central ; - * all -> all users ; - * specific right like show_all_ticket, create_ticket.... - * - comments : boolean / is the comments displayed near the dropdown (default true) - * - entity : integer or array / restrict to a defined entity or array of entities - * (default -1 : no restriction) - * - entity_sons : boolean / if entity restrict specified auto select its sons - * only available if entity is a single value not an array(default false) - * - all : Nobody or All display for none selected - * all=0 (default) -> Nobody - * all=1 -> All - * all=-1-> nothing - * - rand : integer / already computed rand value - * - toupdate : array / Update a specific item on select change on dropdown - * (need value_fieldname, to_update, url (see Ajax::updateItemOnSelectEvent for informations) - * and may have moreparams) - * - used : array / Already used items ID: not to display in dropdown (default empty) - * - on_change : string / value to transmit to "onChange" - * - * @param $options array of possible options - * - * @return int (print out an HTML select box) - **/ - static function dropdown($options = []) { - global $CFG_GLPI; - - $options['url'] = $CFG_GLPI["root_doc"].'/plugins/processmaker/ajax/dropdownUsers.php'; - return User::dropdown( $options ); - } - - - /** - * Summary of getGLPIUserId - * returns GLPI user ID from a Processmaker user ID - * @param string $pmUserId - * @return int GLPI user id, or 0 if not found - */ - public static function getGLPIUserId($pmUserId) { - $obj = new self; - if ($obj->getFromDBByRequest([ - 'WHERE' => [ - 'pm_users_id' => $pmUserId - ], - ])) { - return $obj->fields['id']; - } - - return 0; - } - - - /** - * Summary of getPMUserId - * returns processmaker user id for given GLPI user id - * @param int $glpi_userId id of user from GLPI database - * @return string which is the uid of user in Processmaker database, or false if not found - */ - public static function getPMUserId($glpiUserId) { - if (is_numeric($glpiUserId)) { - $obj = new self; - if ($obj->getFromDB($glpiUserId)) { - return $obj->fields['pm_users_id']; - } - } - return false; - } - - - /** - * Summary of getGlpiIdFromAny - * Returns the GLPI id of the user or false if not found - * Accept either PM GUID, GLPI logon, or GLPI ID - * @param $any - * @return mixed GLPI ID of the user or false if not found - */ - public static function getGlpiIdFromAny($any) { - $ret = self::getGLPIUserId($any); - if ($ret) { - return $ret; - } - $ret = self::getPMUserId($any); - if ($ret) { - return $any; - } - $usr = new User; - if ($usr->getFromDBbyName($any)) { - return $usr->getId(); - } - return false; - } - - - ///** - // * Summary of getNewPassword - // * @param mixed $username - // * @return string a new password computed - // * from uppercasing first letter of $username - // * and encoding - // * and adding a ramdon number (4 digits) - // * and truncating it to a length of 20 chars - // */ - //public static function getNewPassword( $username ) { - // $newPass = Toolbox::encrypt( ucfirst( stripslashes( $username ) ), GLPIKEY) ; - // return substr( rand(1000,9999).$newPass, 0, 19) ; - //} - -} + $firstname_field = $DB->quoteName(User::getTableField('firstname')); + $realname_field = $DB->quoteName(User::getTableField('realname')); + $fields = $_SESSION["glpinames_format"] == User::FIRSTNAME_BEFORE + ? [$firstname_field, $realname_field] + : [$realname_field, $firstname_field]; + $concat = new \QueryExpression( + 'CONCAT(' . implode(',' . $DB->quoteValue(' ') . ',', $fields) . ')' + . ' LIKE ' . $DB->quoteValue($txt_search) + ); + $query['WHERE']['AND'] = [ + 'glpi_users.name' => ['LIKE', $txt_search], + 'OR' => [ + 'glpi_users.realname' => ['LIKE', $txt_search], + 'glpi_users.firstname' => ['LIKE', $txt_search], + 'glpi_users.phone' => ['LIKE', $txt_search], + 'glpi_useremails.email' => ['LIKE', $txt_search], + $concat + ] + ]; + } + $query['WHERE']['AND']['NOT']['glpi_users.id'] = $used; + + if ($_SESSION["glpinames_format"] == User::FIRSTNAME_BEFORE) { + $query['ORDER'] = ['glpi_users.firstname', 'glpi_users.realname', 'glpi_users.name']; + } else { + $query['ORDER'] = ['glpi_users.realname', 'glpi_users.firstname', 'glpi_users.name']; + } + + if ($search != $CFG_GLPI["ajax_wildcard"]) { + $query['LIMIT'] = $limit; + $query['START'] = $start; + } + } + + return $DB->request($query); + } + + + /** + * Make a select box with all glpi users where select key = name + * + * Parameters which could be used in options array : + * - name : string / name of the select (default is users_id) + * - right : string / limit user who have specific right : + * id -> only current user (default case); + * interface -> central ; + * all -> all users ; + * specific right like show_all_ticket, create_ticket.... + * - comments : boolean / is the comments displayed near the dropdown (default true) + * - entity : integer or array / restrict to a defined entity or array of entities + * (default -1 : no restriction) + * - entity_sons : boolean / if entity restrict specified auto select its sons + * only available if entity is a single value not an array(default false) + * - all : Nobody or All display for none selected + * all=0 (default) -> Nobody + * all=1 -> All + * all=-1-> nothing + * - rand : integer / already computed rand value + * - toupdate : array / Update a specific item on select change on dropdown + * (need value_fieldname, to_update, url (see Ajax::updateItemOnSelectEvent for informations) + * and may have moreparams) + * - used : array / Already used items ID: not to display in dropdown (default empty) + * - on_change : string / value to transmit to "onChange" + * + * @param $options array of possible options + * + * @return int (print out an HTML select box) + **/ + static function dropdown($options = []) { + global $CFG_GLPI; + + $options['url'] = $CFG_GLPI["root_doc"].'/plugins/processmaker/ajax/dropdownUsers.php'; + return User::dropdown( $options ); + } + + + /** + * Summary of getGLPIUserId + * returns GLPI user ID from a Processmaker user ID + * @param string $pmUserId + * @return int GLPI user id, or 0 if not found + */ + public static function getGLPIUserId($pmUserId) { + $obj = new self; + if ($obj->getFromDBByRequest([ + 'WHERE' => [ + 'pm_users_id' => $pmUserId + ], + ])) { + return $obj->fields['id']; + } + + return 0; + } + + + /** + * Summary of getPMUserId + * returns processmaker user id for given GLPI user id + * @param int $glpi_userId id of user from GLPI database + * @return string which is the uid of user in Processmaker database, or false if not found + */ + public static function getPMUserId($glpiUserId) { + if (is_numeric($glpiUserId)) { + $obj = new self; + if ($obj->getFromDB($glpiUserId)) { + return $obj->fields['pm_users_id']; + } + } + return false; + } + + + /** + * Summary of getGlpiIdFromAny + * Returns the GLPI id of the user or false if not found + * Accept either PM GUID, GLPI logon, or GLPI ID + * @param $any + * @return mixed GLPI ID of the user or false if not found + */ + public static function getGlpiIdFromAny($any) { + $ret = self::getGLPIUserId($any); + if ($ret) { + return $ret; + } + $ret = self::getPMUserId($any); + if ($ret) { + return $any; + } + $usr = new User; + if ($usr->getFromDBbyName($any)) { + return $usr->getId(); + } + return false; + } + + + ///** + // * Summary of getNewPassword + // * @param mixed $username + // * @return string a new password computed + // * from uppercasing first letter of $username + // * and encoding + // * and adding a ramdon number (4 digits) + // * and truncating it to a length of 20 chars + // */ + //public static function getNewPassword( $username ) { + // $newPass = Toolbox::encrypt( ucfirst( stripslashes( $username ) ), GLPIKEY) ; + // return substr( rand(1000,9999).$newPass, 0, 19) ; + //} + +} diff --git a/install/mysql/processmaker-empty.sql b/install/mysql/processmaker-empty.sql index 3e8dd8d..5816a38 100644 --- a/install/mysql/processmaker-empty.sql +++ b/install/mysql/processmaker-empty.sql @@ -1,190 +1,190 @@ -/*!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://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, - `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', - `ssl_verify` tinyint(1) NOT NULL DEFAULT '0', - `db_version` varchar(10) NOT NULL DEFAULT '3.4.10', - `max_cases_per_item` int(11) 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, - `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', - `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; - - --- 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 @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://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, + `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', + `ssl_verify` tinyint(1) NOT NULL DEFAULT '0', + `db_version` varchar(10) NOT NULL DEFAULT '4.0.0', + `max_cases_per_item` int(11) 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, + `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', + `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; + + +-- 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 */; \ No newline at end of file diff --git a/install/update.php b/install/update.php index 78b4c60..3d90099 100644 --- a/install/update.php +++ b/install/update.php @@ -1,60 +1,64 @@ -fieldExists("glpi_plugin_processmaker_configs", "db_version" )) { - $current_version = '2.4.1'; - } else { - 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) { - case '2.4.1' : - // will upgrade any old versions (< 3.2.8) to 3.2.8 - include_once(GLPI_ROOT."/plugins/processmaker/install/update_to_3_2_8.php"); - $new_version = update_to_3_2_8(); - - case '3.2.8' : - // will upgrade 3.2.8 to 3.2.9 - include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_2_8_to_3_2_9.php"); - $new_version = update_3_2_8_to_3_2_9(); - - case '3.2.9' : - // will upgrade 3.2.9 to 3.3.0 - include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_2_9_to_3_3_0.php"); - $new_version = update_3_2_9_to_3_3_0(); - - case '3.3.0' : - // will upgrade 3.3.0 to 3.3.1 - include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_3_0_to_3_3_1.php"); - $new_version = update_3_3_0_to_3_3_1(); - case '3.3.1' : - // 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(); - case '3.4.9' : - // will upgrade 3.4.9 to 3.4.10 - include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_4_9_to_3_4_10.php"); - $new_version = update_3_4_9_to_3_4_10(); - } - - if (isset($new_version)) { - // end update by updating the db version number - $query = "UPDATE `glpi_plugin_processmaker_configs` SET `db_version` = '$new_version' WHERE `id` = 1;"; - - $DB->query($query) or die("error when updating db_version field in glpi_plugin_processmaker_configs" . $DB->error()); - } - -} +fieldExists("glpi_plugin_processmaker_configs", "db_version" )) { + $current_version = '2.4.1'; + } else { + 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) { + case '2.4.1' : + // will upgrade any old versions (< 3.2.8) to 3.2.8 + include_once(GLPI_ROOT."/plugins/processmaker/install/update_to_3_2_8.php"); + $new_version = update_to_3_2_8(); + + case '3.2.8' : + // will upgrade 3.2.8 to 3.2.9 + include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_2_8_to_3_2_9.php"); + $new_version = update_3_2_8_to_3_2_9(); + + case '3.2.9' : + // will upgrade 3.2.9 to 3.3.0 + include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_2_9_to_3_3_0.php"); + $new_version = update_3_2_9_to_3_3_0(); + + case '3.3.0' : + // will upgrade 3.3.0 to 3.3.1 + include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_3_0_to_3_3_1.php"); + $new_version = update_3_3_0_to_3_3_1(); + case '3.3.1' : + // 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(); + case '3.4.9' : + // will upgrade 3.4.9 to 3.4.10 + include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_4_9_to_3_4_10.php"); + $new_version = update_3_4_9_to_3_4_10(); + case '3.4.10' : + // will upgrade 3.4.10 to 4.0.0 + include_once(GLPI_ROOT."/plugins/processmaker/install/update_3_4_10_to_4_0_0.php"); + $new_version = update_3_4_10_to_4_0_0(); + } + + if (isset($new_version) && $new_version !== false) { + // end update by updating the db version number + $query = "UPDATE `glpi_plugin_processmaker_configs` SET `db_version` = '$new_version' WHERE `id` = 1;"; + + $DB->query($query) or die("error when updating db_version field in glpi_plugin_processmaker_configs" . $DB->error()); + } + +} diff --git a/install/update_3_4_10_to_4_0_0.php b/install/update_3_4_10_to_4_0_0.php new file mode 100644 index 0000000..3c4ec05 --- /dev/null +++ b/install/update_3_4_10_to_4_0_0.php @@ -0,0 +1,14 @@ +migratePasswords()) { + return '4.0.0'; + } + + return false; +} \ No newline at end of file diff --git a/locales/cs_CZ.mo b/locales/cs_CZ.mo index 92cf1ab66fb45ced87a0c988c01f7798f34511e8..dc1250480fed9bc8baba858eb6a423b9baf7ca39 100644 GIT binary patch delta 4114 zcmaKudvH|M9mh{X6r==5AY!P76A(zijoCm-c`1IHY|_Gt z55TE7(w*3$?Q}%j8TbQ+n%b!^&@L%6t*xcC*g8|&VrO(@WIF8(W9umWd^a}_AMKg_ z-Oulwd(ZFuUMFz8`Qp0l+vO#_hOr;H7TH>2%yaPjV|Xx|cNta1`F?eI+dAd@~niGz$yiRJa`St=a0Y zNBnswlq0(#Kl3OLIs6?chn|5t@EEl44CH6tQ0|%i3J_57YHYZRN z@hPYbyaum_??Oc|ZsI`drb2yJ59h(9{=5^eVZIxd!!uABc?(X1fA{Al z8Tr2sCBOpTm|LMd-wLNg2P*RYFaQrgrT9gteSd(8>|ap(FZ-N`7s^C6RCCUTvReng z3>QG{Yb_`LlTfy?AOmUt#luit`UF(d9EEl86jW(0LhT#HL;I#cIa&i1dBEoaSj~Jn zoC({Z_CM;s|3TJQjzF9@&q6iXX{b`X4i(A!P$l^XR7onZqSVfSs%ewYyP;~^3645<0$g97phiIL#6a6RLx$11a0zA9={0{!TS)~W-?aA zIZy{I;~@v{fpQ=Y70`oFb`L_?d%EzR`u`L~27U!qyT3s>bOEXdK7_hPWrW9>rV+}( z?NFs?hdQtmYX3vf!UIr|9)~)(AM!KjcyO`IKef*JrkKCGT9^d2VFpywEb_S(>Y&|l zHGIrpe*-o$zXX-38@Li;Bisycf(oD)&V$GO_vfL`y8yHD{38_Ay0mJbi&sEJvKs1| zY=F9c_xkJKg1Vl)P$l~rR7OrgYHEHDSHX{9D_lXR>YOK`N_Ygy?u*l?e>2J%7L@XF zma7OWq5fufLv`~(sO~@H&rd>SkirD>`Tw48jvo_x(Ja1>b{mYyx5EnpQ!1z8b0-<51u2gNpb#)WI)7HT7#y zj-7`Jq?pY&z_C!J$Sy#Uhqpj^7=iSY*#~ufeh5{H=iwFbER^9lVLki+D&=syyT;tCzY(WCZ&B#{}m09N(ypoFj!WhL9?^B`Ks1&Wo&$fRLg@D) z>h|5pPUIeBFA_(#ASq;U=yokeCL*rCI2x8oS5%F;nPdM{9!c9+BoTGO)^lyh&J3pe zJ{*DZVDNIKLOb82&AN`F@oN;wJ7wujP=O{UzWlky@?I`_xYCl*?-JL#D9 zDYxB8rwbEX!|pc6w(kffw&RWX`68B|HPVmscda_b0i%hKr&#P3a*+FD=mrk zNLVo|VNEEhP;59?Bflhcti(qyZFD*_PWpfCz0+y4WWR4hd9cU^HacDS;U)sjBxR9p zsBZ`c>Kg*VMjM>JsG%|U_@on~=GQgkmQVgqIY;eu+Py$a^CCMhSRb4h%+*&cp460b z?+-^3fmM;1Q+O9_%pI<%=-XBCO3~Ey{fF|$lA*BOIZ!$*By76SD@&&I6j!%KQ~8%Y zd-_2BSUTp~r2lz_eoBPG$w)f)TxHAV7Bx|Hpot;{LpB|XyKY-Lmgzs4$RD*Sw`WHx zl*k{mHAy$&wC~6tW)imvr>i>|OPu~5AMKzoGGWKElE`>&ZQsY0MMcv$$3kf@;ikQa zPV7Gv>Tw3X9rC5`#3=lk3P$o5xT93(!u$cZ9IS2wkejLIH&O=8aLB}w{A2O z#t}Ieih7y+;TUS|v)9fk&idh+=KQgkaxj#D&*$q4zUeU|oDcgZh;qntlmBkirTxF~ z9cT8#_`sv!y+Aw}mZE8)JR6w>k`iG7@etu3dE0WvYFXY}pGFPn3k;)wGfrh8C$6G8x*fPcXEfA~;h=$}p&raZZZV~(0ac+o+=OoIK;1Wt zrFZ~W;FqYRPGb;;a#KA0n{X;#Ohcuv4%NYCYa3?M?m||_96-(dAkM{iaS0wpJ$D(^ z(Ku?!t|EP!KT#9CgG(`)i$3b6l8RDPjk>W7H()o$;wjWjKgV<&v+XHV%BNA!MYDdX zn2OQ35;ee$xEMF1COCxo`22kGuhbpmgdV(zn!zuq7u>L_p&7@ZHd_+vzBJTk%0*3} z3JY)xYSRv59KM76nUfqefD5PzeHKmrRr#6|8TdUe!#k)KEMa=OUS?f`n(;;s+7m6P zly;&9xCfQmmr{>D9?J~TqK(&4vTRyYG%#WF60sOqIEy! z(LREU@QOWu12q8`)6ZbjB%%gd#%MI4Mh;o%+et+uc>|T&L&)UKVbt24LZ$FL@=h~` zIrtlDU@?4SG7B}ZN>sVpXvfm zp_XJCHS-Xrp*358_v318#9>qi6R0J+j>@Eq-}6?CLXv2@QJZfsYLo6mpHBFxXr^aT z9bdw9yn@Qiq`e-&H>wAdQ8TE-b+`ug)eNKVKaN`ai>Qf>VIls6>Mt&B=J`cwtiMv^ z<^+Gn!-0EDEmmL`R^fZ77hFRxrZYNyZuOXn&8QA{V>Z5u8qg@RDrN$8-!0TcQ{6L5 zljru$?B11};F_sNjj$J&<1SQ652FTl8cBxv7PZT#P^k@P<7hw`sDWf5t6)lSJvN~B z#6i?&K7#7!xX)e~#d|n$4)s%c8;C7@Wb_A|1@Wcz5u0ifMDaB#|RZIPi~-Q%;VT@>-zL&OP{SMWBOv0(b>{M zWhL2d_RMrr|gg&ckLZz9|ZdNHHv>#ZNz6JWCW4t;8xqrGV&ny5^1hTOxmO zISo-OoC{H3IY;O3^AAOzaruX1-*P!s@zws&gfdr6Q+`!nd)q)~Pj~*>wt@BvccI5y zmha)O#O*DvC@ReJ6nZ=nb+!2o?Sq~D|94+;QQ$tOCGkYCx4`SfB>nAVCwrU=$+7+y zlFz&RTNmyMa&Dz;7}=ld3ajhu+1}o7oR2f(oNv;8_eZ*Og8XL}zZT^DlbPV`Ube;G Iks0Rt7u|~qw*UYD diff --git a/locales/cs_CZ.po b/locales/cs_CZ.po index ac47e53..60efb1b 100644 --- a/locales/cs_CZ.po +++ b/locales/cs_CZ.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: processmaker-plugin\n" "POT-Creation-Date: 2018-08-06 14:32+0200\n" -"PO-Revision-Date: 2018-08-06 14:43+0200\n" +"PO-Revision-Date: 2021-02-15 14:25\n" "Last-Translator: tomolimo\n" "Language-Team: Czech\n" "Language: cs_CZ\n" @@ -12,11 +12,7 @@ msgstr "" "X-Generator: Poedit 2.1.1\n" "X-Poedit-Basepath: ..\n" "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n" -"X-Poedit-KeywordsList: ;__:1,2t;_e:1,2t;_x:1c,2,3t;_n:1,2,4t;__s:1,2t;" -"_ex:1c,2,3t;_sx:1c,2,3t;_nx:1c,2,3,5t\n" -"X-Crowdin-Project: processmaker-plugin\n" -"X-Crowdin-Language: cs\n" -"X-Crowdin-File: /3.3.0/source.po\n" +"X-Poedit-KeywordsList: ;__:1,2t;_e:1,2t;_x:1c,2,3t;_n:1,2,4t;__s:1,2t;_ex:1c,2,3t;_sx:1c,2,3t;_nx:1c,2,3,5t\n" "X-Poedit-SearchPath-0: ajax\n" "X-Poedit-SearchPath-1: front\n" "X-Poedit-SearchPath-2: inc\n" @@ -24,75 +20,80 @@ msgstr "" "X-Poedit-SearchPath-4: js\n" "X-Poedit-SearchPath-5: hook.php\n" "X-Poedit-SearchPath-6: setup.php\n" +"X-Crowdin-Project: processmaker-plugin\n" +"X-Crowdin-Project-ID: 310131\n" +"X-Crowdin-Language: cs\n" +"X-Crowdin-File: /3.3.0/source.po\n" +"X-Crowdin-File-ID: 15\n" -#: ajax/task_users.php:25 +#: ajax/task_users.php:25 msgid "Re-assign task to" msgstr "Úkol předat" -#: ajax/task_users.php:45 +#: ajax/task_users.php:45 msgid "Re-assign" msgstr "Předat" -#: front/case.form.php:35 +#: front/case.form.php:35 msgid "Case has been deleted!" msgstr "Případ byl smazán!" -#: front/case.form.php:37 +#: front/case.form.php:37 msgid "Unable to delete case!" msgstr "Případ se nedaří smazat!" -#: front/case.form.php:50 +#: front/case.form.php:50 msgid "Case has been cancelled!" msgstr "Případ byl zrušen!" -#: front/case.form.php:52 front/case.form.php:55 +#: front/case.form.php:52 front/case.form.php:55 msgid "Unable to cancel case!" msgstr "Případ se nedaří zrušit!" -#: front/case.form.php:76 front/case.form.php:78 inc/case.class.php:1018 +#: front/case.form.php:76 front/case.form.php:78 inc/case.class.php:1018 msgid "Process cases" msgstr "Případy procesu" -#: front/case.php:5 front/caselink.form.php:27 front/caselink.php:5 -#: front/process.form.php:25 front/process.php:5 inc/caselink.class.php:143 -#: inc/config.class.php:50 inc/config.class.php:354 inc/process.class.php:393 -#: inc/profile.class.php:52 inc/profile.class.php:83 +#: front/case.php:5 front/caselink.form.php:27 front/caselink.php:5 +#: front/process.form.php:25 front/process.php:5 inc/caselink.class.php:143 +#: inc/config.class.php:50 inc/config.class.php:354 inc/process.class.php:393 +#: inc/profile.class.php:52 inc/profile.class.php:83 msgid "ProcessMaker" msgstr "ProcessMaker" -#: front/processmaker.form.php:85 +#: front/processmaker.form.php:85 msgid "Task re-assigned!" msgstr "Úkol předán!" -#: front/processmaker.form.php:87 +#: front/processmaker.form.php:87 msgid "Error re-assigning task: " msgstr "Chyba při předávání úkolu: " -#: front/processmaker.form.php:90 +#: front/processmaker.form.php:90 msgid "Task already assigned to this person!" msgstr "Úkol už je této osobě přiřazen!" -#: front/processmaker.helpdesk.form.php:21 +#: front/processmaker.helpdesk.form.php:21 msgid "Process - Case" msgstr "Proces – případ" -#: front/processmaker.helpdesk.form.php:24 inc/case.class.php:605 +#: front/processmaker.helpdesk.form.php:24 inc/case.class.php:605 msgid "Select the process you want to add" msgstr "Vyberte proces který chcete přidat" -#: hook.php:31 inc/taskcategory.class.php:98 +#: hook.php:31 inc/taskcategory.class.php:98 msgid "Synchronize Task List" msgstr "Synchronizovat seznam úkolů" -#: hook.php:158 inc/case.class.php:77 +#: hook.php:158 inc/case.class.php:77 msgid "Case" msgstr "Případ" -#: hook.php:158 inc/case.class.php:586 inc/case.class.php:1062 +#: hook.php:158 inc/case.class.php:586 inc/case.class.php:1062 msgid "Status" msgstr "Stav" -#: inc/case.class.php:23 inc/case.class.php:90 inc/case.class.php:92 +#: inc/case.class.php:23 inc/case.class.php:90 inc/case.class.php:92 msgid "Process case" msgid_plural "Process cases" msgstr[0] "Případ procesu" @@ -100,465 +101,462 @@ msgstr[1] "Případy procesu" msgstr[2] "Případy procesu" msgstr[3] "Případy procesu" -#: inc/case.class.php:80 +#: inc/case.class.php:80 msgid "Sub-case" -msgstr "" +msgstr "Dílčí případ" -#: inc/case.class.php:312 +#: inc/case.class.php:312 msgid "Current task(s) properties" msgstr "Vlastnosti stávajícího úkolu" -#: inc/case.class.php:316 inc/task.class.php:263 +#: inc/case.class.php:316 inc/task.class.php:263 msgid "Task" msgstr "Úkol" -#: inc/case.class.php:317 inc/task.class.php:264 +#: inc/case.class.php:317 inc/task.class.php:264 msgid "Task guid" msgstr "Nikde se neopakující identif. úkolu" -#: inc/case.class.php:318 inc/task.class.php:265 +#: inc/case.class.php:318 inc/task.class.php:265 msgid "Current user" msgstr "Stávající uživatel" -#: inc/case.class.php:319 inc/task.class.php:266 +#: inc/case.class.php:319 inc/task.class.php:266 msgid "Task delegation date" msgstr "Datum delegování úkolu" -#: inc/case.class.php:341 inc/task.class.php:275 +#: inc/case.class.php:341 inc/task.class.php:275 msgid "To be claimed" msgstr "Chcete-li uplatnit" -#: inc/case.class.php:377 +#: inc/case.class.php:377 msgid "Sub-case properties" -msgstr "" +msgstr "Vlastnosti dílčího případu" -#: inc/case.class.php:380 +#: inc/case.class.php:380 msgid "Parent case properties" -msgstr "" +msgstr "Vlastnosti nadřazeného případu" -#: inc/case.class.php:382 +#: inc/case.class.php:382 msgid "Case properties" msgstr "Vlastnosti případu" -#: inc/case.class.php:387 inc/case.class.php:584 inc/case.class.php:1036 -#: inc/process.class.php:548 +#: inc/case.class.php:387 inc/case.class.php:584 inc/case.class.php:1036 +#: inc/process.class.php:548 msgid "Process" msgstr "Proces" -#: inc/case.class.php:388 +#: inc/case.class.php:388 msgid "Case title" msgstr "Název případu" -#: inc/case.class.php:389 +#: inc/case.class.php:389 msgid "Case number" msgstr "Číslo případu" -#: inc/case.class.php:390 +#: inc/case.class.php:390 msgid "Case status" msgstr "Stav případu" -#: inc/case.class.php:391 +#: inc/case.class.php:391 msgid "Case guid" msgstr "Nikde se neopakující identif. případu" -#: inc/case.class.php:392 +#: inc/case.class.php:392 msgid "Creator" msgstr "Vytvořil" -#: inc/case.class.php:393 +#: inc/case.class.php:393 msgid "Creation date" msgstr "Datum vytvoření" -#: inc/case.class.php:394 +#: inc/case.class.php:394 msgid "Last update" msgstr "Poslední úprava" -#: inc/case.class.php:479 -#, php-format +#: inc/case.class.php:479 +#, php-format msgid "Case is linked to a %1s" -msgstr "" +msgstr "Případ je propojen s %1s" -#: inc/case.class.php:481 -#, php-format +#: inc/case.class.php:481 +#, php-format msgid "Sub-case is linked to a %1s" -msgstr "" +msgstr "Dílčí případ je propojen s %1s" -#: inc/case.class.php:506 +#: inc/case.class.php:506 msgid "Case cancellation" msgstr "Zrušení případu" -#: inc/case.class.php:507 +#: inc/case.class.php:507 msgid "Cancel case" msgstr "Zrušit případ" -#: inc/case.class.php:511 +#: inc/case.class.php:511 msgid "Confirm cancellation?" msgstr "Potvrdit zrušení?" -#: inc/case.class.php:511 inc/profile.class.php:23 +#: inc/case.class.php:511 inc/profile.class.php:23 msgid "Cancel" msgstr "Storno" -#: inc/case.class.php:532 +#: inc/case.class.php:532 msgid "Case deletion" msgstr "Mazání případu" -#: inc/case.class.php:533 +#: inc/case.class.php:533 msgid "Delete case" msgstr "Smazat případ" -#: inc/case.class.php:585 inc/case.class.php:1029 +#: inc/case.class.php:585 inc/case.class.php:1029 msgid "Title" msgstr "Titulek" -#: inc/case.class.php:587 inc/case.class.php:1070 +#: inc/case.class.php:587 inc/case.class.php:1070 msgid "Sub-case of" -msgstr "" +msgstr "Dílčí případ z" -#: inc/case.class.php:602 +#: inc/case.class.php:602 msgid "Add a new case" msgstr "Přidat nový případ" -#: inc/case.class.php:995 +#: inc/case.class.php:995 msgctxt "case_status" msgid "Draft" msgstr "Koncept" -#: inc/case.class.php:996 +#: inc/case.class.php:996 msgctxt "case_status" msgid "To do" msgstr "Dodělat" -#: inc/case.class.php:997 +#: inc/case.class.php:997 msgctxt "case_status" msgid "Completed" msgstr "Dokončeno" -#: inc/case.class.php:998 +#: inc/case.class.php:998 msgctxt "case_status" msgid "Cancelled" msgstr "Zrušeno" -#: inc/case.class.php:1022 +#: inc/case.class.php:1022 msgid "ID" msgstr "Identif." -#: inc/case.class.php:1049 +#: inc/case.class.php:1049 msgid "Item" msgstr "Položka" -#: inc/case.class.php:1056 +#: inc/case.class.php:1056 msgid "Item entity" msgstr "Entita položky" -#: inc/casechangelog.class.php:35 +#: inc/casechangelog.class.php:35 msgid "Change log" msgstr "Seznam změn" -#: inc/casedynaform.class.php:80 +#: inc/casedynaform.class.php:80 msgid "Dynaforms" msgstr "Dynamické formuláře" -#: inc/casehistory.class.php:35 +#: inc/casehistory.class.php:35 msgid "History" msgstr "Historie" -#: inc/caselink.class.php:51 +#: inc/caselink.class.php:51 msgid "Case-links" msgstr "Propojení případů" -#: inc/caselink.class.php:53 +#: inc/caselink.class.php:53 msgid "Case-link" msgstr "Propojení případu" -#: inc/caselink.class.php:75 inc/caselink.class.php:165 +#: inc/caselink.class.php:75 inc/caselink.class.php:165 msgid "External data" msgstr "Externí data" -#: inc/caselink.class.php:80 inc/caselink.class.php:171 +#: inc/caselink.class.php:80 inc/caselink.class.php:171 msgid "Self" msgstr "Samo" -#: inc/caselink.class.php:85 inc/caselink.class.php:189 +#: inc/caselink.class.php:85 inc/caselink.class.php:189 msgid "Source task GUID" msgstr "Nikde se neopakující identif. zdrojového úkolu" -#: inc/caselink.class.php:93 inc/caselink.class.php:195 +#: inc/caselink.class.php:93 inc/caselink.class.php:195 msgid "Target task GUID" msgstr "Nikde se neopakující identif. cílového úkolu" -#: inc/caselink.class.php:101 inc/caselink.class.php:207 +#: inc/caselink.class.php:101 inc/caselink.class.php:207 msgid "Target process GUID" msgstr "Nikde se neopakující identif. cílového procesu" -#: inc/caselink.class.php:110 inc/caselink.class.php:201 +#: inc/caselink.class.php:110 inc/caselink.class.php:201 msgid "Target dynaform GUID" msgstr "Nikde se neopakující identif. cílového dynamického formuláře" -#: inc/caselink.class.php:115 inc/caselink.class.php:213 +#: inc/caselink.class.php:115 inc/caselink.class.php:213 msgid "Source condition" msgstr "Stav zdroje" -#: inc/caselink.class.php:121 inc/caselink.class.php:177 +#: inc/caselink.class.php:121 inc/caselink.class.php:177 msgid "Claim target task" msgstr "Převzít cílový úkol" -#: inc/caselink.class.php:126 inc/caselink.class.php:183 +#: inc/caselink.class.php:126 inc/caselink.class.php:183 msgid "External application JSON config" msgstr "JSON nastavení externí aplikace" -#: inc/casemap.class.php:43 +#: inc/casemap.class.php:43 msgid "Map" msgstr "Mapa" -#: inc/config.class.php:41 +#: inc/config.class.php:41 msgid "ProcessMaker setup" msgstr "Nastavení ProcessMaker" -#: inc/config.class.php:159 +#: inc/config.class.php:159 msgid "Server URL (must be in same domain than GLPI)" msgstr "URL adresa serveru (je třeba, aby byla ze stejné domény jako GLPI)" -#: inc/config.class.php:164 +#: inc/config.class.php:164 msgid "Common domain with GLPI" msgstr "Společná doména s GLPI" -#: inc/config.class.php:193 +#: inc/config.class.php:193 msgid "None!" msgstr "Žádná!" -#: inc/config.class.php:202 +#: inc/config.class.php:202 msgid "Workspace Name" msgstr "Název pracovního prostoru" -#: inc/config.class.php:207 +#: inc/config.class.php:207 msgid "Server administrator name" msgstr "Uživatelské jméno správce serveru" -#: inc/config.class.php:212 +#: inc/config.class.php:212 msgid "Server administrator password" msgstr "Heslo správce serveru" -#: inc/config.class.php:218 inc/config.class.php:258 +#: inc/config.class.php:218 inc/config.class.php:258 msgid "Connection status" msgstr "Stav spojení" -#: inc/config.class.php:234 +#: inc/config.class.php:234 msgid "SQL server setup" msgstr "Nastavení SQL serveru" -#: inc/config.class.php:237 +#: inc/config.class.php:237 msgid "SQL server (MariaDB or MySQL)" msgstr "SQL server (MariaDB nebo MySQL)" -#: inc/config.class.php:242 +#: inc/config.class.php:242 msgid "Database name" msgstr "Název databáze" -#: inc/config.class.php:247 +#: inc/config.class.php:247 msgid "SQL user" msgstr "SQL uživatel" -#: inc/config.class.php:252 +#: inc/config.class.php:252 msgid "SQL password" msgstr "SQL heslo" -#: inc/config.class.php:269 +#: inc/config.class.php:269 msgid "Theme Name" msgstr "Název motivu vzhledu" -#: inc/config.class.php:275 +#: inc/config.class.php:275 msgid "Main Task Category (edit to change name)" msgstr "Hlavní kategorie úkolu (pro změnu názvu upravte)" -#: inc/config.class.php:282 +#: inc/config.class.php:282 msgid "Task Writer (edit to change name)" msgstr "Úkol zapsal (pro změnu jména upravte)" -#: inc/config.class.php:302 +#: inc/config.class.php:302 msgid "Group in ProcessMaker which will contain all GLPI users" msgstr "Skupina v ProcessMaker která bude obsahovat všechny uživatele z GLPI" -#: inc/config.class.php:331 +#: inc/config.class.php:331 msgid "Processmaker system information" msgstr "Systémové informace o Processmaker" -#: inc/config.class.php:334 inc/config.class.php:344 +#: inc/config.class.php:334 inc/config.class.php:344 msgid "Version" msgstr "Verze" -#: inc/config.class.php:335 +#: inc/config.class.php:335 msgid "Web server" msgstr "Webový server" -#: inc/config.class.php:336 +#: inc/config.class.php:336 msgid "Server name" msgstr "Název serveru" -#: inc/config.class.php:337 +#: inc/config.class.php:337 msgid "PHP version" msgstr "Verze PHP" -#: inc/config.class.php:338 +#: inc/config.class.php:338 msgid "DB version" msgstr "Verze databáze" -#: inc/config.class.php:339 +#: inc/config.class.php:339 msgid "DB server IP" msgstr "IP adresa webového serveru" -#: inc/config.class.php:340 +#: inc/config.class.php:340 msgid "DB name" msgstr "Název databáze" -#: inc/config.class.php:341 +#: inc/config.class.php:341 msgid "User browser" msgstr "Prohlížeč uživatele" -#: inc/config.class.php:342 +#: inc/config.class.php:342 msgid "User IP" msgstr "IP adresa uživatele" -#: inc/config.class.php:344 +#: inc/config.class.php:344 msgid "Not yet!" msgstr "Ještě ne!" -#: inc/process.class.php:350 +#: inc/process.class.php:350 msgid "Synchronize Process List" msgstr "Synchronizovat seznam procesů" -#: inc/process.class.php:427 inc/process.class.php:589 +#: inc/process.class.php:427 inc/process.class.php:589 msgid "Process GUID" msgstr "Nikde se neopakující identif. procesu" -#: inc/process.class.php:433 +#: inc/process.class.php:433 msgid "Process type" -msgstr "" +msgstr "Typ procesu" -#: inc/process.class.php:439 +#: inc/process.class.php:439 msgid "Hide case num. & title" -msgstr "" +msgstr "Skrýt číslo případu a nadpis" -#: inc/process.class.php:445 +#: inc/process.class.php:445 msgid "Insert Task Category" msgstr "Vložit kategorii úkolu" -#: inc/process.class.php:457 +#: inc/process.class.php:457 msgid "Ticket type (self-service)" msgstr "Typ požadavku (samoobslužné)" -#: inc/process.class.php:464 inc/process.class.php:609 +#: inc/process.class.php:464 inc/process.class.php:609 msgid "Visible in Incident for Central interface" -msgstr "" +msgstr "Viditelné v incidentu pro ústřední rozhraní" -#: inc/process.class.php:470 inc/process.class.php:614 +#: inc/process.class.php:470 inc/process.class.php:614 msgid "Visible in Request for Central interface" -msgstr "" +msgstr "Viditelné v požadavku pro ústřední rozhraní" -#: inc/process.class.php:476 inc/process.class.php:666 +#: inc/process.class.php:476 inc/process.class.php:666 msgid "Visible in Change" -msgstr "" +msgstr "Viditelné ve změně" -#: inc/process.class.php:482 inc/process.class.php:671 +#: inc/process.class.php:482 inc/process.class.php:671 msgid "Visible in Problem" -msgstr "" +msgstr "Viditelné v problému" -#: inc/process.class.php:519 +#: inc/process.class.php:519 msgctxt "process_type" msgid "Classic" msgstr "Klasický" -#: inc/process.class.php:520 +#: inc/process.class.php:520 msgctxt "process_type" msgid "BPMN" msgstr "BPMN" -#: inc/process.class.php:546 +#: inc/process.class.php:546 msgid "Processes" msgstr "Procesy" -#: inc/process.class.php:599 +#: inc/process.class.php:599 msgid "Hide case number and title in task descriptions" msgstr "V popisech úkolů skrýt číslo a titulek případu" -#: inc/process.class.php:604 +#: inc/process.class.php:604 msgid "Insert Task Category comments in Task Description" msgstr "Vložit komentáře kategorie úkolu do jeho popisu" -#: inc/process.class.php:619 +#: inc/process.class.php:619 msgid "ITIL Category for Self-service interface (left empty to disable)" -msgstr "" +msgstr "ITIL kategorie pro samoobslužné rozhraní (ponecháním nevyplněného bude vypnuto)" -#: inc/process.class.php:646 +#: inc/process.class.php:646 msgid "Type for Self-service interface" -msgstr "" +msgstr "Typ samoobslužného rozhraní" -#: inc/process.class.php:676 +#: inc/process.class.php:676 msgid "Process type (to be changed only if not up-to-date)" -msgstr "" +msgstr "Typ procesu (který má být změněno pouze pokud není aktuální)" -#: inc/process_profile.class.php:26 inc/process_profile.class.php:45 +#: inc/process_profile.class.php:26 inc/process_profile.class.php:45 msgid "Authorizations" msgstr "Oprávnění" -#: inc/process_profile.class.php:179 +#: inc/process_profile.class.php:179 msgid "Authorization not added: already existing!" msgstr "Oprávnění nepřidáno: už existuje!" -#: inc/processmaker.class.php:116 inc/processmaker.class.php:118 +#: inc/processmaker.class.php:116 inc/processmaker.class.php:118 msgctxt "errors" msgid "Error creating case!" msgstr "Chyba při vytváření případu!" -#: inc/processmaker.class.php:117 +#: inc/processmaker.class.php:117 msgctxt "errors" msgid "Can't create case: no rights for it!" msgstr "Případ se nedaří vytvořit: nedostatečná oprávnění!" -#: inc/processmaker.class.php:984 +#: inc/processmaker.class.php:984 msgid "Syncs GLPI users and groups into ProcessMaker." msgstr "Synchronizuje uživatele a skupiny z GLPI do ProcessMaker." -#: inc/processmaker.class.php:986 +#: inc/processmaker.class.php:986 msgid "Cleaning of orphan cases." msgstr "Čištění osiřelých případů." -#: inc/processmaker.class.php:986 +#: inc/processmaker.class.php:986 msgid "Number of days to keep orphan cases" msgstr "Po kolik dnů ponechávat osiřelé případy" -#: inc/processmaker.class.php:988 +#: inc/processmaker.class.php:988 msgid "To apply task actions between cases." msgstr "Pro uplatnění akcí úkolu mezi případy." -#: inc/processmaker.class.php:1696 +#: inc/processmaker.class.php:1696 msgid "Case title: " msgstr "Titulek případu: " -#: inc/processmaker.class.php:2178 +#: inc/processmaker.class.php:2178 msgid "A 'Case' is running!" msgstr "„Případ“ je v běhu!" -#: inc/processmaker.class.php:2179 +#: inc/processmaker.class.php:2179 msgid "You must manage it first (see 'Process - Case' tab)!" msgstr "Nejprve je třeba toto spravovat (viz panel „Proces – případ“)!" -#: inc/processmaker.class.php:3038 -msgid "" -"ProcessMaker plugin is under maintenance, please retry later, thank you." -msgstr "" -"Na zásuvném modulu ProcessMaker probíhá údržba, zkuste to prosím později – " -"děkujeme." +#: inc/processmaker.class.php:3038 +msgid "ProcessMaker plugin is under maintenance, please retry later, thank you." +msgstr "Na zásuvném modulu ProcessMaker probíhá údržba, zkuste to prosím později – děkujeme." -#: inc/profile.class.php:17 +#: inc/profile.class.php:17 msgid "Process configuration" msgstr "Nastavení procesu" -#: inc/profile.class.php:21 +#: inc/profile.class.php:21 msgid "Cases" msgstr "Případy" -#: inc/task.class.php:29 +#: inc/task.class.php:29 msgid "Process case task" msgid_plural "Process case tasks" msgstr[0] "Zpracovat úkoly případu" @@ -566,47 +564,48 @@ msgstr[1] "Process case tasks" msgstr[2] "Process case tasks" msgstr[3] "Process case tasks" -#: inc/task.class.php:258 +#: inc/task.class.php:258 msgid "Sub-case task(s)" -msgstr "" +msgstr "Úkoly dílčího případu" -#: inc/taskcategory.class.php:21 inc/taskcategory.class.php:31 +#: inc/taskcategory.class.php:21 inc/taskcategory.class.php:31 msgid "Task List" msgstr "Seznam úkolů" -#: inc/taskcategory.class.php:32 +#: inc/taskcategory.class.php:32 msgid "Task name" msgstr "Název úkolu" -#: inc/taskcategory.class.php:34 inc/taskcategory.class.php:60 +#: inc/taskcategory.class.php:34 inc/taskcategory.class.php:60 msgid "Start" msgstr "Spustit" -#: inc/taskcategory.class.php:35 +#: inc/taskcategory.class.php:35 msgid "Task GUID" msgstr "Nikde se neopakující identif. úkolu" -#: inc/taskcategory.class.php:38 inc/taskcategory.class.php:78 +#: inc/taskcategory.class.php:38 inc/taskcategory.class.php:78 msgid "Sub-process" msgstr "Dílčí proces" -#~ msgid "Case item" -#~ msgstr "Case item" +#~ msgid "Case item" +#~ msgstr "Case item" -#~ msgid "Subcase of" -#~ msgstr "Subcase of" +#~ msgid "Subcase of" +#~ msgstr "Subcase of" -#~ msgid "Project type" -#~ msgstr "Project type" +#~ msgid "Project type" +#~ msgstr "Project type" -#~ msgid "Hide case number and title" -#~ msgstr "Hide case number and title" +#~ msgid "Hide case number and title" +#~ msgstr "Hide case number and title" -#~ msgid "ITIL Category (self-service)" -#~ msgstr "ITIL Category (self-service)" +#~ msgid "ITIL Category (self-service)" +#~ msgstr "ITIL Category (self-service)" -#~ msgid "Project type (to be changed if not up-to-date)" -#~ msgstr "Project type (to be changed if not up-to-date)" +#~ msgid "Project type (to be changed if not up-to-date)" +#~ msgstr "Project type (to be changed if not up-to-date)" + +#~ msgid "Plugin is under maintenance, please retry later, thank you." +#~ msgstr "Plugin is under maintenance, please retry later, thank you." -#~ msgid "Plugin is under maintenance, please retry later, thank you." -#~ msgstr "Plugin is under maintenance, please retry later, thank you." diff --git a/locales/en_GB.mo b/locales/en_GB.mo index 3ded28a42a92916450bd02834ebd6543b6ce0b76..ecc00290f60d73a3d23b4ebafe30b552bc5105f2 100644 GIT binary patch literal 13391 zcmeI2dvG1qeaDyZGUg58*_0f)HIj_3tcMNw+6KREfn+O|Y`{>I)x9g-MfdJrcK6yA zl!Q`B8(yI%2}yw#NO?5SLIYEnh9+eiW|I6tn*LGBOhZW837w=3FipyI+I0H)p0oGr z3gk{^_$Qswj(+!Z-h0mP_dAb0qt{P6>a!ltbI3=K7mxP5ci=V0^TT6K_PjdmfH%WK z@DM!x6wmuGd<>oezXDH!-+?RO8+rWrQ(gYK@G{c-;4$z@5AWu)A+P^K& zzXzfM@BTdgFys~9Q}7)4RjBv<1Jt9t^qx_Zde5m*Bg&%^~!VS=evgaeP7k&-$=lz7A zet0CEm)=*yC9nu(kIhi+?Sksx6;S<}%=4>Ib~y-t6@ChK!N>FbzlBE<|3_%x8&LW@ zf==r_$HHHOr$E(T1@+$DkU#HQemY1RUaUj}!;Djqr!Af5j zK(%*K&K*#Cz6xr7O+dY83jPX=q3YcMrHA{V>OYyMzX<8F_YElhd_PZr7s`K*q!Ibg z095_$Q1!2d>VFlg{p+F1-2|nlL-2g~0F*!eO`iTn&L2VP>!(od9YZ16|12ndtbugF z+X6Md2`D=UPH?CYKlz!L1UMAX3SSNlHlj>&p6L<*5C`si$wA{V#EU5k!;0m}d zk5A|M`{8Az-wEYEuR_`LbtwD(2&$iNLFxSnjH-T~3}t5npXLCvqTaW2_wJM4$oKFcOWk7{Q&X`YjovzuW;-0YG{bBfzszbsP}vvYJCo&>fZ%b?@6d}Jr6ZM zUx8Ym--hbXh6~*KyaUS5ZimwA7og_vV-T10UV_rs525<`Qz*YVn#m$RI1kEh15ovM z-ziSRX8hHpao!!SlvJ5%s@cq>$U_vCySO3z=0$G{h$-t#r6`TY&3 zdjAZihqs~XAB7Vs{R}8QbwKH-n5U0Iih9>T`Oh6t^&f(&{~T2RUxsSuTTtcx9!f7i zhD;&vXHfq5kv^BcCg)}-eT~3V-~^QY>rnbQ1ZCd`p~m+Dl%2l{rKf*_EMeX|P~$xn z=T`c;Q2x}F^HP`+-wWkW--5Ew-$4Vv2QP%)fU9>ARJon-RJa%7>Rtt&1`ok5_$ah? zgC`Mx4bm0wUm&jHor5#2g4>|h=NqB)@@mfSLyhalIp2Y&5PuhHoJ*)IeHNhfya}pb z+u;##p-27IBRgtM2o&L=iXDT(4_X&ce~$bXauuTII;0cXh{#@t5Ivtk zzKF~s^7s9So(mA^Up|M+*{7f1TaXVUT6?ZRK7}-&8Ugv{v(1E@nhy^lg*<*2ycUtY zOUOQC6Y~4WZHVk9+l(Q4K8?tR!^j^Z%Md*k2k%eeb9wk~_@z8-a%$e*nTMZ(*CW4) zXkTHw_x>1(kOvSwGYksmjo`w09VV&?*s&uu_DkOz?) zkt*^e@;IVrr-Szl`~otBd;-~l+>AVd+=S?vLM}nZkvovzLGDG?B3C1N{s_@pS42)j zK8NU8?qJUm3SNoafSiszhMa_yk>5bhL40I2q9;TC0Qo$!8~GDN&xnKfNthtVBbOrs zh@Nwik0T#N^!zSz9I`|ao^8k=a=Rk=b89mIFGlV`QsfcjNJLKqxk7<;lb4M9>5TEy zG@Oota>u%rlb5WUOjh!9$!0$dibg5R(`K4VyR>D?(`BaOr)Dw;qE-VYi;Z%6n-z8k zei}#3W?C;yg2D%WXImR)Dv4|M#lL6=8d0HC^~2f+7&A>Y$I$kEKPtaZ8)iC*8}-BK zWTWYnsyj`Xnxqj$VKm+0Z7iD|amh5&ATh0hl1k$y3J#bOHN1_DtP&^T4Sp8Jk%{8W z_~mj?E*ig@1b%te1P8-3bM3VkO})*2)R~#q2uy}uJLXcYYFwh(8zkY>tm)k7e54jc znc3Z_1}PnmOjZd@J&8*}nwoMj6-J@@(yOLQK{bc#tp-U#8W2@x)ppyZl!I!Zip^MB zO2YbF!gM1nyR4SSHGa8^e3x<>AdpFD_z-wUT$-3$TiAu#gC=~ zQ;ny+&GJT6o=gXs)jTPIFK00El!=o%MXerFlpEJ-7`z&yqWOTQ-@RZ@XrboNv@Q-iSX#Ck|A?QUzsHtE!brGd^J{#!jQu+Yy%Kd(P^;=6vG} zI4>DzFq*#bjk@)ywy<#ts7!9W->)_T``XT{uDYtz_(|f=dLy#cyl$JWpd8|f zu_?J3B8Tg?1+yU1>Or`U9CTB{phXj^dtH6&8&Nf^5h-_jJL4$m;5Rd~K}Nt%c6Fre z&!%dACJ5^DCRbaTBtG!Iu8!^)ZTb1AZ>NiOsJ6K>Dr?F1G9FV4>*`IdMZD-8rbKf~ zvRh}DriSz8$zZOsTfa1)7_i+{x@pf%gC^|?rIo4?l_{k)B3D|Esk_c4L59Dw00&7A zOSm7+nAy0|+iIbJ1F=}=4V&$I@bzXyU9PqVeu&0)3n#GSF zmd^mMtGZwk)IvETF}qo?s+g`CiA!o4U*@GOI(PyXZ_oN*uQ%?_ALV@0b~8Uu%zHC0ZB8Y6 zJ=N)hZ_gSoti#xJ+gZaFu%|g2LQ&15YU?OXpR$UzdXRLuR@#cSj;uQ2**4e*GZ(VP zvuUlxwpFURxV91wBy17MVK$oaN`O=D)cIvREY0XdW*3XJZFlb`OXt6Fe4k?r`}*AA z^;MJ|(1(#6gA*Htw92?I4sTqI9sac7?a4n*S^+n)_eAzoiGtkW*EZfkp=Po>`Yw>1 zg!^^EP-i;KZoBw1^L$f_bq?s!{8#6h&ji}1PVc%(a)~>*mEtm=gUcIsdvZxNPW}G0 zQr!olw}*vAr$Ng}ZJ^Biz1sBca7%GjHqxwb-~ZXQS;k4(D*@E0lLdoXn(ko&T&W@im~O0sGl4yTVh28CIS?UGpYBaFgv$nY^hH@nh+Pm$)j;kNcpJZiGL z!$Z;k#~a!V(0b1Trf^>%*lwjg-?7#3-fmCcHsQWFj&h%a)u22-HLh_W;iNV%bxYz; zW%E*)J>}R7I44#)3YEfoh{aMb&<91Tw)vJV=_|&$c#-YfB;j<06RzwVa`el~=B{kN zf7ny(gz)l(Z9;SWs7<3IJLjkHWyYs(Nn7)E?0|)#av}GzqE>Ky`r1vp;En=IM|Tx= z2mA59I4W$RPen7(H_%_`8z}UzHvJbB2L~_c>+kDZs#9`dJn^HHgIJstag18b(KRL~ znr>jj!g%11dTRS+%fD-+fpE#Sl%`53JR3iQxLK$aJhX{oQNl z8n`@|wVyZI!ir|?#6+>bXCPZU5#&5r>@W2U^bC>|DXC`_p^3Cvsx3Qh3rEdx&uR^0 zGiws#D&)3Y*nsaVRv6k+G=u$p{e%5&Z8WVU^%qe8T(xas6?Ly1>|JFFZtq>wJFqgf zr-=JlvfD+}GH zwjFa8?-m#D7PXw%+rzmN!vEj9#rDsh=AEPc!sJ6#=bpuj#l?%o{Em@h%i_gi^Ai3r z*M_Zc-NlPVKDC<{XdLYqFBTUs78frT7cUm`|83B{%i_hN`>%(^i^au@#lzl2{?cD8 g&Rr(*j}Z9t<} zNq_fq-jCn!cYbH4zdK>oLjljd$j6YqtAgOi@asqN!_)jo5S$42!DHY7cs_i{=bwRx zlYa^F7re?3Lj-?>$HO<_(ePdPVR*z*L2xQO9-a)(ho``;kS4+P@K|Vlz6Dp4zZ3Eo ze32iG^RO>}6dp$Y`#%38sCl1;r@@z@#{UaE2_DK~RDT-Oy4LY?1iS>E4!1&@277&Z zvJ;FqBE`xI2aSD^Ow4pjg5Jda}$(nA-NU#^83w+zpK z7eVzKhaZKLQ2jGsem9hVJ^M0!03%ASLsH$d5SAC!I!gc|2MUp@t;=Z4Q`Q1jjf89I0XYWyc4TMC}_^}m5y*V|Bf z{}*)YKpC3nRH*VbK3{@bM+K_i5OjVBwVp|+`66iGT~O`51r@-!D90fwKP}pyJ1B4wdw94Agl!5h{M13Ds{a)cm7R z^VXp3S%=#1Ef5t1_d@yWqfqPrIh5XBg=+U#xBKqkcS8d;w}7k3revyHNIc8M1}o_fYnH&+}xI zCcBoP^m~ENZ-W~DO4tMULfPp6?1m3R&HF5rKl~DIgs(xZ^LU&{JOgSyYdqIMt*aku zU)MnCVGe2?O?U|0kLZ!lcRrsdbFnYD5^8PIyB>oKBeMHt$c2b(qer&Xv$lZq{Y!mX zxCXfzi4dLVeMtMsNodbwh;*!Ve+tolcOsh+`Aqw3KMdY)39ZK8x%?)*&|`GswA! z&c!sMXN&tS&Ok`|Ge|#j8*(G^N#p?1K(0qpr2U*lViTfso%q5dpw5q;3-q(qtQ`z9 zyVgXRNn3Fo#WP*O)>_SkCbsjYN?owEmCq(=baR+TNo?XIH({-2YZVjLQybP6jNKn) zdC{}8X%-BIan;s6iorA+1(_wQ%DNl1D5=@H)f`1`rWMtS)NGiUDQn|)7fYCNLo8Of zo{Poor5?p|wr28#jjZX{N|-TjHKuG@q?>8dv}qn$Uzg=!-ty@@%IkiSE?F_IPf3F= zrHaP<&W7=fHT7gB7_5g;!{lK)V{?$vx^6=$)g;pmf2tIh!Jm7;r>uZ1~_RW4y~tu(c9F?n~^V>-9#t6CX4 z*uKrgVZ(}KZ?dTw9#e)?CJSs2^Ki=P%(aqXWHD^FeIX8~leCcqLus0%Cbgw7%c2># zOYIqL4eifu8i#cgHk$)~8ESQB+lT_B9=n>aN@A+}K7lUyzg4qAZ-M+n!)J zrfqH}G)a4$6${x@qk*L|t;sdtzO<%bIJXV=V`viP3&BX3<)+niwjPx#md#+gZ7ss+ ziK!OODBJb~qhT}HmBhA--`p(NoP;|9^2S=Ykg3Oro$zSEby zp#o1+Vzc;0JG)~Kx@>2h*K}sGWmUyF>8y7p%Nup%oCCGeB5bs~doqHg7fCMRsu~4d>+9LWZgF0UfDgPrKU(Dp*VvPMase_|+q( z$#I)c(wfWo!`nR?rcucG#bZYoXw}nMTdY8R-Py;b2_>x8nN$Z(t2XnY;syb;#?W{@ zKQ1ur**#*q8!h|~eWH;J-)e^~?b)43<||r=nMS{ zmX$53K~vJ5AmjUxaw~9U*QOC3`2j(}wP@emMdU6n%6t~>aVKU8Z||;^Zq=ENOU4zt zYuTlo$y{pj4$u`mF>7&I-O7^=O5?t;@@pU)T9 zeP+2SX{3{^yVcf$2@UqakvZ5CD-yd{=w2|~t<}|0T)Zo^i#b5L`u2!ZX)+IkYy2g6 zO_W6%3#TtG`Jkg@IIeR2aAdTWK@utV-Qoq&*%G5ON~5!Ax82vWoT!!iUTdfPtsGpN zq;pwQH;z;2^_)|86dPe2^3p-j=VgI`x-)Cd+O~@p;dm`to$BcdbVMeLw}w^48(AGa zE-OtMM6~>UrQ6eRI$zcfOVpCU>fX;Z)Y{xs_2Pkbn4>~;HEA?6%cZ7`Mcg;OZSkt$ z+UjLUt-Av6;*)ZZRoli!cP%gBWs3KTsv_r&#H-S9t>g_;(fL)}axt`2MC#RJS51`M zYY>5>#QO{D8R+Z3xYWnrg{FUFWy8R_zJb0z8kTn3o3QN%wA;9$Xs0{3G?9jJMubn& z3O?0H>QN(EJ;EDb3;mZSY}lxnp?IbqWwX6zPt3uqnVsyB_qxSq6>jm#9otrq4v!8k z?V-Qix0=^F?i6N01&nX^=j)sJdAvy%S4!O8yl3L_(#1>dw3=y~mWJYLQe&Emxp*qd zS6^4!VPorJZpDlx?rmV8++XgerpT7Iq4Q>#&sI#iyn3w84O%Z*RbvlVMD zsF>L#nJYJEn=95|SRpj*E5614tB(task will be re-assigned to former " +"group):" +msgstr "" +"Please input reason to un-claim
(task will be re-assigned to former " +"group):" + +#: ajax/task_users.php:127 +msgid "Un-claim" +msgstr "Un-claim" + +#: ajax/task_users.php:130 +msgid "Can't un-assign task!" +msgstr "Can't un-assign task!" + +#: ajax/task_users.php:134 +msgid "Please input reason to re-assign:" +msgstr "Please input reason to re-assign:" + +#: ajax/task_users.php:145 +msgid "Send reminder" +msgstr "Send reminder" + +#: front/case.form.php:32 msgid "Case has been deleted!" msgstr "Case has been deleted!" -#: front/case.form.php:37 +#: front/case.form.php:34 msgid "Unable to delete case!" msgstr "Unable to delete case!" -#: front/case.form.php:50 +#: front/case.form.php:46 msgid "Case has been cancelled!" msgstr "Case has been cancelled!" -#: front/case.form.php:52 front/case.form.php:55 +#: front/case.form.php:48 front/case.form.php:51 msgid "Unable to cancel case!" msgstr "Unable to cancel case!" -#: front/case.form.php:76 front/case.form.php:78 inc/case.class.php:1018 +#: front/case.form.php:70 front/case.form.php:72 inc/case.class.php:1272 msgid "Process cases" msgstr "Process cases" -#: front/case.php:5 front/caselink.form.php:27 front/caselink.php:5 -#: front/process.form.php:25 front/process.php:5 inc/caselink.class.php:143 -#: inc/config.class.php:50 inc/config.class.php:354 inc/process.class.php:393 +#: front/case.php:5 front/caselink.form.php:29 front/caselink.php:5 +#: front/process.form.php:27 front/process.php:5 inc/caselink.class.php:158 +#: inc/config.class.php:50 inc/config.class.php:363 inc/process.class.php:409 #: inc/profile.class.php:52 inc/profile.class.php:83 msgid "ProcessMaker" msgstr "ProcessMaker" -#: front/processmaker.form.php:85 +#: front/processmaker.form.php:80 msgid "Task re-assigned!" msgstr "Task re-assigned!" -#: front/processmaker.form.php:87 +#: front/processmaker.form.php:82 msgid "Error re-assigning task: " msgstr "Error re-assigning task: " -#: front/processmaker.form.php:90 -msgid "Task already assigned to this person!" -msgstr "Task already assigned to this person!" +#: front/processmaker.form.php:93 +msgid "Task un-claimed!" +msgstr "Task un-claimed!" + +#: front/processmaker.form.php:95 +msgid "" +"Can't un-claim task! Verify 'Assignement Rules' in the process definition." +msgstr "" +"Can't un-claim task! Verify 'Assignement Rules' in the process definition." #: front/processmaker.helpdesk.form.php:21 msgid "Process - Case" msgstr "Process - Case" -#: front/processmaker.helpdesk.form.php:24 inc/case.class.php:605 +#: front/processmaker.helpdesk.form.php:24 inc/case.class.php:761 msgid "Select the process you want to add" msgstr "Select the process you want to add" -#: hook.php:31 inc/taskcategory.class.php:98 +#: hook.php:9 inc/taskcategory.class.php:214 msgid "Synchronize Task List" msgstr "Synchronize Task List" -#: hook.php:158 inc/case.class.php:77 +#: hook.php:76 inc/case.class.php:89 msgid "Case" msgstr "Case" -#: hook.php:158 inc/case.class.php:586 inc/case.class.php:1062 +#: hook.php:76 inc/case.class.php:740 inc/case.class.php:1317 msgid "Status" msgstr "Status" -#: inc/case.class.php:23 inc/case.class.php:90 inc/case.class.php:92 +#: inc/case.class.php:25 msgid "Process case" msgid_plural "Process cases" msgstr[0] "Process case" msgstr[1] "Process cases" -#: inc/case.class.php:80 +#: inc/case.class.php:92 msgid "Sub-case" msgstr "Sub-case" -#: inc/case.class.php:312 +#: inc/case.class.php:265 +#, php-format +msgid "" +"Task un-claimed!
Case: %s
Task: \"%s\" has been " +"un-assigned from \"%s\" and assigned to \"%s\" group.
Reason: %s" +msgstr "" +"Task un-claimed!
Case: %s
Task: \"%s\" has been " +"un-assigned from \"%s\" and assigned to \"%s\" group.
Reason: %s" + +#: inc/case.class.php:382 +#, php-format +msgid "" +"Task re-assigned!
Case: %s
Task: \"%s\" has " +"been re-assigned from \"%s\" to \"%s\".
Reason: %s" +msgstr "" +"Task re-assigned!
Case: %s
Task: \"%s\" has " +"been re-assigned from \"%s\" to \"%s\".
Reason: %s" + +#: inc/case.class.php:391 +#, php-format +msgid "" +"Task assigned!
Case: %s
Task: \"%s\" has been " +"assigned to \"%s\".
Reason: %s" +msgstr "" +"Task assigned!
Case: %s
Task: \"%s\" has been " +"assigned to \"%s\".
Reason: %s" + +#: inc/case.class.php:472 msgid "Current task(s) properties" msgstr "Current task properties" -#: inc/case.class.php:316 inc/task.class.php:263 +#: inc/case.class.php:476 inc/task.class.php:283 msgid "Task" msgstr "Task" -#: inc/case.class.php:317 inc/task.class.php:264 +#: inc/case.class.php:477 inc/task.class.php:284 inc/taskcategory.class.php:43 +#: inc/taskcategory.class.php:122 msgid "Task guid" msgstr "Task guid" -#: inc/case.class.php:318 inc/task.class.php:265 +#: inc/case.class.php:478 inc/task.class.php:285 msgid "Current user" msgstr "Current user" -#: inc/case.class.php:319 inc/task.class.php:266 +#: inc/case.class.php:479 inc/task.class.php:286 msgid "Task delegation date" msgstr "Task delegation date" -#: inc/case.class.php:341 inc/task.class.php:275 +#: inc/case.class.php:501 inc/task.class.php:295 msgid "To be claimed" msgstr "To be claimed" -#: inc/case.class.php:377 +#: inc/case.class.php:537 msgid "Sub-case properties" msgstr "Sub-case properties" -#: inc/case.class.php:380 +#: inc/case.class.php:540 msgid "Parent case properties" msgstr "Parent case properties" -#: inc/case.class.php:382 +#: inc/case.class.php:542 msgid "Case properties" msgstr "Case properties" -#: inc/case.class.php:387 inc/case.class.php:584 inc/case.class.php:1036 -#: inc/process.class.php:548 +#: inc/case.class.php:547 inc/case.class.php:738 inc/case.class.php:1290 +#: inc/process.class.php:576 msgid "Process" msgstr "Process" -#: inc/case.class.php:388 +#: inc/case.class.php:548 inc/notificationtargetprocessmaker.class.php:64 msgid "Case title" msgstr "Case title" -#: inc/case.class.php:389 +#: inc/case.class.php:549 msgid "Case number" msgstr "Case number" -#: inc/case.class.php:390 +#: inc/case.class.php:550 msgid "Case status" msgstr "Case status" -#: inc/case.class.php:391 +#: inc/case.class.php:551 msgid "Case guid" msgstr "Case guid" -#: inc/case.class.php:392 +#: inc/case.class.php:552 msgid "Creator" msgstr "Creator" -#: inc/case.class.php:393 +#: inc/case.class.php:553 inc/case.class.php:1332 msgid "Creation date" msgstr "Creation date" -#: inc/case.class.php:394 +#: inc/case.class.php:554 msgid "Last update" msgstr "Last update" -#: inc/case.class.php:479 +#: inc/case.class.php:637 #, php-format msgid "Case is linked to a %1s" msgstr "Case is linked to a %1s" -#: inc/case.class.php:481 +#: inc/case.class.php:639 #, php-format msgid "Sub-case is linked to a %1s" msgstr "Sub-case is linked to a %1s" -#: inc/case.class.php:506 +#: inc/case.class.php:660 msgid "Case cancellation" msgstr "Case cancellation" -#: inc/case.class.php:507 +#: inc/case.class.php:661 msgid "Cancel case" msgstr "Cancel case" -#: inc/case.class.php:511 +#: inc/case.class.php:665 msgid "Confirm cancellation?" msgstr "Confirm cancellation?" -#: inc/case.class.php:511 inc/profile.class.php:23 +#: inc/case.class.php:665 inc/profile.class.php:23 msgid "Cancel" msgstr "Cancel" -#: inc/case.class.php:532 +#: inc/case.class.php:679 msgid "Case deletion" msgstr "Case deletion" -#: inc/case.class.php:533 -msgid "Delete case" -msgstr "Delete case" - -#: inc/case.class.php:585 inc/case.class.php:1029 +#: inc/case.class.php:739 inc/case.class.php:1283 msgid "Title" msgstr "Title" -#: inc/case.class.php:587 inc/case.class.php:1070 +#: inc/case.class.php:741 inc/case.class.php:1324 msgid "Sub-case of" msgstr "Sub-case of" -#: inc/case.class.php:602 +#: inc/case.class.php:758 msgid "Add a new case" msgstr "Add a new case" -#: inc/case.class.php:995 +#: inc/case.class.php:1189 msgctxt "case_status" msgid "Draft" msgstr "Draft" -#: inc/case.class.php:996 +#: inc/case.class.php:1190 msgctxt "case_status" msgid "To do" msgstr "To do" -#: inc/case.class.php:997 +#: inc/case.class.php:1191 msgctxt "case_status" msgid "Completed" msgstr "Completed" -#: inc/case.class.php:998 +#: inc/case.class.php:1192 msgctxt "case_status" msgid "Cancelled" msgstr "Cancelled" -#: inc/case.class.php:1022 +#: inc/case.class.php:1276 msgid "ID" msgstr "ID" -#: inc/case.class.php:1049 +#: inc/case.class.php:1297 inc/notificationtargetprocessmaker.class.php:72 +msgid "Item type" +msgstr "Item type" + +#: inc/case.class.php:1304 msgid "Item" msgstr "Item" -#: inc/case.class.php:1056 +#: inc/case.class.php:1311 msgid "Item entity" msgstr "Item entity" -#: inc/casechangelog.class.php:35 +#: inc/case.class.php:1341 +msgid "Last update date" +msgstr "Last update date" + +#: inc/case.class.php:1354 +#, php-format +msgid "Case status is '%s'" +msgstr "Case status is '%s'" + +#: inc/casechangelog.class.php:36 msgid "Change log" msgstr "Change log" -#: inc/casedynaform.class.php:80 +#: inc/casedynaform.class.php:83 msgid "Dynaforms" msgstr "Dynaforms" -#: inc/casehistory.class.php:35 +#: inc/casehistory.class.php:36 msgid "History" msgstr "History" @@ -269,43 +358,51 @@ msgstr "Case-links" msgid "Case-link" msgstr "Case-link" -#: inc/caselink.class.php:75 inc/caselink.class.php:165 +#: inc/caselink.class.php:75 +msgid "Synchronous" +msgstr "Synchronous" + +#: inc/caselink.class.php:80 inc/caselink.class.php:180 msgid "External data" msgstr "External data" -#: inc/caselink.class.php:80 inc/caselink.class.php:171 +#: inc/caselink.class.php:85 inc/caselink.class.php:186 msgid "Self" msgstr "Self" -#: inc/caselink.class.php:85 inc/caselink.class.php:189 +#: inc/caselink.class.php:90 inc/caselink.class.php:204 msgid "Source task GUID" msgstr "Source task GUID" -#: inc/caselink.class.php:93 inc/caselink.class.php:195 +#: inc/caselink.class.php:99 inc/caselink.class.php:210 msgid "Target task GUID" msgstr "Target task GUID" -#: inc/caselink.class.php:101 inc/caselink.class.php:207 +#: inc/caselink.class.php:107 inc/caselink.class.php:222 msgid "Target process GUID" msgstr "Target process GUID" -#: inc/caselink.class.php:110 inc/caselink.class.php:201 +#: inc/caselink.class.php:116 inc/caselink.class.php:216 msgid "Target dynaform GUID" msgstr "Target dynaform GUID" -#: inc/caselink.class.php:115 inc/caselink.class.php:213 +#: inc/caselink.class.php:121 inc/caselink.class.php:228 msgid "Source condition" msgstr "Source condition" -#: inc/caselink.class.php:121 inc/caselink.class.php:177 +#: inc/caselink.class.php:127 inc/caselink.class.php:192 msgid "Claim target task" msgstr "Claim target task" -#: inc/caselink.class.php:126 inc/caselink.class.php:183 +#: inc/caselink.class.php:137 +msgid "Impersonate target task user" +msgstr "Impersonate target task user" + +#: inc/caselink.class.php:142 inc/caselink.class.php:198 msgid "External application JSON config" msgstr "External application JSON config" -#: inc/casemap.class.php:43 +#: inc/casemap.class.php:44 msgid "Map" msgstr "Map" @@ -314,187 +411,288 @@ msgid "ProcessMaker setup" msgstr "ProcessMaker setup" #: inc/config.class.php:159 -msgid "Server URL (must be in same domain than GLPI)" -msgstr "Server URL (must be in same domain than GLPI)" +msgid "" +"Server URL (must be in same domain than GLPI, if GLPI is using HTTPS, PM " +"server must also use HTTPS)" +msgstr "" +"Server URL (must be in same domain than GLPI, if GLPI is using HTTPS, PM " +"server must also use HTTPS)" -#: inc/config.class.php:164 +#: inc/config.class.php:163 msgid "Common domain with GLPI" msgstr "Common domain with GLPI" -#: inc/config.class.php:193 +#: inc/config.class.php:192 msgid "None!" msgstr "None!" -#: inc/config.class.php:202 +#: inc/config.class.php:201 +msgid "Verify SSL certificate" +msgstr "Verify SSL certificate" + +#: inc/config.class.php:206 msgid "Workspace Name" msgstr "Workspace Name" -#: inc/config.class.php:207 +#: inc/config.class.php:211 msgid "Server administrator name" msgstr "Server administrator name" -#: inc/config.class.php:212 +#: inc/config.class.php:216 msgid "Server administrator password" msgstr "Server administrator password" -#: inc/config.class.php:218 inc/config.class.php:258 +#: inc/config.class.php:222 inc/config.class.php:262 msgid "Connection status" msgstr "Connection status" -#: inc/config.class.php:234 +#: inc/config.class.php:238 msgid "SQL server setup" msgstr "SQL server setup" -#: inc/config.class.php:237 +#: inc/config.class.php:241 msgid "SQL server (MariaDB or MySQL)" msgstr "SQL server (MariaDB or MySQL)" -#: inc/config.class.php:242 +#: inc/config.class.php:246 msgid "Database name" msgstr "Database name" -#: inc/config.class.php:247 +#: inc/config.class.php:251 msgid "SQL user" msgstr "SQL user" -#: inc/config.class.php:252 +#: inc/config.class.php:256 msgid "SQL password" msgstr "SQL password" -#: inc/config.class.php:269 +#: inc/config.class.php:273 msgid "Theme Name" msgstr "Theme Name" -#: inc/config.class.php:275 +#: inc/config.class.php:279 msgid "Main Task Category (edit to change name)" msgstr "Main Task Category (edit to change name)" -#: inc/config.class.php:282 -msgid "Task Writer (edit to change name)" -msgstr "Task Writer (edit to change name)" +#: inc/config.class.php:286 +msgid "Task writer (edit to change name)" +msgstr "Task writer (edit to change name)" -#: inc/config.class.php:302 +#: inc/config.class.php:306 msgid "Group in ProcessMaker which will contain all GLPI users" msgstr "Group in ProcessMaker which will contain all GLPI users" -#: inc/config.class.php:331 +#: inc/config.class.php:321 inc/process.class.php:510 inc/process.class.php:637 +msgid "Max cases per item (0=unlimited)" +msgstr "Max cases per item (0=unlimited)" + +#: inc/config.class.php:340 msgid "Processmaker system information" msgstr "Processmaker system information" -#: inc/config.class.php:334 inc/config.class.php:344 +#: inc/config.class.php:343 inc/config.class.php:353 msgid "Version" msgstr "Version" -#: inc/config.class.php:335 +#: inc/config.class.php:344 msgid "Web server" msgstr "Web server" -#: inc/config.class.php:336 +#: inc/config.class.php:345 msgid "Server name" msgstr "Server name" -#: inc/config.class.php:337 +#: inc/config.class.php:346 msgid "PHP version" msgstr "PHP version" -#: inc/config.class.php:338 +#: inc/config.class.php:347 msgid "DB version" msgstr "DB version" -#: inc/config.class.php:339 +#: inc/config.class.php:348 msgid "DB server IP" msgstr "DB server IP" -#: inc/config.class.php:340 +#: inc/config.class.php:349 msgid "DB name" msgstr "DB name" -#: inc/config.class.php:341 +#: inc/config.class.php:350 msgid "User browser" msgstr "User browser" -#: inc/config.class.php:342 +#: inc/config.class.php:351 msgid "User IP" msgstr "User IP" -#: inc/config.class.php:344 +#: inc/config.class.php:353 msgid "Not yet!" msgstr "Not yet!" -#: inc/process.class.php:350 +#: inc/notificationtargetcase.class.php:26 +msgid "Send email" +msgstr "Send email" + +#: inc/notificationtargetcase.class.php:37 +msgid "eMail recipients" +msgstr "eMail recipients" + +#: inc/notificationtargetprocessmaker.class.php:60 +msgid "Process category" +msgstr "Process category" + +#: inc/notificationtargetprocessmaker.class.php:61 +msgid "Process category id" +msgstr "Process category id" + +#: inc/notificationtargetprocessmaker.class.php:62 +msgid "Process category comment" +msgstr "Process category comment" + +#: inc/notificationtargetprocessmaker.class.php:63 +msgid "Case id" +msgstr "Case id" + +#: inc/notificationtargetprocessmaker.class.php:65 +msgid "Case description" +msgstr "Case description" + +#: inc/notificationtargetprocessmaker.class.php:67 +msgid "Case variable 'XXX'" +msgstr "Case variable 'XXX'" + +#: inc/notificationtargetprocessmaker.class.php:68 +msgid "List of values in 'YYY' array" +msgstr "List of values in 'YYY' array" + +#: inc/notificationtargetprocessmaker.class.php:69 +msgid "Number of rows in 'YYY' array" +msgstr "Number of rows in 'YYY' array" + +#: inc/notificationtargetprocessmaker.class.php:70 +msgid "Value for colname in 'YYY' array" +msgstr "Value for colname in 'YYY' array" + +#: inc/notificationtargetprocessmaker.class.php:71 +msgid "Value for key in 'ZZZ' assoc array (1-dimension array)" +msgstr "Value for key in 'ZZZ' assoc array (1-dimension array)" + +#: inc/notificationtargetprocessmaker.class.php:73 +msgid "Item id" +msgstr "Item id" + +#: inc/notificationtargetprocessmaker.class.php:74 +msgid "Item URL" +msgstr "Item URL" + +#: inc/notificationtargetprocessmaker.class.php:75 +msgid "Item title" +msgstr "Item title" + +#: inc/notificationtargetprocessmaker.class.php:83 +msgid "XXX is to be replaced by any case variable names" +msgstr "XXX is to be replaced by any case variable names" + +#: inc/notificationtargetprocessmaker.class.php:86 +msgid "YYY is to be replaced by any array variables" +msgstr "YYY is to be replaced by any array variables" + +#: inc/notificationtargetprocessmaker.class.php:90 +msgid "" +"ZZZ is to be replaced by any assoc array variables (1-dimension array with " +"key/value pairs)" +msgstr "" +"ZZZ is to be replaced by any assoc array variables (1-dimension array with " +"key/value pairs)" + +#: inc/notificationtargettask.class.php:195 +msgid "Task action" +msgstr "Task action" + +#: inc/process.class.php:366 msgid "Synchronize Process List" msgstr "Synchronize Process List" -#: inc/process.class.php:427 inc/process.class.php:589 +#: inc/process.class.php:443 inc/process.class.php:617 msgid "Process GUID" msgstr "Process GUID" -#: inc/process.class.php:433 +#: inc/process.class.php:449 msgid "Process type" msgstr "Process type" -#: inc/process.class.php:439 +#: inc/process.class.php:455 msgid "Hide case num. & title" msgstr "Hide case num. & title" -#: inc/process.class.php:445 +#: inc/process.class.php:461 msgid "Insert Task Category" msgstr "Insert Task Category" -#: inc/process.class.php:457 +#: inc/process.class.php:473 msgid "Ticket type (self-service)" msgstr "Ticket type (self-service)" -#: inc/process.class.php:464 inc/process.class.php:609 +#: inc/process.class.php:480 inc/process.class.php:642 msgid "Visible in Incident for Central interface" msgstr "Visible in Incident for Central interface" -#: inc/process.class.php:470 inc/process.class.php:614 +#: inc/process.class.php:486 inc/process.class.php:647 msgid "Visible in Request for Central interface" msgstr "Visible in Request for Central interface" -#: inc/process.class.php:476 inc/process.class.php:666 +#: inc/process.class.php:492 inc/process.class.php:699 msgid "Visible in Change" msgstr "Visible in Change" -#: inc/process.class.php:482 inc/process.class.php:671 +#: inc/process.class.php:498 inc/process.class.php:704 msgid "Visible in Problem" msgstr "Visible in Problem" -#: inc/process.class.php:519 +#: inc/process.class.php:504 +msgid "Maintenance" +msgstr "Maintenance" + +#: inc/process.class.php:547 msgctxt "process_type" msgid "Classic" msgstr "Classic" -#: inc/process.class.php:520 +#: inc/process.class.php:548 msgctxt "process_type" msgid "BPMN" msgstr "BPMN" -#: inc/process.class.php:546 +#: inc/process.class.php:574 msgid "Processes" msgstr "Processes" -#: inc/process.class.php:599 +#: inc/process.class.php:627 msgid "Hide case number and title in task descriptions" msgstr "Hide case number and title in task descriptions" -#: inc/process.class.php:604 +#: inc/process.class.php:632 msgid "Insert Task Category comments in Task Description" msgstr "Insert Task Category comments in Task Description" -#: inc/process.class.php:619 +#: inc/process.class.php:652 msgid "ITIL Category for Self-service interface (left empty to disable)" msgstr "ITIL Category for Self-service interface (left empty to disable)" -#: inc/process.class.php:646 +#: inc/process.class.php:679 msgid "Type for Self-service interface" msgstr "Type for Self-service interface" -#: inc/process.class.php:676 +#: inc/process.class.php:709 msgid "Process type (to be changed only if not up-to-date)" msgstr "Process type (to be changed only if not up-to-date)" +#: inc/process.class.php:862 +#, php-format +msgid "Process '%s' is under maintenance, please retry later, thank you." +msgstr "Process '%s' is under maintenance, please retry later, thank you." + #: inc/process_profile.class.php:26 inc/process_profile.class.php:45 msgid "Authorizations" msgstr "Authorizations" @@ -513,35 +711,44 @@ msgctxt "errors" msgid "Can't create case: no rights for it!" msgstr "Can't create case: no rights for it!" -#: inc/processmaker.class.php:984 +#: inc/processmaker.class.php:1012 msgid "Syncs GLPI users and groups into ProcessMaker." msgstr "Syncs GLPI users and groups into ProcessMaker." -#: inc/processmaker.class.php:986 +#: inc/processmaker.class.php:1014 msgid "Cleaning of orphan cases." msgstr "Cleaning of orphan cases." -#: inc/processmaker.class.php:986 +#: inc/processmaker.class.php:1014 msgid "Number of days to keep orphan cases" msgstr "Number of days to keep orphan cases" -#: inc/processmaker.class.php:988 +#: inc/processmaker.class.php:1016 msgid "To apply task actions between cases." msgstr "To apply task actions between cases." -#: inc/processmaker.class.php:1696 +#: inc/processmaker.class.php:1707 msgid "Case title: " msgstr "Case title: " -#: inc/processmaker.class.php:2178 +#: inc/processmaker.class.php:2262 msgid "A 'Case' is running!" msgstr "A 'Case' is running!" -#: inc/processmaker.class.php:2179 +#: inc/processmaker.class.php:2263 msgid "You must manage it first (see 'Process - Case' tab)!" msgstr "You must manage it first (see 'Process - Case' tab)!" -#: inc/processmaker.class.php:3038 +#: inc/processmaker.class.php:2779 +#, php-format +msgid "" +"Unable to derivate case! Retry in a moment, or ask your administrator." +"
Error code: %u
Error message: %s
" +msgstr "" +"Unable to derivate case! Retry in a moment, or ask your administrator." +"
Error code: %u
Error message: %s
" + +#: inc/processmaker.class.php:3283 msgid "" "ProcessMaker plugin is under maintenance, please retry later, thank you." msgstr "" @@ -555,36 +762,176 @@ msgstr "Process configuration" msgid "Cases" msgstr "Cases" +#: inc/profile.class.php:23 +msgid "Ad Hoc user re-assign" +msgstr "Ad Hoc user re-assign" + #: inc/task.class.php:29 msgid "Process case task" msgid_plural "Process case tasks" msgstr[0] "Process case task" msgstr[1] "Process case tasks" -#: inc/task.class.php:258 +#: inc/task.class.php:278 msgid "Sub-case task(s)" msgstr "Sub-case task(s)" -#: inc/taskcategory.class.php:21 inc/taskcategory.class.php:31 -msgid "Task List" -msgstr "Task List" +#: inc/taskcategory.class.php:24 inc/taskcategory.class.php:116 +msgid "Process task" +msgstr "Process task" -#: inc/taskcategory.class.php:32 +#: inc/taskcategory.class.php:29 inc/taskcategory.class.php:39 +msgid "Task list" +msgstr "Task list" + +#: inc/taskcategory.class.php:40 inc/taskcategory.class.php:118 msgid "Task name" msgstr "Task name" -#: inc/taskcategory.class.php:34 inc/taskcategory.class.php:60 +#: inc/taskcategory.class.php:42 inc/taskcategory.class.php:68 +#: inc/taskcategory.class.php:121 inc/taskcategory.class.php:155 msgid "Start" msgstr "Start" -#: inc/taskcategory.class.php:35 -msgid "Task GUID" -msgstr "Task GUID" - -#: inc/taskcategory.class.php:38 inc/taskcategory.class.php:78 +#: inc/taskcategory.class.php:46 inc/taskcategory.class.php:86 +#: inc/taskcategory.class.php:125 inc/taskcategory.class.php:173 msgid "Sub-process" msgstr "Sub-process" +#: inc/taskcategory.class.php:117 +msgid "Process name" +msgstr "Process name" + +#, fuzzy +#~| msgid "Delete case" +#~ msgid "Delete permanently" +#~ msgstr "Delete case" + +#, fuzzy +#~| msgid "None!" +#~ msgid "None" +#~ msgstr "None!" + +#, fuzzy +#~| msgid "Maintenance" +#~ msgid "Maintenance mode" +#~ msgstr "Maintenance" + +#, fuzzy +#~| msgid "Case id" +#~ msgid "Case URL" +#~ msgstr "Case id" + +#, fuzzy +#~| msgid "Task guid" +#~ msgid "Task add" +#~ msgstr "Task guid" + +#, fuzzy +#~| msgid "Task re-assigned!" +#~ msgid "Task re-assign" +#~ msgstr "Task re-assigned!" + +#, fuzzy +#~| msgid "Task un-claimed!" +#~ msgid "Task un-claim" +#~ msgstr "Task un-claimed!" + +#, fuzzy +#~| msgid "Task name" +#~ msgid "Task done" +#~ msgstr "Task name" + +#, fuzzy +#~| msgid "Send reminder" +#~ msgid "Task reminder" +#~ msgstr "Send reminder" + +#, fuzzy +#~| msgid "Creation date" +#~ msgid "Opening date" +#~ msgstr "Creation date" + +#, fuzzy +#~| msgid "Case description" +#~ msgid "Description" +#~ msgstr "Case description" + +#, fuzzy +#~| msgid "Process category id" +#~ msgid "Category id" +#~ msgstr "Process category id" + +#, fuzzy +#~| msgid "Process category comment" +#~ msgid "Category comment" +#~ msgstr "Process category comment" + +#, fuzzy +#~| msgid "Task action" +#~ msgid "Total duration" +#~ msgstr "Task action" + +#, fuzzy +#~| msgid "Re-assign task" +#~ msgid "User assigned to task" +#~ msgstr "Re-assign task" + +#, fuzzy +#~| msgid "Case is linked to a %1s" +#~ msgid "User login assigned to task" +#~ msgstr "Case is linked to a %1s" + +#, fuzzy +#~| msgid "Re-assign task" +#~ msgid "Group assigned to task" +#~ msgstr "Re-assign task" + +#, fuzzy +#~| msgid "Start" +#~ msgid "Start date" +#~ msgstr "Start" + +#, fuzzy +#~| msgid "Last update" +#~ msgid "Last updater" +#~ msgstr "Last update" + +#, fuzzy +#~| msgid "Task delegation date" +#~ msgid "Delegation index" +#~ msgstr "Task delegation date" + +#, fuzzy +#~| msgid "Delete case" +#~ msgid "Delete" +#~ msgstr "Delete case" + +#, fuzzy +#~| msgctxt "case_status" +#~| msgid "Completed" +#~ msgid "Complete name" +#~ msgstr "Completed" + +#, fuzzy +#~| msgid "Re-assign" +#~ msgctxt "processmaker" +#~ msgid "Re-assign" +#~ msgstr "Re-assign" + +#, fuzzy +#~| msgid "Process case" +#~| msgid_plural "Process cases" +#~ msgctxt "processmaker" +#~ msgid "Process case" +#~ msgstr "Process case" + +#~ msgid "Task GUID" +#~ msgstr "Task GUID" + +#~ msgid "Task List" +#~ msgstr "Task List" + #~ msgid "Case item" #~ msgstr "Case item" diff --git a/locales/fr_FR.mo b/locales/fr_FR.mo index a72879c76d0b1aa022fc544db053320a77fab2f7..eefb4d668937e7c9ad913d95d1d084ebdd830804 100644 GIT binary patch delta 4551 zcmaLad2p2V9mnzCl4Lm&NFX3*!jl8S5yIvokfKdE zR6rjoC`UOINU_km&QxYV>ZI682iws<+D<7&ZA+&YPAj#YL8tG}?vqUIjD05G=k~{s)Jq5{R5c6^%3X#B+`d@ z6$j#*s1ARLn%KwAeK(D1-~&(t8;*mpEH|F&aE5bZ5o!R9r~$1*y|@82ke#TG_MwI6 zocr%!4cEUwWgxq+F=KH!s>4Ot1skyry*LC<#VM3gxQhIlzi}$ZG={I#S7SGr> zRD%tu0WL-jY^8I*1+_GrFc0_O2t4cD|2d{{eG@H=-=?6Hx)`=P>WW2}gKD4()$x4f z&opu>z!)~*A=H5GU_IW&URcgLD3f)lRL{m@T!YH!v&cZ><_HCCo>!6VnQO?H%&$-l z+;zO~*qw(fseb@B)4JvC*jZY8ps* zi+fR-ID~58yim7r2Q0SEHE z&B4uFui?{r8b8E0a9x}{v9V3@u+$PvM9r)THNq{Z6rM-T>=Fj?Bh<|2vu;|`rAR+! z6>6YsQD4JW$Ni}1PNDYD1=Nzoe@sDZ{UK@>{{@vIcS&j!^+OF{Bx;~Fs3mDY{gyw5 z%2W$#ZFivB+lv~|LFf8KREAC?t819%4{QQq5;(YGdn4$!PEFvd>b>-&Cblg zJ~$Q!U{{=u>S!*OVQJ+?P%d~Jcw5@7atv$y6;C;&Fsd9 z@dv1keU93^c{QocISff=+|*If8i!LA=9{R2yos98b)1C1##+p0;p%V+`tc=H!|Cia zEm0OK)%{TQLs3gqf;3_3P4mBm`6+@rVIr>7&l5UcAWjpT32mzlgpSet$9yEKU)~PNeF^Q=$A~>d z#}Tk!$tqd?ESHT$52A@!N@zKrBX$v5BBgl&p<_Rx{W6O#0+8^F`d{>oFkqfbgUvCA{G*RiKhsg_zJO%;OJq#%~>Bx zt^HuH{_&Zr0L#c?D)6%~<}3`fSa3|L17EZK-r(8{-QH*~ADoxS z8Zs|Er+kd3VoZ6pRbEqDSvA^IZU?MHT2)y^qNt#-OGY#r_OG2Nd1?+ z7ga<4Kx>F5SGM@90#hFh##+3|`Y&{FblB*Q#%~NOwF`&GyGAq^e;{#Y_&YAwB)fG) zO=q7MMjReTbHP}ky)7KFd`h$x^+&@#t2t&hc_U`FH?ltF3#%9lSJW=6nC$Y|>noZH>zg|B+S$+)ZP%a(8ONmy?I>;05w#s!+Gz)E`J<&3`~BT>!nB?C%ze)1eb2e) zU7q(n=Tz`eV0UX|p)qDusxiaShl#ielW`07#a+nH?Bz5NPvQ_fhyC$Q9Dx^6?Oeko z{1P)TX{gg)HV&pn-n(;`lX3*8${r~#}(4X6Y4;0Dw{wxT-Pg%)c2*1V8}2U$9z6N zN_ib>1`XJXtC631lan&`F)CwUpxW!t^yMg2s*6!?mj~6)WE@TZrj~*pT#3p=JL-`una|P$|5I>fk0SGs$da#$bk{X6iw$c{M6yD^N>vKWgTWy4USY^3T38N4X$h z!ysNnZLZnmRco~fEnJS1a3kvfFQfkV7HVJ@u@FB+?TO?u&RZ}BV@rtI3k_I?-ZA8V z0);(XsKoQwj5koJUdFIx8>)j%t~*f~ID*A^21$nb$i4q}R7R66_6YBtgGy_1XdV?3yVR-rOb=Xwun zsXI}7X`^do4+U+G)2QA23MxexQJe7!Y5;#h4OFAll8iuo%X3i~szR;pB2;^gr~%#U z*4Lmi)Pbz7*?|lsVxDzx{1COKAE0LNIjW&}rmNjL5H+KTr~%AEEx}UP)u>Il9`)Q~ zScp%emgoYi-9O<>yoICn{?FiFv$)WV+9Zdt4|e07_&k>2KTzL=!Xjht#>J@D>o_Vy z&!IZ_9%_JZqcU^}mC>uH3En`qmq}(+iQYfn)e`+Hy^t9 z6H1-6%tJLa3$<4oP|vmD6nqd<@GREjd1T+3RA!|CRZk@Uv}tO&pg(q@8rpd2<0LOSg|Fb#i#y8j8XD&`hy#-)>-0f$kWcrR*` z9zc>5F|Sh4hvyH@1ruNG45SJ*qgvDq8?XlV;Y|EFwqq&_s)ip%E!7s(5BjcH%14Pd;w&+h@De(nafp54 z_fcNz)_ZBB@EoD;?;vK`pC+e8x+uL!G!uF)=MXOu49R?x&~j}cltpb`9d{C?#2Mo2 z#BxH162bQ}mKeQAdk7tS39agbgtk|h(7~6(4yL4MeS`8aLVNZk@g1V~=&+wn$zQpX z>PkXuwubmBQA<2QY$dcrN`C{fgV;^v5Q~UI#5m${VlAyNj3ibQyfLvO$az2U6j4uf6FL?+L z*-q7bTetgD>E~XUixqCUmo2>o@V>K zgY9emR--rgz}V>WS8m9oHuz)`@*MXGVfo-Pz~I zmnFGfbG6zo$w|3gpP5sdUhDUVJG`OxF2B|4vpVv+uF^Xx&7QW zy!O1@V8;J^DCD(o<`yT$2H>@e^Ck@a?`HYOFLE>Nro2dkudU7768$Leow&F)_Njtu z#-xrz_SJ%?^8Mk?Qp*>zLhYe|&uR@@E#9D6;tj43`vMj>d%6Q%+_$5J-?xty)uzw( zhI+c!b_LpfK~18u=UB^qKKnvpW?W-5z4*6r3_jMl*Zy)sS)o(ZjHj*%Oq^cO;k81s zC#;|^;I#rh-MwR3UUIyTFKGX> zAYdOVJ2IpFQ09HR^BpRyCAjzUU&FLyMf6wC8zzM-Bnqh zQ`>TTsd|TP=6GX&wCJycJb3MJMRieZmOb4*tLKQ-LN3Fh_Kx--{|pDLf-X|(bM}?5 z(7shMW|WgNXSp0w1Uqdsodt{|I<^HOviTTcQN2_kc F{|lzla<~8h diff --git a/locales/fr_FR.po b/locales/fr_FR.po index dadf1bc..fd4da01 100644 --- a/locales/fr_FR.po +++ b/locales/fr_FR.po @@ -1,18 +1,19 @@ msgid "" msgstr "" "Project-Id-Version: processmaker-plugin\n" -"POT-Creation-Date: 2020-07-13 09:41+0200\n" -"PO-Revision-Date: 2020-07-13 11:02+0200\n" +"POT-Creation-Date: 2021-02-15 17:32+0100\n" +"PO-Revision-Date: 2021-02-15 17:34+0100\n" "Last-Translator: tomolimo\n" "Language-Team: French\n" "Language: fr_FR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.3.1\n" +"X-Generator: Poedit 2.4.2\n" "X-Poedit-Basepath: ..\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Poedit-KeywordsList: ;__:1,2t;_e:1,2t;_x:1c,2,3t;_n:1,2,4t;__s:1,2t;_ex:1c,2,3t;_sx:1c,2,3t;_nx:1c,2,3,5t\n" +"X-Poedit-KeywordsList: ;__:1,2t;_e:1,2t;_x:1c,2,3t;_n:1,2,4t;__s:1,2t;" +"_ex:1c,2,3t;_sx:1c,2,3t;_nx:1c,2,3,5t\n" "X-Crowdin-Project: processmaker-plugin\n" "X-Crowdin-Project-ID: 310131\n" "X-Crowdin-Language: fr\n" @@ -28,54 +29,63 @@ msgstr "" #: ajax/task_users.php:36 msgid "Re-assign task to" -msgstr "Ré-affecter tâche à" +msgstr "Réattribuer la tâche à" -#: ajax/task_users.php:60 ajax/task_users.php:61 ajax/task_users.php:124 +#: ajax/task_users.php:67 ajax/task_users.php:68 ajax/task_users.php:135 msgid "Re-assign" -msgstr "Ré-affecter" +msgstr "Réattribuer" -#: ajax/task_users.php:110 -#| msgid "Task already assigned to this person!" -msgid "Task is already assigned to this user or group!" -msgstr "La tâche est déjà affectée à cet utilisateur (ou ce groupe) !" +#: ajax/task_users.php:100 +msgid "Input at least 10 words in English to justify." +msgstr "Entrez au moins 10 mots en anglais pour justifier." -#: ajax/task_users.php:110 ajax/task_users.php:122 -#| msgid "Re-assign task to" +#: ajax/task_users.php:118 +msgid "Task is already un-assigned!" +msgstr "L'attribution de cette tâche est déjà supprimée !" + +#: ajax/task_users.php:118 ajax/task_users.php:120 ajax/task_users.php:133 msgid "Re-assign task" -msgstr "Ré-affecter tâche" +msgstr "Réattribuer la tâche" -#: ajax/task_users.php:114 ajax/task_users.php:119 -#| msgid "Claim target task" +#: ajax/task_users.php:120 +msgid "Task is already assigned to this user!" +msgstr "La tâche est déjà attribuée à cet utilisateur !" + +#: ajax/task_users.php:125 ajax/task_users.php:130 msgid "Un-claim task" -msgstr "Annuler affectation de la tâche" +msgstr "Supprimer l'attribution de la tâche" -#: ajax/task_users.php:115 -msgid "Please input reason to un-claim
(task will be re-assigned to former group):" -msgstr "Saisir la raison pour l'annulation de l'affectation
(la tâche sera ré-affectée au groupe précédent) :" +#: ajax/task_users.php:126 +msgid "" +"Please input reason to un-claim
(task will be re-assigned to former " +"group):" +msgstr "" +"Saisir la raison pour l'annulation de l'attribution
(la tâche sera " +"réattribuée au groupe précédent) :" -#: ajax/task_users.php:116 +#: ajax/task_users.php:127 msgid "Un-claim" -msgstr "Annulation de l'affectation" +msgstr "Suppression de l'attribution" -#: ajax/task_users.php:119 -msgid "Can\\'t un-assign Task!" -msgstr "Annulation de l'affectation impossible !" - -#: ajax/task_users.php:123 -msgid "Please input reason to re-assign:" -msgstr "Saisir la raison pour la ré-affectation :" +#: ajax/task_users.php:130 +msgid "Can't un-assign task!" +msgstr "Suppression de l'attribution impossible !" #: ajax/task_users.php:134 +msgid "Please input reason to re-assign:" +msgstr "Saisir la raison pour la réattribution :" + +#: ajax/task_users.php:145 msgid "Send reminder" msgstr "Envoyer un rappel" #: front/case.form.php:32 msgid "Case has been deleted!" -msgstr "Le cas a été effacé !" +msgstr "Le cas a été supprimé !" #: front/case.form.php:34 msgid "Unable to delete case!" -msgstr "Impossible d'effacer le cas !" +msgstr "Impossible de supprimer le cas !" #: front/case.form.php:46 msgid "Case has been cancelled!" @@ -85,12 +95,12 @@ msgstr "Le cas a été annulé !" msgid "Unable to cancel case!" msgstr "Impossible d'annuler le cas !" -#: front/case.form.php:70 front/case.form.php:72 inc/case.class.php:1310 +#: front/case.form.php:70 front/case.form.php:72 inc/case.class.php:1272 msgid "Process cases" msgstr "Cas des processus" #: front/case.php:5 front/caselink.form.php:29 front/caselink.php:5 -#: front/process.form.php:27 front/process.php:5 inc/caselink.class.php:157 +#: front/process.form.php:27 front/process.php:5 inc/caselink.class.php:158 #: inc/config.class.php:50 inc/config.class.php:363 inc/process.class.php:409 #: inc/profile.class.php:52 inc/profile.class.php:83 msgid "ProcessMaker" @@ -98,222 +108,235 @@ msgstr "ProcessMaker" #: front/processmaker.form.php:80 msgid "Task re-assigned!" -msgstr "Tâche ré-affectée !" +msgstr "Tâche réattribuée !" #: front/processmaker.form.php:82 msgid "Error re-assigning task: " -msgstr "Impossible de ré-affecter cette tâche :" +msgstr "Impossible de réattribuer cette tâche :" #: front/processmaker.form.php:93 -#| msgid "Task name" msgid "Task un-claimed!" -msgstr "Annulation de l'affectation de la tâche effectuée !" +msgstr "Annulation de l'attribution de la tâche effectuée !" #: front/processmaker.form.php:95 -msgid "Can't un-claim task! Verify 'Assignement Rules' in the process definition." -msgstr "Annulation de l'affectation impossible ! Vérifiez les règles d'assignation dans la définition du Processus." +msgid "" +"Can't un-claim task! Verify 'Assignement Rules' in the process definition." +msgstr "" +"Annulation de l'attribution impossible ! Vérifiez les règles d'attribution " +"dans la définition du Processus." #: front/processmaker.helpdesk.form.php:21 msgid "Process - Case" msgstr "Processus - Cas" -#: front/processmaker.helpdesk.form.php:24 inc/case.class.php:799 +#: front/processmaker.helpdesk.form.php:24 inc/case.class.php:761 msgid "Select the process you want to add" -msgstr "Choisir le processus à démarrer" +msgstr "Choisir le processus à ajouter" #: hook.php:9 inc/taskcategory.class.php:214 msgid "Synchronize Task List" -msgstr "Synchroniser la liste des Tâches" +msgstr "Synchroniser la liste des tâches" #: hook.php:76 inc/case.class.php:89 msgid "Case" msgstr "Cas" -#: hook.php:76 inc/case.class.php:778 inc/case.class.php:1355 +#: hook.php:76 inc/case.class.php:740 inc/case.class.php:1317 msgid "Status" msgstr "Statut" -#: inc/case.class.php:25 inc/case.class.php:102 inc/case.class.php:104 +#: inc/case.class.php:25 msgid "Process case" msgid_plural "Process cases" msgstr[0] "Cas du processus" -msgstr[1] "Cas des processus" +msgstr[1] "Cas du processus" #: inc/case.class.php:92 msgid "Sub-case" msgstr "Sous-cas" -#: inc/case.class.php:303 +#: inc/case.class.php:265 #, php-format -msgid "Task un-claimed!
Case: %s
Task: \"%s\" has been un-assigned from \"%s\" and assigned to \"%s\" group.
Reason: %s" -msgstr "Annulation de l'affection de la tâche effectuée !
Cas : %s
Tâche : \"%s\" a été libérée de \"%s\" et assignée au groupe \"%s\".
Motif : %s" +msgid "" +"Task un-claimed!
Case: %s
Task: \"%s\" has been " +"un-assigned from \"%s\" and assigned to \"%s\" group.
Reason: %s" +msgstr "" +"Suppression de l'attribution de la tâche effectuée !
Cas : " +"%s
Tâche : \"%s\" a été libérée de \"%s\" et attribuée au groupe " +"\"%s\".
Motif : %s" -#: inc/case.class.php:420 +#: inc/case.class.php:382 #, php-format -msgid "Task re-assigned!
Case: %s
Task: \"%s\" has been re-assigned from \"%s\" to \"%s\".
Reason: %s" -msgstr "Tâche ré-assignée !
Cas : %s
Tâche : \"%s\" a été ré-assignée de \"%s\" à \"%s\".
Motif : %s" +msgid "" +"Task re-assigned!
Case: %s
Task: \"%s\" has " +"been re-assigned from \"%s\" to \"%s\".
Reason: %s" +msgstr "" +"Tâche réattribuée !
Cas : %s
Tâche : \"%s\" a " +"été réattribuée de \"%s\" à \"%s\".
Motif : %s" -#: inc/case.class.php:429 +#: inc/case.class.php:391 #, php-format -msgid "Task assigned!
Case: %s
Task: \"%s\" has been assigned to \"%s\".
Reason: %s" -msgstr "Tâche assignée !
Cas : %s
Tâche : \"%s\" a été asignée à \"%s\".
Motif : %s" +msgid "" +"Task assigned!
Case: %s
Task: \"%s\" has been " +"assigned to \"%s\".
Reason: %s" +msgstr "" +"Tâche attribuée !
Cas : %s
Tâche : \"%s\" a été " +"attribuée à \"%s\".
Motif : %s" -#: inc/case.class.php:510 +#: inc/case.class.php:472 msgid "Current task(s) properties" msgstr "Propriétés des tâches en cours" -#: inc/case.class.php:514 inc/task.class.php:283 +#: inc/case.class.php:476 inc/task.class.php:283 msgid "Task" msgstr "Tâche" -#: inc/case.class.php:515 inc/task.class.php:284 +#: inc/case.class.php:477 inc/task.class.php:284 inc/taskcategory.class.php:43 +#: inc/taskcategory.class.php:122 msgid "Task guid" msgstr "Guid de la tâche" -#: inc/case.class.php:516 inc/task.class.php:285 +#: inc/case.class.php:478 inc/task.class.php:285 msgid "Current user" msgstr "Utilisateur actuel" -#: inc/case.class.php:517 inc/task.class.php:286 +#: inc/case.class.php:479 inc/task.class.php:286 msgid "Task delegation date" -msgstr "Date de délégation de tâche" +msgstr "Date d'attribution de tâche" -#: inc/case.class.php:539 inc/task.class.php:295 +#: inc/case.class.php:501 inc/task.class.php:295 msgid "To be claimed" msgstr "A réclamer" -#: inc/case.class.php:575 +#: inc/case.class.php:537 msgid "Sub-case properties" msgstr "Propriétés du sous-cas" -#: inc/case.class.php:578 +#: inc/case.class.php:540 msgid "Parent case properties" msgstr "Propriétés du cas parent" -#: inc/case.class.php:580 +#: inc/case.class.php:542 msgid "Case properties" msgstr "Propriétés du cas" -#: inc/case.class.php:585 inc/case.class.php:776 inc/case.class.php:1328 +#: inc/case.class.php:547 inc/case.class.php:738 inc/case.class.php:1290 #: inc/process.class.php:576 msgid "Process" msgstr "Processus" -#: inc/case.class.php:586 inc/notificationtargetprocessmaker.class.php:64 +#: inc/case.class.php:548 inc/notificationtargetprocessmaker.class.php:64 msgid "Case title" msgstr "Titre du cas" -#: inc/case.class.php:587 +#: inc/case.class.php:549 msgid "Case number" msgstr "Numéro du cas" -#: inc/case.class.php:588 +#: inc/case.class.php:550 msgid "Case status" msgstr "Statut du cas" -#: inc/case.class.php:589 +#: inc/case.class.php:551 msgid "Case guid" msgstr "Guid du cas" -#: inc/case.class.php:590 +#: inc/case.class.php:552 msgid "Creator" msgstr "Créateur" -#: inc/case.class.php:591 inc/case.class.php:1370 +#: inc/case.class.php:553 inc/case.class.php:1332 msgid "Creation date" msgstr "Date de création" -#: inc/case.class.php:592 +#: inc/case.class.php:554 msgid "Last update" msgstr "Dernière mise à jour" -#: inc/case.class.php:675 +#: inc/case.class.php:637 #, php-format msgid "Case is linked to a %1s" msgstr "Le cas est lié à un %1s" -#: inc/case.class.php:677 +#: inc/case.class.php:639 #, php-format msgid "Sub-case is linked to a %1s" msgstr "Le sous-cas est lié à un %1s" -#: inc/case.class.php:698 +#: inc/case.class.php:660 msgid "Case cancellation" msgstr "Annulation du cas" -#: inc/case.class.php:699 +#: inc/case.class.php:661 msgid "Cancel case" msgstr "Annuler cas" -#: inc/case.class.php:703 +#: inc/case.class.php:665 msgid "Confirm cancellation?" msgstr "Confirmer l’annulation ?" -#: inc/case.class.php:703 inc/profile.class.php:23 +#: inc/case.class.php:665 inc/profile.class.php:23 msgid "Cancel" msgstr "Annuler" -#: inc/case.class.php:717 +#: inc/case.class.php:679 msgid "Case deletion" msgstr "Suppression du cas" -#: inc/case.class.php:777 inc/case.class.php:1321 +#: inc/case.class.php:739 inc/case.class.php:1283 msgid "Title" msgstr "Titre" -#: inc/case.class.php:779 inc/case.class.php:1362 +#: inc/case.class.php:741 inc/case.class.php:1324 msgid "Sub-case of" msgstr "Sous-cas de" -#: inc/case.class.php:796 +#: inc/case.class.php:758 msgid "Add a new case" msgstr "Ajouter un nouveau cas" -#: inc/case.class.php:1227 +#: inc/case.class.php:1189 msgctxt "case_status" msgid "Draft" msgstr "Brouillon" -#: inc/case.class.php:1228 +#: inc/case.class.php:1190 msgctxt "case_status" msgid "To do" msgstr "A faire" -#: inc/case.class.php:1229 +#: inc/case.class.php:1191 msgctxt "case_status" msgid "Completed" msgstr "Terminé" -#: inc/case.class.php:1230 +#: inc/case.class.php:1192 msgctxt "case_status" msgid "Cancelled" msgstr "Annulé" -#: inc/case.class.php:1314 +#: inc/case.class.php:1276 msgid "ID" msgstr "ID" -#: inc/case.class.php:1335 inc/notificationtargetprocessmaker.class.php:72 -#| msgid "Item entity" +#: inc/case.class.php:1297 inc/notificationtargetprocessmaker.class.php:72 msgid "Item type" msgstr "Type de l'item" -#: inc/case.class.php:1342 +#: inc/case.class.php:1304 msgid "Item" msgstr "Item" -#: inc/case.class.php:1349 +#: inc/case.class.php:1311 msgid "Item entity" msgstr "Entité de l'item" -#: inc/case.class.php:1379 -#| msgid "Last update" +#: inc/case.class.php:1341 msgid "Last update date" msgstr "Date de dernière mise à jour" -#: inc/case.class.php:1392 +#: inc/case.class.php:1354 #, php-format -#| msgid "Case status" msgid "Case status is '%s'" msgstr "L'état du cas est '%s'" @@ -341,43 +364,43 @@ msgstr "Lien-cas" msgid "Synchronous" msgstr "Synchrone" -#: inc/caselink.class.php:80 inc/caselink.class.php:179 +#: inc/caselink.class.php:80 inc/caselink.class.php:180 msgid "External data" msgstr "Données externes" -#: inc/caselink.class.php:85 inc/caselink.class.php:185 +#: inc/caselink.class.php:85 inc/caselink.class.php:186 msgid "Self" msgstr "Self" -#: inc/caselink.class.php:90 inc/caselink.class.php:203 +#: inc/caselink.class.php:90 inc/caselink.class.php:204 msgid "Source task GUID" msgstr "GUID de la tâche source" -#: inc/caselink.class.php:98 inc/caselink.class.php:209 +#: inc/caselink.class.php:99 inc/caselink.class.php:210 msgid "Target task GUID" msgstr "GUID de la tâche cible" -#: inc/caselink.class.php:106 inc/caselink.class.php:221 +#: inc/caselink.class.php:107 inc/caselink.class.php:222 msgid "Target process GUID" msgstr "GUID du Processus cible" -#: inc/caselink.class.php:115 inc/caselink.class.php:215 +#: inc/caselink.class.php:116 inc/caselink.class.php:216 msgid "Target dynaform GUID" msgstr "GUID du dynaform cible" -#: inc/caselink.class.php:120 inc/caselink.class.php:227 +#: inc/caselink.class.php:121 inc/caselink.class.php:228 msgid "Source condition" msgstr "Condition d'activation du lien" -#: inc/caselink.class.php:126 inc/caselink.class.php:191 +#: inc/caselink.class.php:127 inc/caselink.class.php:192 msgid "Claim target task" msgstr "Tâche cible 'à réclamer'" -#: inc/caselink.class.php:136 +#: inc/caselink.class.php:137 msgid "Impersonate target task user" msgstr "Personnifier l'utilisateur de la tâche cible" -#: inc/caselink.class.php:141 inc/caselink.class.php:197 +#: inc/caselink.class.php:142 inc/caselink.class.php:198 msgid "External application JSON config" msgstr "Configuration JSON de l'application externe" @@ -390,9 +413,12 @@ msgid "ProcessMaker setup" msgstr "Configuration du serveur ProcessMaker" #: inc/config.class.php:159 -#| msgid "Server URL (must be in same domain than GLPI)" -msgid "Server URL (must be in same domain than GLPI, if GLPI is using HTTPS, PM server must also use HTTPS)" -msgstr "URL du serveur (doit être dans le même domaine que GLPI, si GLPI utilise HTTPS, alors PM doit aussi utiliser HTTPS)" +msgid "" +"Server URL (must be in same domain than GLPI, if GLPI is using HTTPS, PM " +"server must also use HTTPS)" +msgstr "" +"URL du serveur (doit être dans le même domaine que GLPI, si GLPI utilise " +"HTTPS, alors PM doit aussi utiliser HTTPS)" #: inc/config.class.php:163 msgid "Common domain with GLPI" @@ -412,7 +438,7 @@ msgstr "Nom du Workspace" #: inc/config.class.php:211 msgid "Server administrator name" -msgstr "Non de l'administreur du server ProcessMaker" +msgstr "Nom de l'administrateur du server ProcessMaker" #: inc/config.class.php:216 msgid "Server administrator password" @@ -451,7 +477,7 @@ msgid "Main Task Category (edit to change name)" msgstr "Catégorie principale des tâches (éditer pour changer le nom)" #: inc/config.class.php:286 -msgid "Task Writer (edit to change name)" +msgid "Task writer (edit to change name)" msgstr "Auteur des tâches (éditer pour changer le nom)" #: inc/config.class.php:306 @@ -484,7 +510,7 @@ msgstr "Version de PHP" #: inc/config.class.php:347 msgid "DB version" -msgstr "Version de la Db" +msgstr "Version de la DB" #: inc/config.class.php:348 msgid "DB server IP" @@ -515,30 +541,22 @@ msgid "eMail recipients" msgstr "Destinataires des emails" #: inc/notificationtargetprocessmaker.class.php:60 -#| msgid "Process case" -#| msgid_plural "Process cases" msgid "Process category" msgstr "Catégorie du processus" #: inc/notificationtargetprocessmaker.class.php:61 -#| msgid "Process case" -#| msgid_plural "Process cases" msgid "Process category id" msgstr "ID de la catégorie du processus" #: inc/notificationtargetprocessmaker.class.php:62 -#| msgid "Process case task" -#| msgid_plural "Process case tasks" msgid "Process category comment" msgstr "Commentaire de la catégorie du processus" #: inc/notificationtargetprocessmaker.class.php:63 -#| msgid "Case guid" msgid "Case id" msgstr "ID du cas" #: inc/notificationtargetprocessmaker.class.php:65 -#| msgid "Case deletion" msgid "Case description" msgstr "Description du cas" @@ -563,17 +581,14 @@ msgid "Value for key in 'ZZZ' assoc array (1-dimension array)" msgstr "Valeur pour la clé 'key' du tableau associatif à une dimension 'ZZZ'" #: inc/notificationtargetprocessmaker.class.php:73 -#| msgid "Item" msgid "Item id" msgstr "ID de l'item" #: inc/notificationtargetprocessmaker.class.php:74 -#| msgid "Item" msgid "Item URL" msgstr "URL de l'item" #: inc/notificationtargetprocessmaker.class.php:75 -#| msgid "Item entity" msgid "Item title" msgstr "Titre de l'item" @@ -586,11 +601,14 @@ msgid "YYY is to be replaced by any array variables" msgstr "YYY doit être remplacé par n'importe quel nom de tableau" #: inc/notificationtargetprocessmaker.class.php:90 -msgid "ZZZ is to be replaced by any assoc array variables (1-dimension array with key/value pairs)" -msgstr "ZZZ doit être replacé par n'importe quel nom de tableau associatif à une dimension (paire clé/valeur)" +msgid "" +"ZZZ is to be replaced by any assoc array variables (1-dimension array with " +"key/value pairs)" +msgstr "" +"ZZZ doit être replacé par n'importe quel nom de tableau associatif à une " +"dimension (paire clé/valeur)" #: inc/notificationtargettask.class.php:195 -#| msgid "Task delegation date" msgid "Task action" msgstr "Action de la tâche" @@ -608,7 +626,7 @@ msgstr "Type de processus" #: inc/process.class.php:455 msgid "Hide case num. & title" -msgstr "Cacher num. et titre du cas" +msgstr "Cacher le numéro et le titre du cas" #: inc/process.class.php:461 msgid "Insert Task Category" @@ -654,15 +672,18 @@ msgstr "Processus" #: inc/process.class.php:627 msgid "Hide case number and title in task descriptions" -msgstr "Masquer numéro et titre des cas dans les descriptions des tâches" +msgstr "Masquer le numéro et le titre des cas dans les descriptions des tâches" #: inc/process.class.php:632 msgid "Insert Task Category comments in Task Description" -msgstr "Insérer les commentaires des Catégories de Tâches dans les descriptions des Tâches" +msgstr "" +"Insérer les commentaires des catégories de tâches dans les descriptions des " +"tâches" #: inc/process.class.php:652 msgid "ITIL Category for Self-service interface (left empty to disable)" -msgstr "Catégorie ITIL pour l'interface libre-service (laissez vide pour désactiver)" +msgstr "" +"Catégorie ITIL pour l'interface libre-service (laissez vide pour désactiver)" #: inc/process.class.php:679 msgid "Type for Self-service interface" @@ -674,7 +695,6 @@ msgstr "Type de processus (à modifier uniquement si pas à jour)" #: inc/process.class.php:862 #, php-format -#| msgid "ProcessMaker plugin is under maintenance, please retry later, thank you." msgid "Process '%s' is under maintenance, please retry later, thank you." msgstr "Le processus '%s' est en maintenance, ré-essayez plus tard, merci." @@ -698,7 +718,8 @@ msgstr "Impossible de créer le cas : pas de droits pour cela !" #: inc/processmaker.class.php:1012 msgid "Syncs GLPI users and groups into ProcessMaker." -msgstr "Synchronisation des utilisateurs GLPI et des groups avec ProcessMaker." +msgstr "" +"Synchronisation des utilisateurs GLPI et des groupes avec ProcessMaker." #: inc/processmaker.class.php:1014 msgid "Cleaning of orphan cases." @@ -712,26 +733,33 @@ msgstr "Nombre de jours avant nettoyage des cas orphelins" msgid "To apply task actions between cases." msgstr "Pour appliquer des actions de tâches entre cas." -#: inc/processmaker.class.php:1720 +#: inc/processmaker.class.php:1707 msgid "Case title: " msgstr "Titre du cas : " -#: inc/processmaker.class.php:2275 +#: inc/processmaker.class.php:2262 msgid "A 'Case' is running!" msgstr "Un 'Cas' est en cours !" -#: inc/processmaker.class.php:2276 +#: inc/processmaker.class.php:2263 msgid "You must manage it first (see 'Process - Case' tab)!" msgstr "Vous devez d'abord le terminer (voir onglet 'Processus - Cas') !" -#: inc/processmaker.class.php:2774 +#: inc/processmaker.class.php:2779 #, php-format -msgid "Unable to derivate case! Retry in a moment, or ask your administrator.
Error code: %u
Error message: %s
" -msgstr "Impossible de dériver le cas ! Ré-essayez dans un moment, ou demandez à votre administrateur.
Code d'erreur : %u
Message d'erreur : %s
" +msgid "" +"Unable to derivate case! Retry in a moment, or ask your administrator." +"
Error code: %u
Error message: %s
" +msgstr "" +"Impossible de dériver le cas ! Ré-essayez dans un moment, ou demandez à " +"votre administrateur.
Code d'erreur : %u
Message d'erreur : %s
" -#: inc/processmaker.class.php:3281 -msgid "ProcessMaker plugin is under maintenance, please retry later, thank you." -msgstr "Le plugin ProcessMaker est en maintenance, veuillez ré-essayer plus tard, merci." +#: inc/processmaker.class.php:3283 +msgid "" +"ProcessMaker plugin is under maintenance, please retry later, thank you." +msgstr "" +"Le plugin ProcessMaker est en maintenance, veuillez ré-essayer plus tard, " +"merci." #: inc/profile.class.php:17 msgid "Process configuration" @@ -743,7 +771,7 @@ msgstr "Cas" #: inc/profile.class.php:23 msgid "Ad Hoc user re-assign" -msgstr "Ré-assignation d'un utilisateur Ad Hoc" +msgstr "Réattribution d'un utilisateur Ad Hoc" #: inc/task.class.php:29 msgid "Process case task" @@ -756,47 +784,161 @@ msgid "Sub-case task(s)" msgstr "Tache(s) du sous-cas" #: inc/taskcategory.class.php:24 inc/taskcategory.class.php:116 -#| msgid "Process case" -#| msgid_plural "Process cases" msgid "Process task" msgstr "Tâche du processus" -#: inc/taskcategory.class.php:29 -#| msgid "Task List" +#: inc/taskcategory.class.php:29 inc/taskcategory.class.php:39 msgid "Task list" msgstr "List des tâches" -#: inc/taskcategory.class.php:39 -msgid "Task List" -msgstr "Liste des tâches" - #: inc/taskcategory.class.php:40 inc/taskcategory.class.php:118 msgid "Task name" -msgstr "Nom de la Tâche" +msgstr "Nom de la tâche" #: inc/taskcategory.class.php:42 inc/taskcategory.class.php:68 #: inc/taskcategory.class.php:121 inc/taskcategory.class.php:155 msgid "Start" msgstr "Démarrer" -#: inc/taskcategory.class.php:43 inc/taskcategory.class.php:122 -msgid "Task GUID" -msgstr "GUID de la Tâche" - #: inc/taskcategory.class.php:46 inc/taskcategory.class.php:86 #: inc/taskcategory.class.php:125 inc/taskcategory.class.php:173 msgid "Sub-process" msgstr "Sous-processus" #: inc/taskcategory.class.php:117 -#| msgid "Process case" -#| msgid_plural "Process cases" msgid "Process name" -msgstr "Nom du procesus" +msgstr "Nom du processus" -#~ msgid "Delete case" +#, fuzzy +#~| msgid "Delete case" +#~ msgid "Delete permanently" #~ msgstr "Delete case" +#, fuzzy +#~| msgid "None!" +#~ msgid "None" +#~ msgstr "Aucun !" + +#, fuzzy +#~| msgid "Maintenance" +#~ msgid "Maintenance mode" +#~ msgstr "Maintenance" + +#, fuzzy +#~| msgid "Case id" +#~ msgid "Case URL" +#~ msgstr "ID du cas" + +#, fuzzy +#~| msgid "Task guid" +#~ msgid "Task add" +#~ msgstr "Guid de la tâche" + +#, fuzzy +#~| msgid "Task re-assigned!" +#~ msgid "Task re-assign" +#~ msgstr "Tâche réattribuée !" + +#, fuzzy +#~| msgid "Task un-claimed!" +#~ msgid "Task un-claim" +#~ msgstr "Annulation de l'attribution de la tâche effectuée !" + +#, fuzzy +#~| msgid "Task name" +#~ msgid "Task done" +#~ msgstr "Nom de la tâche" + +#, fuzzy +#~| msgid "Send reminder" +#~ msgid "Task reminder" +#~ msgstr "Envoyer un rappel" + +#, fuzzy +#~| msgid "Creation date" +#~ msgid "Opening date" +#~ msgstr "Date de création" + +#, fuzzy +#~| msgid "Case description" +#~ msgid "Description" +#~ msgstr "Description du cas" + +#, fuzzy +#~| msgid "Process category id" +#~ msgid "Category id" +#~ msgstr "ID de la catégorie du processus" + +#, fuzzy +#~| msgid "Process category comment" +#~ msgid "Category comment" +#~ msgstr "Commentaire de la catégorie du processus" + +#, fuzzy +#~| msgid "Task action" +#~ msgid "Total duration" +#~ msgstr "Action de la tâche" + +#, fuzzy +#~| msgid "Re-assign task" +#~ msgid "User assigned to task" +#~ msgstr "Réattribuer la tâche" + +#, fuzzy +#~| msgid "Case is linked to a %1s" +#~ msgid "User login assigned to task" +#~ msgstr "Le cas est lié à un %1s" + +#, fuzzy +#~| msgid "Re-assign task" +#~ msgid "Group assigned to task" +#~ msgstr "Réattribuer la tâche" + +#, fuzzy +#~| msgid "Start" +#~ msgid "Start date" +#~ msgstr "Démarrer" + +#, fuzzy +#~| msgid "Last update" +#~ msgid "Last updater" +#~ msgstr "Dernière mise à jour" + +#, fuzzy +#~| msgid "Task delegation date" +#~ msgid "Delegation index" +#~ msgstr "Date d'attribution de tâche" + +#, fuzzy +#~| msgid "Delete case" +#~ msgid "Delete" +#~ msgstr "Delete case" + +#, fuzzy +#~| msgctxt "case_status" +#~| msgid "Completed" +#~ msgid "Complete name" +#~ msgstr "Terminé" + +#, fuzzy +#~| msgid "Re-assign" +#~ msgctxt "processmaker" +#~ msgid "Re-assign" +#~ msgstr "Réattribuer" + +#, fuzzy +#~| msgid "Process case" +#~| msgid_plural "Process cases" +#~ msgctxt "processmaker" +#~ msgid "Process case" +#~ msgstr "Cas du processus" + +#~ msgid "Task GUID" +#~ msgstr "Task GUID" + +#~ msgid "Task List" +#~ msgstr "Task List" + #~ msgid "Case item" #~ msgstr "Case item" diff --git a/locales/source.po b/locales/source.po index ea91229..ffb2ad1 100644 --- a/locales/source.po +++ b/locales/source.po @@ -1,15 +1,15 @@ msgid "" msgstr "" -"Project-Id-Version: Processmaker plugin 3.3.0\n" -"POT-Creation-Date: 2020-07-13 09:41+0200\n" -"PO-Revision-Date: 2020-07-13 11:03+0200\n" +"Project-Id-Version: Processmaker plugin 3.4.0\n" +"POT-Creation-Date: 2021-02-15 17:32+0100\n" +"PO-Revision-Date: 2021-02-15 17:32+0100\n" "Last-Translator: tomolimo\n" "Language-Team: en_GB\n" "Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.3.1\n" +"X-Generator: Poedit 2.4.2\n" "X-Poedit-Basepath: ..\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Poedit-KeywordsList: ;__:1,2t;_e:1,2t;_x:1c,2,3t;_n:1,2,4t;__s:1,2t;" @@ -24,808 +24,892 @@ msgstr "" #: ajax/task_users.php:36 msgid "Re-assign task to" -msgstr "Re-assign task to" +msgstr "" -#: ajax/task_users.php:60 ajax/task_users.php:61 ajax/task_users.php:124 +#: ajax/task_users.php:67 ajax/task_users.php:68 ajax/task_users.php:135 msgid "Re-assign" -msgstr "Re-assign" +msgstr "" -#: ajax/task_users.php:110 -#| msgid "Task already assigned to this person!" -msgid "Task is already assigned to this user or group!" -msgstr "Task is already assigned to this user or group!" +#: ajax/task_users.php:100 +msgid "Input at least 10 words in English to justify." +msgstr "" -#: ajax/task_users.php:110 ajax/task_users.php:122 -#| msgid "Re-assign task to" +#: ajax/task_users.php:118 +msgid "Task is already un-assigned!" +msgstr "" + +#: ajax/task_users.php:118 ajax/task_users.php:120 ajax/task_users.php:133 msgid "Re-assign task" -msgstr "Re-assign task" +msgstr "" -#: ajax/task_users.php:114 ajax/task_users.php:119 -#| msgid "Claim target task" +#: ajax/task_users.php:120 +msgid "Task is already assigned to this user!" +msgstr "" + +#: ajax/task_users.php:125 ajax/task_users.php:130 msgid "Un-claim task" -msgstr "Un-claim task" +msgstr "" -#: ajax/task_users.php:115 +#: ajax/task_users.php:126 msgid "" "Please input reason to un-claim
(task will be re-assigned to former " "group):" msgstr "" -"Please input reason to un-claim
(task will be re-assigned to former " -"group):" -#: ajax/task_users.php:116 +#: ajax/task_users.php:127 msgid "Un-claim" -msgstr "Un-claim" +msgstr "" -#: ajax/task_users.php:119 -msgid "Can\\'t un-assign Task!" -msgstr "Can\\'t un-assign Task!" - -#: ajax/task_users.php:123 -msgid "Please input reason to re-assign:" -msgstr "Please input reason to re-assign:" +#: ajax/task_users.php:130 +msgid "Can't un-assign task!" +msgstr "" #: ajax/task_users.php:134 +msgid "Please input reason to re-assign:" +msgstr "" + +#: ajax/task_users.php:145 msgid "Send reminder" -msgstr "Send reminder" +msgstr "" #: front/case.form.php:32 msgid "Case has been deleted!" -msgstr "Case has been deleted!" +msgstr "" #: front/case.form.php:34 msgid "Unable to delete case!" -msgstr "Unable to delete case!" +msgstr "" #: front/case.form.php:46 msgid "Case has been cancelled!" -msgstr "Case has been cancelled!" +msgstr "" #: front/case.form.php:48 front/case.form.php:51 msgid "Unable to cancel case!" -msgstr "Unable to cancel case!" +msgstr "" -#: front/case.form.php:70 front/case.form.php:72 inc/case.class.php:1310 +#: front/case.form.php:70 front/case.form.php:72 inc/case.class.php:1272 msgid "Process cases" -msgstr "Process cases" +msgstr "" #: front/case.php:5 front/caselink.form.php:29 front/caselink.php:5 -#: front/process.form.php:27 front/process.php:5 inc/caselink.class.php:157 +#: front/process.form.php:27 front/process.php:5 inc/caselink.class.php:158 #: inc/config.class.php:50 inc/config.class.php:363 inc/process.class.php:409 #: inc/profile.class.php:52 inc/profile.class.php:83 msgid "ProcessMaker" -msgstr "ProcessMaker" +msgstr "" #: front/processmaker.form.php:80 msgid "Task re-assigned!" -msgstr "Task re-assigned!" +msgstr "" #: front/processmaker.form.php:82 msgid "Error re-assigning task: " -msgstr "Error re-assigning task: " +msgstr "" #: front/processmaker.form.php:93 -#| msgid "Task name" msgid "Task un-claimed!" -msgstr "Task un-claimed!" +msgstr "" #: front/processmaker.form.php:95 msgid "" "Can't un-claim task! Verify 'Assignement Rules' in the process definition." msgstr "" -"Can't un-claim task! Verify 'Assignement Rules' in the process definition." #: front/processmaker.helpdesk.form.php:21 msgid "Process - Case" -msgstr "Process - Case" +msgstr "" -#: front/processmaker.helpdesk.form.php:24 inc/case.class.php:799 +#: front/processmaker.helpdesk.form.php:24 inc/case.class.php:761 msgid "Select the process you want to add" -msgstr "Select the process you want to add" +msgstr "" #: hook.php:9 inc/taskcategory.class.php:214 msgid "Synchronize Task List" -msgstr "Synchronize Task List" +msgstr "" #: hook.php:76 inc/case.class.php:89 msgid "Case" -msgstr "Case" +msgstr "" -#: hook.php:76 inc/case.class.php:778 inc/case.class.php:1355 +#: hook.php:76 inc/case.class.php:740 inc/case.class.php:1317 msgid "Status" -msgstr "Status" +msgstr "" -#: inc/case.class.php:25 inc/case.class.php:102 inc/case.class.php:104 +#: inc/case.class.php:25 msgid "Process case" msgid_plural "Process cases" -msgstr[0] "Process case" -msgstr[1] "Process cases" +msgstr[0] "" +msgstr[1] "" #: inc/case.class.php:92 msgid "Sub-case" -msgstr "Sub-case" +msgstr "" -#: inc/case.class.php:303 +#: inc/case.class.php:265 #, php-format msgid "" "Task un-claimed!
Case: %s
Task: \"%s\" has been " "un-assigned from \"%s\" and assigned to \"%s\" group.
Reason: %s" msgstr "" -"Task un-claimed!
Case: %s
Task: \"%s\" has been " -"un-assigned from \"%s\" and assigned to \"%s\" group.
Reason: %s" -#: inc/case.class.php:420 +#: inc/case.class.php:382 #, php-format msgid "" "Task re-assigned!
Case: %s
Task: \"%s\" has " "been re-assigned from \"%s\" to \"%s\".
Reason: %s" msgstr "" -"Task re-assigned!
Case: %s
Task: \"%s\" has " -"been re-assigned from \"%s\" to \"%s\".
Reason: %s" -#: inc/case.class.php:429 +#: inc/case.class.php:391 #, php-format msgid "" "Task assigned!
Case: %s
Task: \"%s\" has been " "assigned to \"%s\".
Reason: %s" msgstr "" -"Task assigned!
Case: %s
Task: \"%s\" has been " -"assigned to \"%s\".
Reason: %s" -#: inc/case.class.php:510 +#: inc/case.class.php:472 msgid "Current task(s) properties" -msgstr "Current task(s) properties" +msgstr "" -#: inc/case.class.php:514 inc/task.class.php:283 +#: inc/case.class.php:476 inc/task.class.php:283 msgid "Task" -msgstr "Task" +msgstr "" -#: inc/case.class.php:515 inc/task.class.php:284 +#: inc/case.class.php:477 inc/task.class.php:284 inc/taskcategory.class.php:43 +#: inc/taskcategory.class.php:122 msgid "Task guid" -msgstr "Task guid" +msgstr "" -#: inc/case.class.php:516 inc/task.class.php:285 +#: inc/case.class.php:478 inc/task.class.php:285 msgid "Current user" -msgstr "Current user" +msgstr "" -#: inc/case.class.php:517 inc/task.class.php:286 +#: inc/case.class.php:479 inc/task.class.php:286 msgid "Task delegation date" -msgstr "Task delegation date" +msgstr "" -#: inc/case.class.php:539 inc/task.class.php:295 +#: inc/case.class.php:501 inc/task.class.php:295 msgid "To be claimed" -msgstr "To be claimed" +msgstr "" -#: inc/case.class.php:575 +#: inc/case.class.php:537 msgid "Sub-case properties" -msgstr "Sub-case properties" +msgstr "" -#: inc/case.class.php:578 +#: inc/case.class.php:540 msgid "Parent case properties" -msgstr "Parent case properties" +msgstr "" -#: inc/case.class.php:580 +#: inc/case.class.php:542 msgid "Case properties" -msgstr "Case properties" +msgstr "" -#: inc/case.class.php:585 inc/case.class.php:776 inc/case.class.php:1328 +#: inc/case.class.php:547 inc/case.class.php:738 inc/case.class.php:1290 #: inc/process.class.php:576 msgid "Process" -msgstr "Process" +msgstr "" -#: inc/case.class.php:586 inc/notificationtargetprocessmaker.class.php:64 +#: inc/case.class.php:548 inc/notificationtargetprocessmaker.class.php:64 msgid "Case title" -msgstr "Case title" +msgstr "" -#: inc/case.class.php:587 +#: inc/case.class.php:549 msgid "Case number" -msgstr "Case number" +msgstr "" -#: inc/case.class.php:588 +#: inc/case.class.php:550 msgid "Case status" -msgstr "Case status" +msgstr "" -#: inc/case.class.php:589 +#: inc/case.class.php:551 msgid "Case guid" -msgstr "Case guid" +msgstr "" -#: inc/case.class.php:590 +#: inc/case.class.php:552 msgid "Creator" -msgstr "Creator" +msgstr "" -#: inc/case.class.php:591 inc/case.class.php:1370 +#: inc/case.class.php:553 inc/case.class.php:1332 msgid "Creation date" -msgstr "Creation date" +msgstr "" -#: inc/case.class.php:592 +#: inc/case.class.php:554 msgid "Last update" -msgstr "Last update" +msgstr "" -#: inc/case.class.php:675 +#: inc/case.class.php:637 #, php-format msgid "Case is linked to a %1s" -msgstr "Case is linked to a %1s" +msgstr "" -#: inc/case.class.php:677 +#: inc/case.class.php:639 #, php-format msgid "Sub-case is linked to a %1s" -msgstr "Sub-case is linked to a %1s" +msgstr "" -#: inc/case.class.php:698 +#: inc/case.class.php:660 msgid "Case cancellation" -msgstr "Case cancellation" +msgstr "" -#: inc/case.class.php:699 +#: inc/case.class.php:661 msgid "Cancel case" -msgstr "Cancel case" +msgstr "" -#: inc/case.class.php:703 +#: inc/case.class.php:665 msgid "Confirm cancellation?" -msgstr "Confirm cancellation?" +msgstr "" -#: inc/case.class.php:703 inc/profile.class.php:23 +#: inc/case.class.php:665 inc/profile.class.php:23 msgid "Cancel" -msgstr "Cancel" +msgstr "" -#: inc/case.class.php:717 +#: inc/case.class.php:679 msgid "Case deletion" -msgstr "Case deletion" +msgstr "" -#: inc/case.class.php:777 inc/case.class.php:1321 +#: inc/case.class.php:739 inc/case.class.php:1283 msgid "Title" -msgstr "Title" +msgstr "" -#: inc/case.class.php:779 inc/case.class.php:1362 +#: inc/case.class.php:741 inc/case.class.php:1324 msgid "Sub-case of" -msgstr "Sub-case of" +msgstr "" -#: inc/case.class.php:796 +#: inc/case.class.php:758 msgid "Add a new case" -msgstr "Add a new case" +msgstr "" -#: inc/case.class.php:1227 +#: inc/case.class.php:1189 msgctxt "case_status" msgid "Draft" -msgstr "Draft" +msgstr "" -#: inc/case.class.php:1228 +#: inc/case.class.php:1190 msgctxt "case_status" msgid "To do" -msgstr "To do" +msgstr "" -#: inc/case.class.php:1229 +#: inc/case.class.php:1191 msgctxt "case_status" msgid "Completed" -msgstr "Completed" +msgstr "" -#: inc/case.class.php:1230 +#: inc/case.class.php:1192 msgctxt "case_status" msgid "Cancelled" -msgstr "Cancelled" +msgstr "" -#: inc/case.class.php:1314 +#: inc/case.class.php:1276 msgid "ID" -msgstr "ID" +msgstr "" -#: inc/case.class.php:1335 inc/notificationtargetprocessmaker.class.php:72 -#| msgid "Item entity" +#: inc/case.class.php:1297 inc/notificationtargetprocessmaker.class.php:72 msgid "Item type" -msgstr "Item type" +msgstr "" -#: inc/case.class.php:1342 +#: inc/case.class.php:1304 msgid "Item" -msgstr "Item" +msgstr "" -#: inc/case.class.php:1349 +#: inc/case.class.php:1311 msgid "Item entity" -msgstr "Item entity" +msgstr "" -#: inc/case.class.php:1379 -#| msgid "Last update" +#: inc/case.class.php:1341 msgid "Last update date" -msgstr "Last update date" +msgstr "" -#: inc/case.class.php:1392 +#: inc/case.class.php:1354 #, php-format -#| msgid "Case status" msgid "Case status is '%s'" -msgstr "Case status is '%s'" +msgstr "" #: inc/casechangelog.class.php:36 msgid "Change log" -msgstr "Change log" +msgstr "" #: inc/casedynaform.class.php:83 msgid "Dynaforms" -msgstr "Dynaforms" +msgstr "" #: inc/casehistory.class.php:36 msgid "History" -msgstr "History" +msgstr "" #: inc/caselink.class.php:51 msgid "Case-links" -msgstr "Case-links" +msgstr "" #: inc/caselink.class.php:53 msgid "Case-link" -msgstr "Case-link" +msgstr "" #: inc/caselink.class.php:75 msgid "Synchronous" -msgstr "Synchronous" +msgstr "" -#: inc/caselink.class.php:80 inc/caselink.class.php:179 +#: inc/caselink.class.php:80 inc/caselink.class.php:180 msgid "External data" -msgstr "External data" +msgstr "" -#: inc/caselink.class.php:85 inc/caselink.class.php:185 +#: inc/caselink.class.php:85 inc/caselink.class.php:186 msgid "Self" -msgstr "Self" +msgstr "" -#: inc/caselink.class.php:90 inc/caselink.class.php:203 +#: inc/caselink.class.php:90 inc/caselink.class.php:204 msgid "Source task GUID" -msgstr "Source task GUID" +msgstr "" -#: inc/caselink.class.php:98 inc/caselink.class.php:209 +#: inc/caselink.class.php:99 inc/caselink.class.php:210 msgid "Target task GUID" -msgstr "Target task GUID" +msgstr "" -#: inc/caselink.class.php:106 inc/caselink.class.php:221 +#: inc/caselink.class.php:107 inc/caselink.class.php:222 msgid "Target process GUID" -msgstr "Target process GUID" +msgstr "" -#: inc/caselink.class.php:115 inc/caselink.class.php:215 +#: inc/caselink.class.php:116 inc/caselink.class.php:216 msgid "Target dynaform GUID" -msgstr "Target dynaform GUID" +msgstr "" -#: inc/caselink.class.php:120 inc/caselink.class.php:227 +#: inc/caselink.class.php:121 inc/caselink.class.php:228 msgid "Source condition" -msgstr "Source condition" +msgstr "" -#: inc/caselink.class.php:126 inc/caselink.class.php:191 +#: inc/caselink.class.php:127 inc/caselink.class.php:192 msgid "Claim target task" -msgstr "Claim target task" +msgstr "" -#: inc/caselink.class.php:136 +#: inc/caselink.class.php:137 msgid "Impersonate target task user" -msgstr "Impersonate target task user" +msgstr "" -#: inc/caselink.class.php:141 inc/caselink.class.php:197 +#: inc/caselink.class.php:142 inc/caselink.class.php:198 msgid "External application JSON config" -msgstr "External application JSON config" +msgstr "" #: inc/casemap.class.php:44 msgid "Map" -msgstr "Map" +msgstr "" #: inc/config.class.php:41 msgid "ProcessMaker setup" -msgstr "ProcessMaker setup" +msgstr "" #: inc/config.class.php:159 -#| msgid "Server URL (must be in same domain than GLPI)" msgid "" "Server URL (must be in same domain than GLPI, if GLPI is using HTTPS, PM " "server must also use HTTPS)" msgstr "" -"Server URL (must be in same domain than GLPI, if GLPI is using HTTPS, PM " -"server must also use HTTPS)" #: inc/config.class.php:163 msgid "Common domain with GLPI" -msgstr "Common domain with GLPI" +msgstr "" #: inc/config.class.php:192 msgid "None!" -msgstr "None!" +msgstr "" #: inc/config.class.php:201 msgid "Verify SSL certificate" -msgstr "Verify SSL certificate" +msgstr "" #: inc/config.class.php:206 msgid "Workspace Name" -msgstr "Workspace Name" +msgstr "" #: inc/config.class.php:211 msgid "Server administrator name" -msgstr "Server administrator name" +msgstr "" #: inc/config.class.php:216 msgid "Server administrator password" -msgstr "Server administrator password" +msgstr "" #: inc/config.class.php:222 inc/config.class.php:262 msgid "Connection status" -msgstr "Connection status" +msgstr "" #: inc/config.class.php:238 msgid "SQL server setup" -msgstr "SQL server setup" +msgstr "" #: inc/config.class.php:241 msgid "SQL server (MariaDB or MySQL)" -msgstr "SQL server (MariaDB or MySQL)" +msgstr "" #: inc/config.class.php:246 msgid "Database name" -msgstr "Database name" +msgstr "" #: inc/config.class.php:251 msgid "SQL user" -msgstr "SQL user" +msgstr "" #: inc/config.class.php:256 msgid "SQL password" -msgstr "SQL password" +msgstr "" #: inc/config.class.php:273 msgid "Theme Name" -msgstr "Theme Name" +msgstr "" #: inc/config.class.php:279 msgid "Main Task Category (edit to change name)" -msgstr "Main Task Category (edit to change name)" +msgstr "" #: inc/config.class.php:286 -msgid "Task Writer (edit to change name)" -msgstr "Task Writer (edit to change name)" +msgid "Task writer (edit to change name)" +msgstr "" #: inc/config.class.php:306 msgid "Group in ProcessMaker which will contain all GLPI users" -msgstr "Group in ProcessMaker which will contain all GLPI users" +msgstr "" #: inc/config.class.php:321 inc/process.class.php:510 inc/process.class.php:637 msgid "Max cases per item (0=unlimited)" -msgstr "Max cases per item (0=unlimited)" +msgstr "" #: inc/config.class.php:340 msgid "Processmaker system information" -msgstr "Processmaker system information" +msgstr "" #: inc/config.class.php:343 inc/config.class.php:353 msgid "Version" -msgstr "Version" +msgstr "" #: inc/config.class.php:344 msgid "Web server" -msgstr "Web server" +msgstr "" #: inc/config.class.php:345 msgid "Server name" -msgstr "Server name" +msgstr "" #: inc/config.class.php:346 msgid "PHP version" -msgstr "PHP version" +msgstr "" #: inc/config.class.php:347 msgid "DB version" -msgstr "DB version" +msgstr "" #: inc/config.class.php:348 msgid "DB server IP" -msgstr "DB server IP" +msgstr "" #: inc/config.class.php:349 msgid "DB name" -msgstr "DB name" +msgstr "" #: inc/config.class.php:350 msgid "User browser" -msgstr "User browser" +msgstr "" #: inc/config.class.php:351 msgid "User IP" -msgstr "User IP" +msgstr "" #: inc/config.class.php:353 msgid "Not yet!" -msgstr "Not yet!" +msgstr "" #: inc/notificationtargetcase.class.php:26 msgid "Send email" -msgstr "Send email" +msgstr "" #: inc/notificationtargetcase.class.php:37 msgid "eMail recipients" -msgstr "eMail recipients" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:60 -#| msgid "Process case" -#| msgid_plural "Process cases" msgid "Process category" -msgstr "Process category" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:61 -#| msgid "Process case" -#| msgid_plural "Process cases" msgid "Process category id" -msgstr "Process category id" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:62 -#| msgid "Process case task" -#| msgid_plural "Process case tasks" msgid "Process category comment" -msgstr "Process category comment" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:63 -#| msgid "Case guid" msgid "Case id" -msgstr "Case id" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:65 -#| msgid "Case deletion" msgid "Case description" -msgstr "Case description" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:67 msgid "Case variable 'XXX'" -msgstr "Case variable 'XXX'" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:68 msgid "List of values in 'YYY' array" -msgstr "List of values in 'YYY' array" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:69 msgid "Number of rows in 'YYY' array" -msgstr "Number of rows in 'YYY' array" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:70 msgid "Value for colname in 'YYY' array" -msgstr "Value for colname in 'YYY' array" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:71 msgid "Value for key in 'ZZZ' assoc array (1-dimension array)" -msgstr "Value for key in 'ZZZ' assoc array (1-dimension array)" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:73 -#| msgid "Item" msgid "Item id" -msgstr "Item id" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:74 -#| msgid "Item" msgid "Item URL" -msgstr "Item URL" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:75 -#| msgid "Item entity" msgid "Item title" -msgstr "Item title" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:83 msgid "XXX is to be replaced by any case variable names" -msgstr "XXX is to be replaced by any case variable names" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:86 msgid "YYY is to be replaced by any array variables" -msgstr "YYY is to be replaced by any array variables" +msgstr "" #: inc/notificationtargetprocessmaker.class.php:90 msgid "" "ZZZ is to be replaced by any assoc array variables (1-dimension array with " "key/value pairs)" msgstr "" -"ZZZ is to be replaced by any assoc array variables (1-dimension array with " -"key/value pairs)" #: inc/notificationtargettask.class.php:195 -#| msgid "Task delegation date" msgid "Task action" -msgstr "Task action" +msgstr "" #: inc/process.class.php:366 msgid "Synchronize Process List" -msgstr "Synchronize Process List" +msgstr "" #: inc/process.class.php:443 inc/process.class.php:617 msgid "Process GUID" -msgstr "Process GUID" +msgstr "" #: inc/process.class.php:449 msgid "Process type" -msgstr "Process type" +msgstr "" #: inc/process.class.php:455 msgid "Hide case num. & title" -msgstr "Hide case num. & title" +msgstr "" #: inc/process.class.php:461 msgid "Insert Task Category" -msgstr "Insert Task Category" +msgstr "" #: inc/process.class.php:473 msgid "Ticket type (self-service)" -msgstr "Ticket type (self-service)" +msgstr "" #: inc/process.class.php:480 inc/process.class.php:642 msgid "Visible in Incident for Central interface" -msgstr "Visible in Incident for Central interface" +msgstr "" #: inc/process.class.php:486 inc/process.class.php:647 msgid "Visible in Request for Central interface" -msgstr "Visible in Request for Central interface" +msgstr "" #: inc/process.class.php:492 inc/process.class.php:699 msgid "Visible in Change" -msgstr "Visible in Change" +msgstr "" #: inc/process.class.php:498 inc/process.class.php:704 msgid "Visible in Problem" -msgstr "Visible in Problem" +msgstr "" #: inc/process.class.php:504 msgid "Maintenance" -msgstr "Maintenance" +msgstr "" #: inc/process.class.php:547 msgctxt "process_type" msgid "Classic" -msgstr "Classic" +msgstr "" #: inc/process.class.php:548 msgctxt "process_type" msgid "BPMN" -msgstr "BPMN" +msgstr "" #: inc/process.class.php:574 msgid "Processes" -msgstr "Processes" +msgstr "" #: inc/process.class.php:627 msgid "Hide case number and title in task descriptions" -msgstr "Hide case number and title in task descriptions" +msgstr "" #: inc/process.class.php:632 msgid "Insert Task Category comments in Task Description" -msgstr "Insert Task Category comments in Task Description" +msgstr "" #: inc/process.class.php:652 msgid "ITIL Category for Self-service interface (left empty to disable)" -msgstr "ITIL Category for Self-service interface (left empty to disable)" +msgstr "" #: inc/process.class.php:679 msgid "Type for Self-service interface" -msgstr "Type for Self-service interface" +msgstr "" #: inc/process.class.php:709 msgid "Process type (to be changed only if not up-to-date)" -msgstr "Process type (to be changed only if not up-to-date)" +msgstr "" #: inc/process.class.php:862 #, php-format -#| msgid "" -#| "ProcessMaker plugin is under maintenance, please retry later, thank you." msgid "Process '%s' is under maintenance, please retry later, thank you." -msgstr "Process '%s' is under maintenance, please retry later, thank you." +msgstr "" #: inc/process_profile.class.php:26 inc/process_profile.class.php:45 msgid "Authorizations" -msgstr "Authorizations" +msgstr "" #: inc/process_profile.class.php:179 msgid "Authorization not added: already existing!" -msgstr "Authorization not added: already existing!" +msgstr "" #: inc/processmaker.class.php:116 inc/processmaker.class.php:118 msgctxt "errors" msgid "Error creating case!" -msgstr "Error creating case!" +msgstr "" #: inc/processmaker.class.php:117 msgctxt "errors" msgid "Can't create case: no rights for it!" -msgstr "Can't create case: no rights for it!" +msgstr "" #: inc/processmaker.class.php:1012 msgid "Syncs GLPI users and groups into ProcessMaker." -msgstr "Syncs GLPI users and groups into ProcessMaker." +msgstr "" #: inc/processmaker.class.php:1014 msgid "Cleaning of orphan cases." -msgstr "Cleaning of orphan cases." +msgstr "" #: inc/processmaker.class.php:1014 msgid "Number of days to keep orphan cases" -msgstr "Number of days to keep orphan cases" +msgstr "" #: inc/processmaker.class.php:1016 msgid "To apply task actions between cases." -msgstr "To apply task actions between cases." +msgstr "" -#: inc/processmaker.class.php:1720 +#: inc/processmaker.class.php:1707 msgid "Case title: " -msgstr "Case title: " +msgstr "" -#: inc/processmaker.class.php:2275 +#: inc/processmaker.class.php:2262 msgid "A 'Case' is running!" -msgstr "A 'Case' is running!" +msgstr "" -#: inc/processmaker.class.php:2276 +#: inc/processmaker.class.php:2263 msgid "You must manage it first (see 'Process - Case' tab)!" -msgstr "You must manage it first (see 'Process - Case' tab)!" +msgstr "" -#: inc/processmaker.class.php:2774 +#: inc/processmaker.class.php:2779 #, php-format msgid "" "Unable to derivate case! Retry in a moment, or ask your administrator." "
Error code: %u
Error message: %s
" msgstr "" -"Unable to derivate case! Retry in a moment, or ask your administrator." -"
Error code: %u
Error message: %s
" -#: inc/processmaker.class.php:3281 +#: inc/processmaker.class.php:3283 msgid "" "ProcessMaker plugin is under maintenance, please retry later, thank you." msgstr "" -"ProcessMaker plugin is under maintenance, please retry later, thank you." #: inc/profile.class.php:17 msgid "Process configuration" -msgstr "Process configuration" +msgstr "" #: inc/profile.class.php:21 msgid "Cases" -msgstr "Cases" +msgstr "" #: inc/profile.class.php:23 msgid "Ad Hoc user re-assign" -msgstr "Ad Hoc user re-assign" +msgstr "" #: inc/task.class.php:29 msgid "Process case task" msgid_plural "Process case tasks" -msgstr[0] "Process case task" -msgstr[1] "Process case tasks" +msgstr[0] "" +msgstr[1] "" #: inc/task.class.php:278 msgid "Sub-case task(s)" -msgstr "Sub-case task(s)" +msgstr "" #: inc/taskcategory.class.php:24 inc/taskcategory.class.php:116 -#| msgid "Process case" -#| msgid_plural "Process cases" msgid "Process task" -msgstr "Process task" +msgstr "" -#: inc/taskcategory.class.php:29 -#| msgid "Task List" +#: inc/taskcategory.class.php:29 inc/taskcategory.class.php:39 msgid "Task list" -msgstr "Task list" - -#: inc/taskcategory.class.php:39 -msgid "Task List" -msgstr "Task List" +msgstr "" #: inc/taskcategory.class.php:40 inc/taskcategory.class.php:118 msgid "Task name" -msgstr "Task name" +msgstr "" #: inc/taskcategory.class.php:42 inc/taskcategory.class.php:68 #: inc/taskcategory.class.php:121 inc/taskcategory.class.php:155 msgid "Start" -msgstr "Start" - -#: inc/taskcategory.class.php:43 inc/taskcategory.class.php:122 -msgid "Task GUID" -msgstr "Task GUID" +msgstr "" #: inc/taskcategory.class.php:46 inc/taskcategory.class.php:86 #: inc/taskcategory.class.php:125 inc/taskcategory.class.php:173 msgid "Sub-process" -msgstr "Sub-process" +msgstr "" #: inc/taskcategory.class.php:117 -#| msgid "Process case" -#| msgid_plural "Process cases" msgid "Process name" -msgstr "Process name" +msgstr "" -#~ msgid "Delete case" +#, fuzzy +#~| msgid "Delete case" +#~ msgid "Delete permanently" #~ msgstr "Delete case" +#, fuzzy +#~ msgid "None" +#~ msgstr "None!" + +#, fuzzy +#~| msgid "Maintenance" +#~ msgid "Maintenance mode" +#~ msgstr "Maintenance" + +#, fuzzy +#~| msgid "Case id" +#~ msgid "Case URL" +#~ msgstr "Case id" + +#, fuzzy +#~| msgid "Task guid" +#~ msgid "Task add" +#~ msgstr "Task guid" + +#, fuzzy +#~| msgid "Task re-assigned!" +#~ msgid "Task re-assign" +#~ msgstr "Task re-assigned!" + +#, fuzzy +#~| msgid "Task un-claimed!" +#~ msgid "Task un-claim" +#~ msgstr "Task un-claimed!" + +#, fuzzy +#~| msgid "Task name" +#~ msgid "Task done" +#~ msgstr "Task name" + +#, fuzzy +#~| msgid "Send reminder" +#~ msgid "Task reminder" +#~ msgstr "Send reminder" + +#, fuzzy +#~| msgid "Creation date" +#~ msgid "Opening date" +#~ msgstr "Creation date" + +#, fuzzy +#~| msgid "Case description" +#~ msgid "Description" +#~ msgstr "Case description" + +#, fuzzy +#~| msgid "Process category id" +#~ msgid "Category id" +#~ msgstr "Process category id" + +#, fuzzy +#~| msgid "Process category comment" +#~ msgid "Category comment" +#~ msgstr "Process category comment" + +#, fuzzy +#~| msgid "Task action" +#~ msgid "Total duration" +#~ msgstr "Task action" + +#, fuzzy +#~| msgid "Re-assign task" +#~ msgid "User assigned to task" +#~ msgstr "Re-assign task" + +#, fuzzy +#~| msgid "Case is linked to a %1s" +#~ msgid "User login assigned to task" +#~ msgstr "Case is linked to a %1s" + +#, fuzzy +#~| msgid "Re-assign task" +#~ msgid "Group assigned to task" +#~ msgstr "Re-assign task" + +#, fuzzy +#~| msgid "Start" +#~ msgid "Start date" +#~ msgstr "Start" + +#, fuzzy +#~| msgid "Last update" +#~ msgid "Last updater" +#~ msgstr "Last update" + +#, fuzzy +#~| msgid "Task delegation date" +#~ msgid "Delegation index" +#~ msgstr "Task delegation date" + +#, fuzzy +#~| msgid "Delete case" +#~ msgid "Delete" +#~ msgstr "Delete case" + +#, fuzzy +#~| msgctxt "case_status" +#~| msgid "Completed" +#~ msgid "Complete name" +#~ msgstr "Completed" + +#, fuzzy +#~| msgid "Re-assign" +#~ msgctxt "processmaker" +#~ msgid "Re-assign" +#~ msgstr "Re-assign" + +#, fuzzy +#~| msgid "Process case" +#~| msgid_plural "Process cases" +#~ msgctxt "processmaker" +#~ msgid "Process case" +#~ msgstr "Process case" + +#~ msgid "Task GUID" +#~ msgstr "Task GUID" + +#~ msgid "Task List" +#~ msgstr "Task List" + #~ msgid "Case item" #~ msgstr "Case item" diff --git a/pics/processmaker-mid.png b/pics/processmaker-mid.png new file mode 100644 index 0000000000000000000000000000000000000000..fdda3e6a904ce214545fc1793a07a67b9527eab4 GIT binary patch literal 2873 zcmV-93&!+`P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D3eHJHK~!i%%~}a? zQ`Z%}{<3UKHn!zW7+YW)3|?@IF%Xu7)g)mX5+F3R4TKWXkT7YRg%X;j(|)RW6_Gx^3hVzSk@U0X!U4k(N3Wq3kwTlS+Aj2h=EKN4nIJ9!0vPv zUux(GD@Utpu~4JYO6?X0SsgBt@U(DzL`A45IYv$Cu@RJ)qIG5KwXO(NSSjv5fc7y+ zUc#|Q=n*jxdIX0RCaYuWk&CUWLl;}=^!0XXvpPr(0+RbOzi_&U960i|BT}_AJ|mV& zhUy$TZTLZmKLo*D@`c?%w}^pIAr2o`x0pw4J>4jMap5Le?9Lvm--#xLh0%SPvGkq7 zBxrIeM<4U|@n!AT7Kn*|qFm{ndzYX%WbM z<^DA=gvJI^B~3=#<~RRQol<(u*e6;F1YV072~qTm2M1aPB}Baha=-KZml69u$i3|TMHvCd2~rDAT{Es*{n_OdE1bjK z02fBQdWymEP>${$ko%cO>;u2VKx$^$jrPqi?5>Kp-6f=MgGckqG=qKmFx@JUTkDp3 zLy;Irjjy?B*|TCtrOt@pdN)Es?0aWshI!P$e)B+XpGSNLKEyyO-DGtheR{_Q!&PJs z0d3U}c(L2?k)R2ufx1YF*M^f;t-?BSQHRY*a71*u*+NE}gCaN`=_aBhRkVKokZWo2 zkz+xw#v_)YL~Qrl2diiAFK-E%6vv)KkQj>$V#d&TGU%d68zISQ6bD|0)8!%?E^J43 za;GXhagt%u9f#)N=e00TX3!yZuZf?K;~;4xXJ5z?VNWuD|oKktvTtYdbySZ-{}E z+H7~8TDr9&zxI~ZBMlBa1~ztJKYH%|G&00TdZeL)C#SNZgWmgR4OQS6iuMq=Y2%`y zXZ8Ieia^fBvd*z~{=Rd~`8BQLquznoTF`DO_--SX19GPN5a!Q{}+fTZn;4uPHImj2xXXIUe%f@@Bfx zYFXo!c!~!eC%c&B{%nrDOE6V+aQJgbi(0x$*a4h=ghVWKtT9PLGkF zB?8Pd{q0N6U(E8Nucv-H5-SCueAF2_G zcNVDkgV~w2V=`h5JmrP|s%q`867dc7^X-fE#YzNnV( zaqH6;Ghp%q1sxNUKXRq5KfV?+u_AuGoNqg`z1R;9l-S3H_o}l&4po z(5~PyTx>86m9Q3a{2F*CaNHV>0IGxrqm_PC&|0eQOL_=asud)*AoC|UAalh4yq1$tjeFsbU`#YNjj~% zLnQbydQ&q>z<8+05aT)X#)YO1q35%MNr+N)Ncz}_a?$d@-(`Zg2Lv0#bOhq)2ww-q zzn#4e{>PLf+ zjv4TbF(~(!j7p(*XJ^u{=Vs9`Klvx)XjLnH9>V@62l0tnaR-=_d=KK!sa4}bJ^ zt=~>MFwosg^W^`IyW;)B*XT1;x}Cw-ANpYdY5WA-V7S!SLC^m65}6U0MZgo!yIVhh zaL^O+)Oh4UwS(p@q&2V;ZLK$=6^E*ruwCcC!Ce3H5u#bJ3CKkS@$Ptx98y~c+~sAk9kb#rMQ3dc68zG>mA zR{rzhTC0`LTsP8|(t3Jz{}p;-O9ibvdV}iQtlio#;eU7FdH3?zJt7%CUBN@9SGSmt zJ-Mwit@GcrCa7^w2wsuF@r$<<_#qn3Z~-&=;e3vhIFViCK;Y56IV0oReVMU7|Bv}B zD89g;i(39_iNWlpqyQT8_Y;qsHOKXl9W1$Vl^lulo|59_vTU^83{uOxl42-&3S7AF zzO1-4D<`CSIo!Uk$3(%T9?nm&FCML5!(;V`y`V^pfg9E?C`?}dl8lnwe#{AzD_10uB|C z$bz08mug$TV92JyNt$AeLFffBhA=S(I&MRI9bc!RokWwh$DX^lsBu61XW-&dDbBw< zo^$fCqU5RJDrpIxEBs0yqeqJd?q7bx^jxiJ>h`im)t6Pb$YgVpI>cT%ErK(U-%l*b zj(4E^I2aKwefw{ib_EE^?*t?Fd!W3|RD9}sd)WDgj+-Oumx00000NkvXXu0mjfNtb^u literal 0 HcmV?d00001 diff --git a/pics/processmaker-tiny.png b/pics/processmaker-tiny.png new file mode 100644 index 0000000000000000000000000000000000000000..3914de47dfd918d850547bb1e41dd3d8d1a8c446 GIT binary patch literal 1417 zcmV;41$O$0P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1s+L6K~zXfm6mNx zTU8jxpWfcy-a=nTJ4R^%TVA&5BoiYO#@Jv(Lrf$yb00MN&7tDkrc6Xbmds>dOcpXs zkbUvXJ}f5NG(pBBYBpckf-xB?WNUdDgAORrmcF;QKIirpZeJ+um$c`e=iGDt_dMr0 z&p8sx+JFtk zP$btAh_wH7Z{@@V9_ibF4Oj+@KG^n zbyr87-IxDfsGMI7NfH{_Kuypp=-BZ}!^A63>sw_sbwg-cBTdZV4j%3O!}0B}c9)Xl zwxE&%g{sdLsRHlT7Ic_(?0Lb=lO*=g6+C`!=t1A;oLBYuGRahI&k3JCWct{mS9A*| zpo9_vVXoop-)8&nW)UK;(&x&cP$P#tEVD5_?~`@knmyJrGg}0Nz^|QC_H&$WLtngyCMStf< z*X(EAf%FdhEoykD#t1u93_r6}$g-mQq5I}6+2MNpt#7b1fPBOG56aFSrw%Au>N2x>~yaifR;zKb(&BRUdaD0=LTOXHUp zy~ial0=&X3H1c`odJkMlV_9)X}39pLJh!>VGnx49E-_SsEHsEmLRx^Py%tERCg1I ziDG3`)?;BSkl-lQuRG`=22UyqnhH=Dwl<-jnM^4qg_oboTMK`(g(jEMzhA*nHVXIC zaQbi}pNP^1c@)1(f~elAfj6Jc7c2nRaC>C>zI+ukOdYan2JplcOadY;anCA~3Ysc( zP-)BsJSgFGgBd=<43ope^Z5kM=*nFu|15^ak7__2N~56rYfID)!OkPr5?8EwEDmml z^DS2BJW>RWD9F(97aX1toV_v4XPQ(hjY`MP{G5I~>m**>h!-$Wgr-zPY8f&y$&-yAHyx1sO_UPe*IwNoYebR%2P4LeIvM({x z@jQ!9G<~k?6zf=jN29p~T{uYUYrfMfnZefQ3*I;DUU+dxVt?HG@}z5!|Ok3{7ov{Ra3S Xe$fDY3mCPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!T`FXx{BIp=cjx%YDLAFCO)erR%` zJs4k=lWEmMHAz6Bib5&SR_E%siu{C;$XMS%*LCsn=V%QV(HGi*+(y@7EfrpPNhxZNQJ-JHPX4)-6~+DU{VYZM(6vUj>k@G ztXAX^$W=}_R#ya#9y?e?471B?kc$UnDPJP3l@8y(`<8uG`?y-onlZpiv3_YhRp~Pl^x4|Xoeg6yI zOfLbCIA|!dLbKNngOdxOl2+1Lol9jj0Y!eNWn)W1Ypn~m6bL{D2{&GcU^Kh}qoEaJ zO|??H1rBX@vTT58A|sUT9!j09h9ToU?>7T>n!L7=i+kK1w08Z}8C8?Antog2QODVb-*K3|I5W;XUTvwc_g!cy z>yiZg?=zVpf2021$GP?&v6M{i*+aV)F$$H~guwCoqW-F_`KIp-@CPst{_)qDbJ_p^ N002ovPDHLkV1gBaVyFNB literal 0 HcmV?d00001 diff --git a/pics/processmaker.png b/pics/processmaker.png new file mode 100644 index 0000000000000000000000000000000000000000..cae114e7eb41f03abd7d94b0814aa22013ff7a2b GIT binary patch literal 4828 zcmV<25+m)2P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D5^+gHK~#8N?VSsB zRn?itHz9!}fK9~G5!0BNrhSBt0Qy8_@Vt2nL$AER>-2I zFyTlB!jPclPVL9mgAHQs_G4m0)k(2K5>(&PCbH#2h6oh9bUsV|uVUZA|A%7op?0i}NTb5EOQN35Ls}_%Ls!@`Z zEYcJyc)93LA#UlMVPafiw(}Qdn4meV8Yfl>lfOMfR=)0KHRJQeKVLLb8z_(kY1YPb)(Dfo`&(JvDoYy1#J{ZBBletVNqW`i6%fa; z;U{y4sXopDgk9r1Gz;T|$=}PA)w8lJLjC>E+Wq3GEk{#Q{dvJrDQ(jVGR6H1$7;g_ zX=A8jR7FN@bhwcwe`~(17*my0)-+`mlF;uePi&JOB)us93?n}q$@f)T;eOt^hq7vnA%#+o3 zWx0I$8~d^!`=nM3$?UEE)?IHy+EVSeG}5nmCd`E_EWrC^nRe52+tWWe($sBK zU}w-O^7q%5YV$v4(jq1-M4xrJtnO`UX`6W6Q=evZr~b+dP?67;j}tRSDlX;Bj< z|KFvuT2cf`z5CTl@!IbC z9s?sryu5fKK1fd<5if+jBdfX3Za5_FUwHp_!ZR3r4`^+W3|fIUl@91D zp1R>HoFWLbIp_?LT8T{5EyIah{``)F4T?2E%u5x^!RWcevcUUO@kkbSLaY(69QA3Y_ij-M7ERGk#-s~gl5Nuno9nPa>9D+9z&=i?-b z%o`F3VTkK`W`@su@RNkxAVe{h@ef7W;+s$42-*bw_7}5r47b?H$L|7$RP(kQ>0D`O)kmaoLoD zzyKJl&|wQtd|VS($2A&+fS(mtjpG!x7&1;I9AN~>?57X7?9na0Pb`CmQ*NGKAa0pE zJZ?k<<4}FGSn=k5@oHs#++NZk)rge2T8-gMJ=Fm|_;!_g<86a$U^V^ehVkMD7ZfLq zEWiZh{a2Kz2MBnHY=al$Ki;fTQDhP!jgL?grlbqqe&sXUt()+?T}z}famT!o&L_zO z)a0^1?H2Kvh2W*VZDyfZTsDkTS1AkC0>$vd?;fzO$06(27mr9vvH*t82X4ZGv$ohK~dW zpFb*E!;LUs-(^|4xbY{iIZHc1Qv#@}yU!bDRnm|$tkh6a=0?~u`mVq4J86wDZWxbs zK=f?NfKWEulE#qYrA>!9M9SJBm@xGP29Y+&dT7Dul#;AqAZgc47+}qM=Gi~>QH{13 z+mRMbSUKaaS9Tn?LKru=^z6ZU*3~FbA@sXU5HirGaLi|pdNB(6w26Zk0aZ{cf3-C@G!AJW~h&Q(%6YuOjp_V7%(9H<)*0;z`96uq~ zo>`nDE*w9=m?~y~yLJKNgGXyBTZO2jeYM>qj7aexN@|81#K#SVw>tyZFKA!{5IF%TG5hr z$A!gK)MBROW0Oy9D{Ij&VLPSy8*E|43i__^Opm@}|NaX*)an=0FOeI#2G`=6(Eur< zFEb6=wQ-*!%r9Z+#$s5s@n9~QILJBj2Kto`qyc18vVy_2xaM!)iYS1o0~ViCXnZgY zCk$I86i+-2#oWgS8mNo`^>E&ZoTy?iu-sS#Xv0+Q3|#ZU506A;J|-Cd1}Dgv~3B?gsAp+deDO9w``T(+02L<(xV=%SvB{e^SL#j8yr}N1N(VbhmUReLcQUM z25q1%UNKP`AH+?XMrF+@Rr6%Z@o<;~Dq(U#rsuc}#QtO1utZ9i25q1%UZ2g_f-K`N z9Ao2s$4_%uu6~(D>5OP5fJzuUkYobhKwziIcEk$W;<$z)1|bD#7t^R|^vyW<2{Y~C z7%L^rD+r@D-Hup5Th{NXcg`Y5$$-8_4G*Nf)|nzwgpnB1B=CrnOwubpvfycn1+-<0 z(|345KMTVV{GLGla_1>+|U!#mm|m^nhFu*4Sbg7KuSXGK^dSBfMv)QrO@@9~qQX*WGQ$#c}Q zB5Yv4bmLY{R{(^O)7}dho-hrsjA0AY(~6**^-1K*=*lb-Hs zWPpTK5a4NgJ}i}i8))IUJT+C~1@vDwGA*F}M)_txDj-ZnoRDCcx2gv|FFmQvy<)@X zbyl7s+RsUlS*0Y5qiI9^3G=%(h-d%xrK6(C3G(DdJIl0~5Ou=b{SsC+K@!&8O?${< z4SAeXcc{?5@Gr!jDHrC_U~4P2i9OldYZ~) z@a>sHolm`ktU0zKy%@YZ21h#yLqAr0ZTx_gA&iF|ZCm-jlz*I7AYNTEDW>(-Lq=<%B@;;mt2R(o2qaAD$npuXOPQLxk*dZPXy0`Ca*_RP!_q0@SM!Qh zyIB*AisSG49!AK%`RikH)$T)ozG1vryL75DEKH>GyZ5!v#Zil)4G51T{r*JG!MUc^ zZ#~#h_N^Co#lMON4+W5`)DfV{{5^cTCy zK2hiA6lQ5(X1ipUZu;kec@qZ36mHyAJ^zsPofmgnUt|bjH_aTvVTa75ZdYD`<-}4~ z^k_8bik^R#9?`eQgDf2Jj(d#UDed5Pb?p5Iu9{I8*X63oj8zo}RLt|f}$doCX7_Yg#iR5m*3t4L{d?>h&SRN3;t z2LtJ1-%Mxh>MC6z9APkgJ0tA{WAoGxMv7E3I&d+O#SWr=xMr_Ek5#;&pRF^?O%gCy z=>na#N{Qyr=8x)flbgg};J77+)%-^`t7KvECQ1WU`11>g<1SNOk?&J?gxhF9gFGJV zQ5BKy4uJ|?eSN7l*AyTUc2;qYm^Qqh7&RzM49)E$as&K>3{CX9E|v?`HnfNX$4`q* zRVT%V2O7lZ@|boqEfO!a=LV!JU{?qud#?bMOEJ=Y!{R|0;AWA09aG7Jhe%BTe<%A} zpryCXGim{M|RCP)g@S?EUud(Wp^0Rv4@C^W|CoDl4b@W>i?>Os) zFl99o`|;>iC1Fkdo+#q*fGo0dJ7Ec7t-@e8gwTYjm*)z z^4Z;G)&Un-P0~t4+Ksdx33CU|bY{ixTU5fSdX5};K{SN1nJI6^3Mtanca{w~6YOv7 zk+6=?WIcRsDMJpWseFI&hNuVwlC(Qyb;IJaVcUK@duUsrr1eNxd!PnM%lEtM$Hzn# zh?+1UNqb9HcS%V*9al5_O`kiRuS zRxdZTw3XB~wf6S16GSwwsbmDk#lWm|@!%C>b%-@YdA0^aA?l~&MzkdHQ&~;R%1C?H z3t3$S^x>?FCj48H#bB7(NMmGym|o`)q@9xG0(tnbEZw3*)4o;qMZ@3f7#AV8_KgKG z>mNu9LENpfnj_2WvXE0etnO{}m@zFG08vQQqSF3i&CQe97ft&Gjr3P;FxFv&APq0{ zm9pF;OCz6k1!$re2otZ5VIjK#q>8yiqbe{MMtk@Wq&3OHd>U#powAey@D~x$g7EnSWZk$md7ET$gSIa;Y8Y67% zg)JnKFb(wna;FxxCtJk2UB}g4W~|Bw5NDe_q=<=GNGg`ZER=>s(0-Xn5&qM-Ns}9r zfiMjujXkpbQb%Od2Yc(q`+Mre$A=nKP^XUH(6Jf73z-lDbS%gzc|IyPLrgEs60=9= ziK)doff;bLG+{_s@1G(;G7%OCq>X(aAy7#kfI#wLun!4aTd-TgAt{k{P7DWX3=#tS zLfm8!tAlgMibkR>ayPN<26?uE2Kh)31hGstq0;1rWF;&Znm8?m9RQgc%>jA%_0rwm zk~Bi!T%e^#6P46R6~f#QNSrH)E(jzf>B;E`A^s1&-+%@T - - Processmaker - processmaker - stable - 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). - 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. - - - 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. - - - https://github.com/tomolimo/processmaker - https://github.com/tomolimo/processmaker/releases - https://github.com/tomolimo/processmaker/issues - https://github.com/tomolimo/processmaker/wiki - - Olivier Moron - - - - 3.3.8 - 9.1 - - - 3.4.26 - 9.2 - - - 3.5.11 - 9.3 - - - 3.6.17 - 9.4 - - - - en_gb - fr_fr - cs_cz - - GPL v2+ - - - Processus - BPMN 2.0 - Workflow - Helpdesk - Ticket - - - Processes - BPMN 2.0 - Helpdesk - Workflows - Ticket - - + + + Processmaker + processmaker + stable + 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). + 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. + + + 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. + + + https://github.com/tomolimo/processmaker + https://github.com/tomolimo/processmaker/releases + https://github.com/tomolimo/processmaker/issues + https://github.com/tomolimo/processmaker/wiki + + Olivier Moron + + + + 3.3.8 + 9.1 + + + 3.4.30 + 9.2 + + + 3.5.15 + 9.3 + + + 3.6.21 + 9.4 + + + 4.0.0 + 9.5 + + + + en_gb + fr_fr + cs_cz + + GPL v2+ + + + Processus + BPMN 2.0 + Workflow + Helpdesk + Ticket + + + Processes + BPMN 2.0 + Helpdesk + Workflows + Ticket + + \ No newline at end of file diff --git a/setup.php b/setup.php index 5beaf89..6f2914d 100644 --- a/setup.php +++ b/setup.php @@ -1,165 +1,178 @@ - $objects, 'notificationtemplates_types' => true]); - - Plugin::registerClass('PluginProcessmakerTask', ['notificationtemplates_types' => true]); - - Plugin::registerClass('PluginProcessmakerTaskCategory', ['addtabon' => 'TaskCategory']); - - if (Session::haveRightsOr("config", [READ, UPDATE])) { - Plugin::registerClass('PluginProcessmakerConfig', ['addtabon' => 'Config']); - $PLUGIN_HOOKS['config_page']['processmaker'] = 'front/config.form.php'; - } - - Plugin::registerClass('PluginProcessmakerProfile', ['addtabon' => 'Profile']); - - Plugin::registerClass('PluginProcessmakerProcess_Profile'); - - $PLUGIN_HOOKS['csrf_compliant']['processmaker'] = true; - - $PLUGIN_HOOKS['pre_show_item']['processmaker'] - = ['PluginProcessmakerProcessmaker', 'pre_show_item_processmaker']; - - $PLUGIN_HOOKS['pre_show_tab']['processmaker'] - = ['PluginProcessmakerProcessmaker', 'pre_show_tab_processmaker']; - $PLUGIN_HOOKS['post_show_tab']['processmaker'] - = ['PluginProcessmakerProcessmaker', 'post_show_tab_processmaker']; - - // Display a menu entry ? - if (Session::haveRightsOr('plugin_processmaker_config', [READ, UPDATE])) { - // 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] ); - - $hooks = []; - foreach ($objects as $obj) { - $hooks[$obj] = ['PluginProcessmakerProcessmaker', 'plugin_pre_item_add_processmaker']; - } - $PLUGIN_HOOKS['pre_item_add']['processmaker'] = $hooks; - - $hooks = []; - foreach ($objects as $obj) { - $hooks[$obj] = 'plugin_pre_item_update_processmaker'; - } - $PLUGIN_HOOKS['pre_item_update']['processmaker'] = $hooks; - - $hooks = ['TicketSatisfaction' => 'plugin_item_update_processmaker_satisfaction', - 'User' => 'plugin_item_update_processmaker_user']; - foreach ($objects as $obj) { - $hooks[$obj.'Task'] = 'plugin_item_update_processmaker_tasks'; - } - $PLUGIN_HOOKS['item_update']['processmaker'] = $hooks; - - $hooks = []; - foreach ($objects as $obj) { - $hooks[$obj] = ['PluginProcessmakerProcessmaker', 'plugin_item_add_processmaker']; - } - $PLUGIN_HOOKS['item_add']['processmaker'] = $hooks; - - $hooks = []; - foreach ($objects as $obj) { - $hooks['NotificationTarget'.$obj] = ['PluginProcessmakerProcessmaker', 'plugin_item_get_data_processmaker']; - } - $PLUGIN_HOOKS['item_get_datas']['processmaker'] = $hooks; - - $hooks = []; - foreach ($objects as $obj) { - $hooks["PluginPdf".$obj."Task"] = ['PluginProcessmakerProcessmaker', 'plugin_item_get_pdfdata_processmaker']; - } - $PLUGIN_HOOKS['item_get_pdfdatas']['processmaker'] = $hooks; - - // Javascript - $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"]; - break; - case "planning.php": - $PLUGIN_HOOKS['add_javascript']['processmaker'] = ["js/planning.js"]; - break; - case "central.php": - $PLUGIN_HOOKS['add_javascript']['processmaker'] = ["js/central.js"]; - break; - } - } - - $PLUGIN_HOOKS['use_massive_action']['processmaker'] = 1; - - $CFG_GLPI['planning_types'][] = 'PluginProcessmakerTask'; - $PLUGIN_HOOKS['post_init']['processmaker'] = 'plugin_processmaker_post_init'; - - // in order to set rights when in helpdesk interface - // otherwise post-only users can't see cases and then can't act on a case task. - $PLUGIN_HOOKS['change_profile']['processmaker'] = 'plugin_processmaker_change_profile'; - -} - - -// Get the name and the version of the plugin - Needed -function plugin_version_processmaker() { - return [ - 'name' => 'Process Maker', - 'version' => PROCESSMAKER_VERSION, - 'author' => 'Olivier Moron', - 'license' => 'GPLv3+', - 'homepage' => 'https://github.com/tomolimo/processmaker', - 'requirements' => [ - 'glpi' => [ - 'min' => '9.4', - 'max' => '9.5' - ], - ] - ]; -} - -// 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.4', 'lt') || version_compare(GLPI_VERSION, '9.5', 'ge')) { - echo "This plugin requires GLPI >= 9.4 and < 9.5"; - return false; - } - - return true; -} - -function plugin_processmaker_check_config($verbose = false) { - - return true; -} - - -function plugin_processmaker_haveRight($module, $right) { - - return Session::haveRight("plugin_processmaker_".$module, $right); -} - +isActivated('processmaker')) { + + $objects = ['Ticket', 'Change', 'Problem']; + + Plugin::registerClass('PluginProcessmakerProcessmaker'); + + Plugin::registerClass('PluginProcessmakerCase', ['addtabon' => $objects, 'notificationtemplates_types' => true]); + + Plugin::registerClass('PluginProcessmakerTask', ['notificationtemplates_types' => true]); + + Plugin::registerClass('PluginProcessmakerTaskCategory', ['addtabon' => 'TaskCategory']); + + if (Session::haveRightsOr("config", [READ, UPDATE])) { + Plugin::registerClass('PluginProcessmakerConfig', ['addtabon' => 'Config']); + $PLUGIN_HOOKS['config_page']['processmaker'] = 'front/config.form.php'; + } + + Plugin::registerClass('PluginProcessmakerProfile', ['addtabon' => 'Profile']); + + Plugin::registerClass('PluginProcessmakerProcess_Profile'); + + $PLUGIN_HOOKS['csrf_compliant']['processmaker'] = true; + + $PLUGIN_HOOKS['pre_show_item']['processmaker'] + = ['PluginProcessmakerProcessmaker', 'pre_show_item_processmaker']; + + $PLUGIN_HOOKS['pre_show_tab']['processmaker'] + = ['PluginProcessmakerProcessmaker', 'pre_show_tab_processmaker']; + //$PLUGIN_HOOKS['post_show_tab']['processmaker'] + // = ['PluginProcessmakerProcessmaker', 'post_show_tab_processmaker']; + + // Display a menu entry ? + if (Session::haveRightsOr('plugin_processmaker_config', [READ, UPDATE])) { + // 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] ); + + $hooks = []; + foreach ($objects as $obj) { + $hooks[$obj] = ['PluginProcessmakerProcessmaker', 'plugin_pre_item_add_processmaker']; + } + $PLUGIN_HOOKS['pre_item_add']['processmaker'] = $hooks; + + $hooks = []; + foreach ($objects as $obj) { + $hooks[$obj] = 'plugin_pre_item_update_processmaker'; + } + $PLUGIN_HOOKS['pre_item_update']['processmaker'] = $hooks; + + $hooks = ['TicketSatisfaction' => 'plugin_item_update_processmaker_satisfaction', + 'User' => 'plugin_item_update_processmaker_user']; + foreach ($objects as $obj) { + $hooks[$obj.'Task'] = 'plugin_item_update_processmaker_tasks'; + } + $PLUGIN_HOOKS['item_update']['processmaker'] = $hooks; + + $hooks = []; + foreach ($objects as $obj) { + $hooks[$obj] = ['PluginProcessmakerProcessmaker', 'plugin_item_add_processmaker']; + } + $PLUGIN_HOOKS['item_add']['processmaker'] = $hooks; + + $hooks = []; + foreach ($objects as $obj) { + $hooks['NotificationTarget'.$obj] = ['PluginProcessmakerProcessmaker', 'plugin_item_get_data_processmaker']; + } + $PLUGIN_HOOKS['item_get_datas']['processmaker'] = $hooks; + + $hooks = []; + foreach ($objects as $obj) { + $hooks["PluginPdf".$obj."Task"] = ['PluginProcessmakerProcessmaker', 'plugin_item_get_pdfdata_processmaker']; + } + $PLUGIN_HOOKS['item_get_pdfdatas']['processmaker'] = $hooks; + + // Javascript + $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"]; + break; + case "planning.php": + $PLUGIN_HOOKS['add_javascript']['processmaker'] = ["js/planning.js"]; + break; + case "central.php": + $PLUGIN_HOOKS['add_javascript']['processmaker'] = ["js/central.js"]; + break; + } + } + + $PLUGIN_HOOKS['use_massive_action']['processmaker'] = 1; + + $CFG_GLPI['planning_types'][] = 'PluginProcessmakerTask'; + $PLUGIN_HOOKS['post_init']['processmaker'] = 'plugin_processmaker_post_init'; + + // in order to set rights when in helpdesk interface + // otherwise post-only users can't see cases and then can't act on a case task. + $PLUGIN_HOOKS['change_profile']['processmaker'] = 'plugin_processmaker_change_profile'; + + //if ($plugin->isActivated('processmaker')) { + + // in order to manage the password encryption + $pmglpikey = new PluginProcessmakerGlpikey; + foreach ($pmglpikey->getFields() as $fld) { + $PLUGIN_HOOKS['secured_fields'][] = $fld; + } + //} + } + +} + + +// Get the name and the version of the plugin - Needed +function plugin_version_processmaker() { + return [ + 'name' => 'Process Maker', + 'version' => PROCESSMAKER_VERSION, + 'author' => 'Olivier Moron', + 'license' => 'GPLv3+', + 'homepage' => 'https://github.com/tomolimo/processmaker', + 'requirements' => [ + 'glpi' => [ + 'min' => '9.5', + 'max' => '9.6' + ], + ] + ]; +} + +// 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.5', 'lt') || version_compare(GLPI_VERSION, '9.6', 'ge')) { + echo "This plugin requires GLPI >= 9.5 and < 9.6"; + return false; + } + + return true; +} + +function plugin_processmaker_check_config($verbose = false) { + + return true; +} + + +function plugin_processmaker_haveRight($module, $right) { + + return Session::haveRight("plugin_processmaker_".$module, $right); +} +