.
--------------------------------------------------------------------------
*/
/**
* PluginProcessmakerCase short summary.
*
* PluginProcessmakerCase description.
*
* @version 1.0
* @author MoronO
*/
class PluginProcessmakerCase extends CommonDBTM {
static $rightname = 'plugin_processmaker_case';
private $process = null;
const DRAFT = 'DRAFT';
const TO_DO = 'TO_DO';
const COMPLETED = 'COMPLETED';
const CANCELLED = 'CANCELLED';
//const ALL = 'all';
static function getTypeName($nb = 0) {
return _n('Process case', 'Process cases', $nb, 'processmaker');
}
//static function canCreate() {
// return Session::haveRight('plugin_processmaker_config', UPDATE);
//}
static function canView() {
return Session::haveRightsOr('plugin_processmaker_case', [READ, UPDATE]);
}
function canViewItem() {
return Session::haveRight('plugin_processmaker_case', READ);
}
//static function canUpdate( ) {
// return Session::haveRight('plugin_processmaker_config', UPDATE);
//}
//function canUpdateItem() {
// return Session::haveRight('plugin_processmaker_config', UPDATE);
//}
function canEdit($ID) {
return $this->canPurgeItem() || self::canCancel();
}
function maybeDeleted() {
return false;
}
//static function canDelete() {
// return parent::canDelete();
//}
//function canDeleteItem() {
// return parent::canDeleteItem();
//}
static function canPurge() {
return true; //self::canDelete();
}
function canPurgeItem() {
return $_SESSION['glpiactiveprofile']['interface'] == 'central'
&& $this->fields['plugin_processmaker_cases_id'] == 0
&& $this->canDeleteItem()
&& (self::canDelete() || $this->fields['case_status'] == self::DRAFT);
}
static function canCancel() {
return plugin_processmaker_haveRight('case', CANCEL);
}
function canCancelItem() {
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 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(), $restrict) as $case) {
$ret[] = $case['id'];
}
return $ret;
}
/**
* 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: %sTask: "%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']),
$dbu->getUserName(isset($glpi_task->oldvalues['users_id_tech']) ? $glpi_task->oldvalues['users_id_tech'] : 0),
$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);
$this->update(['id' => $this->getID(), 'date_mod' => $_SESSION["glpi_currenttime"]]);
}
return $pmResponse;
}
/**
* 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 = $glpi_task->oldvalues['users_id_tech'] ?? $glpi_task->oldvalues['users_id_tech'];
$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 = $dbu->getUserName($newTech);
if ($old_users_tech_id) {
$info = __('Task re-assigned! Case: %sTask: "%s" has been re-assigned from "%s" to "%s".Reason: %s', 'processmaker');
$info = sprintf($info,
$this->getNameID(['forceid' => true]),
$task_name,
$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: %sTask: "%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(["\\'", '\\"'], ["'", '"'], $info);
$info = nl2br($info);
$glpi_task->add([$foreignkey => $glpi_task->fields[$foreignkey],
'date' => $glpi_task->fields['date'],
'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(),
]);
//// and add a fake pm_task in the glpi_plugin_processmaker_tasks table
//$DB->insert(PluginProcessmakerTask::getTable(), [
// 'itemtype' => $pm_task_row['itemtype'],
// 'items_id' => $glpi_task->getID(),
// 'plugin_processmaker_cases_id' => $this->getID(),
// 'plugin_processmaker_taskcategories_id' => $pm_process->fields['taskcategories_id'],
// 'del_index' => $delIndex,
// 'del_thread' => $delThread,
// 'del_thread_status' => PluginProcessmakerTask::INFO
// ]
//);
}
}
/**
* 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' => PluginProcessmakerTask::OPEN
]
]);
foreach ($res 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 "".__('Current task(s) properties', 'processmaker')." ";
if (property_exists($caseInfo, 'currentUsers') && count($caseInfo->currentUsers) > 0) {
echo "
".__('Task', 'processmaker')."
".__('Task guid', 'processmaker')."
".__('Current user', 'processmaker')."
".__('Task delegation date', 'processmaker')."
";
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 "".$currentTask->taskName." ";
} 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->current()) {
$sub_case = new PluginProcessmakerCase;
$sub_case->getFromGUID($row['APP_UID']);
$case_url .= $sub_case->getID()."-".$currentTask->delIndex;
echo "> ".$currentTask->taskName." ";
} else {
echo "".$currentTask->taskName." ";
}
}
echo "".$currentTask->taskId." ";
if ($currentTask->userName == '') {
echo "".__('To be claimed', 'processmaker')." ";
} else {
echo "".$currentTask->userName." ";
}
echo "".Html::convDateTime($tasks[$currentTask->delIndex])." ";
echo " ";
}
} else {
echo "".__('None')." ";
}
echo "
";
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 "".__('Sub-case properties', 'processmaker')." ";
} else {
if ($showparenturl) {
echo "".__('Parent case properties', 'processmaker')." ";
} else {
echo "".__('Case properties', 'processmaker')." ";
}
}
echo "";
echo "".__('Process', 'processmaker')." ";
echo "".__('Case title', 'processmaker')." ";
echo "".__('Case number', 'processmaker')." ";
echo "".__('Case status', 'processmaker')." ";
echo "".__('Case guid', 'processmaker')." ";
echo "".__('Creator', 'processmaker')." ";
echo "".__('Creation date', 'processmaker')." ";
echo "".__('Last update', 'processmaker')." ";
//echo "".__('Case description', 'processmaker')." ";
echo " ";
echo "";
echo "".$caseInfo->processName." ";
if ($showparenturl) {
echo "".$this->getLink()." ";
} else {
echo "".$caseInfo->caseName." ";
}
echo "".$caseInfo->caseNumber." ";
echo "".self::getStatus($caseInfo->caseStatus)." ";
echo "".$caseInfo->caseId." ";
echo "".$caseInfo->caseCreatorUserName." ";
echo "".Html::convDateTime($caseInfo->createDate)." ";
echo "".Html::convDateTime($caseInfo->updateDate)." ";
//echo "".$caseInfo->????." ";
echo " ";
echo "
";
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))." ";
$itemtype::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 "";
}
// 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()) {
// then propose a button to delete case
// the button will be effectively shown by the showFormButtons()
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' => __('Case 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['max_cases_per_item']
|| $PM_SOAP->config['max_cases_per_item'] == 0)) {
echo "";
}
echo "";
if ($canupdate && $numrows) {
Html::openMassiveActionsForm('mass'.__CLASS__.$rand);
$massiveactionparams = ['num_displayed' => $numrows,
'container' => 'mass'.__CLASS__.$rand];
Html::showMassiveActions($massiveactionparams);
}
echo "
";
echo "".PluginProcessmakerCase::getTypeName($numrows)." ";
echo " ";
if ($numrows) {
$header_begin = "";
$header_top = '';
$header_bottom = '';
$header_end = '';
if ($canupdate
&& $numrows) {
$header_top .= "".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand);
$header_top .= " ";
$header_bottom .= "".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand);
$header_bottom .= " ";
}
foreach ($columns as $key => $val) {
$header_end .= "$val ";
}
$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 "";
// show massive action only for main cases (not for subcases)
if ($data['plugin_processmaker_cases_id'] == 0) {
Html::showMassiveActionCheckBox(__CLASS__, $data["assocID"]);
}
echo " ";
}
echo "".$data['pname']." ";
echo "".$link." ";
echo "".self::getStatus($data['case_status'])." ";
echo "";
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 " ";
echo " ";
$i++;
}
echo $header_begin.$header_bottom.$header_end;
}
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['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']]
]);
$re = " fields['id']."\'> ";
if ($DB->delete('glpi_'.strtolower($this->fields['itemtype']).'tasks', ['id' => $sub])
&& $DB->delete('glpi_'.strtolower($this->fields['itemtype']).'tasks', ['content' => ['REGEXP', $re]])
&& $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'] == self::TO_DO
&& $this->cancelTasks()) {
$ret = $this->update(['id' => $this->getID(), 'case_status' => self::CANCELLED]);
}
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 [];
}
//$pm_plugin_url = Plugin::getWebDir('processmaker');
//$front_page = "$pm_plugin_url/front";
$menu = [];
$menu['title'] = self::getTypeName(Session::getPluralNumber());
$menu['page'] = self::getSearchURL(false);
//$menu['icon'] = '">