grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026.
--------------------------------------------------------------------------
*/
/** @file
* @brief
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
/// TODO extends it from CommonDBChild
/**
* TicketFollowup Class
**/
class TicketFollowup extends CommonDBTM {
// From CommonDBTM
public $auto_message_on_action = false;
static $rightname = 'followup';
const SEEPUBLIC = 1;
const UPDATEMY = 2;
const ADDMYTICKET = 4;
const UPDATEALL = 1024;
const ADDGROUPTICKET = 2048;
const ADDALLTICKET = 4096;
const SEEPRIVATE = 8192;
/**
* Name of the type
*
* @param $nb : number of item in the type
**/
static function getTypeName($nb=0) {
return _n('Followup', 'Followups', $nb);
}
static function canCreate() {
return (Session::haveRightsOr(self::$rightname,
array(self::ADDALLTICKET, self::ADDMYTICKET,
self::ADDGROUPTICKET))
|| Session::haveRight('ticket', Ticket::OWN));
}
static function canView() {
return (Session::haveRightsOr(self::$rightname, array(self::SEEPUBLIC, self::SEEPRIVATE))
|| Session::haveRight('ticket', Ticket::OWN));
}
/**
* Is the current user have right to delete the current followup ?
*
* @return boolean
**/
function canPurgeItem() {
$ticket = new Ticket();
if (!$ticket->can($this->getField('tickets_id'), READ)) {
return false;
}
if (Session::haveRight(self::$rightname, PURGE)) {
return true;
}
return false;
}
/**
* Is the current user have right to show the current followup ?
*
* @return boolean
**/
function canViewItem() {
$ticket = new Ticket();
if (!$ticket->can($this->getField('tickets_id'), READ)) {
return false;
}
if (Session::haveRight(self::$rightname, self::SEEPRIVATE)) {
return true;
}
if (!$this->fields['is_private']
&& Session::haveRight(self::$rightname, self::SEEPUBLIC)) {
return true;
}
if ($this->fields["users_id"] === Session::getLoginUserID()) {
return true;
}
return false;
}
/**
* Is the current user have right to create the current followup ?
*
* @return boolean
**/
function canCreateItem() {
$ticket = new Ticket();
if (!$ticket->can($this->getField('tickets_id'), READ)
// No validation for closed tickets
|| (in_array($ticket->fields['status'],$ticket->getClosedStatusArray())
&& !$ticket->isAllowedStatus($ticket->fields['status'], Ticket::INCOMING))) {
return false;
}
return $ticket->canAddFollowups();
}
/**
* Is the current user have right to update the current followup ?
*
* @return boolean
**/
function canUpdateItem() {
if (($this->fields["users_id"] != Session::getLoginUserID())
&& !Session::haveRight(self::$rightname, self::UPDATEALL)) {
return false;
}
$ticket = new Ticket();
if (!$ticket->can($this->getField('tickets_id'), READ)) {
return false;
}
if ($this->fields["users_id"] === Session::getLoginUserID()) {
if (!Session::haveRight(self::$rightname, self::UPDATEMY)) {
return false;
}
return true;
}
// Only the technician
return (Session::haveRight(self::$rightname, self::UPDATEALL)
|| $ticket->isUser(CommonITILActor::ASSIGN, Session::getLoginUserID())
|| (isset($_SESSION["glpigroups"])
&& $ticket->haveAGroup(CommonITILActor::ASSIGN, $_SESSION['glpigroups'])));
}
function getTabNameForItem(CommonGLPI $item, $withtemplate=0) {
if ($item->getType() == 'Ticket') {
$nb = 0;
if (self::canCreate()) {
if ($_SESSION['glpishow_count_on_tabs']) {
$nb = countElementsInTable('glpi_ticketfollowups',
"`tickets_id` = '".$item->getID()."'");
}
return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), $nb);
}
}
return '';
}
static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) {
$fup = new self();
$fup->showSummary($item);
return true;
}
function post_getEmpty() {
if (isset($_SESSION['glpifollowup_private']) && $_SESSION['glpifollowup_private']) {
$this->fields['is_private'] = 1;
}
if (isset($_SESSION["glpiname"])) {
$this->fields['requesttypes_id'] = RequestType::getDefault('followup');
}
}
function post_deleteFromDB() {
global $CFG_GLPI;
$donotif = $CFG_GLPI["use_mailing"];
if (isset($this->input['_disablenotif'])) {
$donotif = false;
}
$job = new Ticket();
$job->getFromDB($this->fields["tickets_id"]);
$job->updateDateMod($this->fields["tickets_id"]);
// Add log entry in the ticket
$changes[0] = 0;
$changes[1] = '';
$changes[2] = $this->fields['id'];
Log::history($this->getField('tickets_id'), 'Ticket', $changes, $this->getType(),
Log::HISTORY_DELETE_SUBITEM);
if( $donotif ) {
$options = array('followup_id' => $this->fields["id"],
// Force is_private with data / not available
'is_private' => $this->fields['is_private']);
NotificationEvent::raiseEvent('delete_followup', $job, $options);
}
}
function prepareInputForUpdate($input) {
// update writer if content change
if (($uid = Session::getLoginUserID())
&& isset($input['content']) && ($input['content'] != $this->fields['content'])) {
$input["users_id"] = $uid;
}
return $input;
}
function post_updateItem($history=1) {
global $CFG_GLPI;
$job = new Ticket();
$mailsend = false;
if ($job->getFromDB($this->fields["tickets_id"])) {
$job->updateDateMod($this->fields["tickets_id"]);
if (count($this->updates)) {
if (!isset($this->input['_disablenotif'])
&& $CFG_GLPI["use_mailing"]
&& (in_array("content",$this->updates)
|| isset($this->input['_need_send_mail']))) {
$options = array('followup_id' => $this->fields["id"],
'is_private' => $this->fields['is_private']);
NotificationEvent::raiseEvent("update_followup", $job, $options);
}
}
// change ticket status (from splitted button)
$this->input['_job'] = new Ticket();
if (!$this->input['_job']->getFromDB($this->input["tickets_id"])) {
return false;
}
if (isset($this->input['_status'])
&& ($this->input['_status'] != $this->input['_job']->fields['status'])) {
$update['status'] = $this->input['_status'];
$update['id'] = $this->input['_job']->fields['id'];
$update['_disablenotif'] = true;
$this->input['_job']->update($update);
}
// Add log entry in the ticket
$changes[0] = 0;
$changes[1] = '';
$changes[2] = $this->fields['id'];
Log::history($this->getField('tickets_id'), 'Ticket', $changes, $this->getType(),
Log::HISTORY_UPDATE_SUBITEM);
}
}
function prepareInputForAdd($input) {
global $CFG_GLPI;
$input["_job"] = new Ticket();
if (empty($input['content'])
&& !isset($input['add_close'])
&& !isset($input['add_reopen'])) {
Session::addMessageAfterRedirect(__("You can't add a followup without description"),
false, ERROR);
return false;
}
if (!$input["_job"]->getFromDB($input["tickets_id"])) {
return false;
}
if ($CFG_GLPI["use_rich_text"]) {
$input['content'] = $input["_job"]->setSimpleTextContent($input["content"]);
}
// Manage File attached (from mailgate)
// Pass filename if set to ticket
if (isset($input['_filename'])) {
$input["_job"]->input['_filename'] = $input['_filename'];
}
// Add docs without notif
$docadded = $input["_job"]->addFiles(0,1);
if (count($docadded) > 0) {
$input['content'] .= "\n";
foreach ($docadded as $name) {
//TRANS: %s is tha document name
$input['content'] .= "\n".sprintf(__('Added document: %s'),
Toolbox::addslashes_deep($name['data']));
}
}
// Pass old assign From Ticket in case of assign change
// if (isset($input["_old_assign"])) {
// $input["_job"]->fields["_old_assign"] = $input["_old_assign"];
// }
// if (!isset($input["type"])) {
// $input["type"] = "followup";
// }
// $input["_type"] = $input["type"];
// unset($input["type"]);
$input['_close'] = 0;
if (!isset($input["users_id"])) {
$input["users_id"] = 0;
if ($uid = Session::getLoginUserID()) {
$input["users_id"] = $uid;
}
}
// if ($input["_isadmin"] && $input["_type"]!="update") {
if (isset($input["add_close"])) {
$input['_close'] = 1;
if (empty($input['content'])) {
$input['content'] = __('Solution approved');
}
}
unset($input["add_close"]);
if (!isset($input["is_private"])) {
$input['is_private'] = 0;
}
if (isset($input["add_reopen"])) {
if ($input["content"] == '') {
if (isset($input["_add"])) {
// Reopen using add form
Session::addMessageAfterRedirect(__('If you want to reopen the ticket, you must specify a reason'),
false, ERROR);
} else {
// Refuse solution
Session::addMessageAfterRedirect(__('If you reject the solution, you must specify a reason'),
false, ERROR);
}
return false;
}
$input['_reopen'] = 1;
}
unset($input["add_reopen"]);
// }
unset($input["add"]);
$input["date"] = $_SESSION["glpi_currenttime"];
return $input;
}
function post_addItem() {
global $CFG_GLPI;
$donotif = !isset($this->input['_disablenotif']) && $CFG_GLPI["use_mailing"];
// if (isset($this->input["_no_notif"]) && $this->input["_no_notif"]) {
// $donotif = false;
// }
$this->input["_job"]->updateDateMod($this->input["tickets_id"], false,
$this->input["users_id"]);
if (isset($this->input["_close"])
&& $this->input["_close"]
&& ($this->input["_job"]->fields["status"] == CommonITILObject::SOLVED)) {
$update['id'] = $this->input["_job"]->fields['id'];
$update['status'] = CommonITILObject::CLOSED;
$update['closedate'] = $_SESSION["glpi_currenttime"];
// Use update method for history
$this->input["_job"]->update($update);
$donotif = false; // Done for ticket update (new status)
}
//manage reopening of ticket
$reopened = false;
if (!isset($this->input['_status'])) {
$this->input['_status'] = $this->input["_job"]->fields["status"];
}
// if reopen set (from followup form or mailcollector)
// and status is reopenable and not changed in form
if (isset($this->input["_reopen"])
&& $this->input["_reopen"]
&& in_array($this->input["_job"]->fields["status"], Ticket::getReopenableStatusArray())
&& $this->input['_status'] == $this->input["_job"]->fields["status"]) {
if (($this->input["_job"]->countUsers(CommonITILActor::ASSIGN) > 0)
|| ($this->input["_job"]->countGroups(CommonITILActor::ASSIGN) > 0)
|| ($this->input["_job"]->countSuppliers(CommonITILActor::ASSIGN) > 0)) {
$update['status'] = CommonITILObject::ASSIGNED;
} else {
$update['status'] = CommonITILObject::INCOMING;
}
$update['id'] = $this->input["_job"]->fields['id'];
// don't notify on Ticket - update event
$update['_disablenotif'] = true;
// Use update method for history
$this->input["_job"]->update($update);
$reopened = true;
}
//change ticket status only if imput change
if (!$reopened
&& $this->input['_status'] != $this->input['_job']->fields['status']) {
$update['status'] = $this->input['_status'];
$update['id'] = $this->input['_job']->fields['id'];
// don't notify on Ticket - update event
$update['_disablenotif'] = true;
// Use update method for history
$this->input['_job']->update($update);
}
if ($donotif) {
$options = array('followup_id' => $this->fields["id"],
'is_private' => $this->fields['is_private']);
NotificationEvent::raiseEvent("add_followup", $this->input["_job"], $options);
}
// Add log entry in the ticket
$changes[0] = 0;
$changes[1] = '';
$changes[2] = $this->fields['id'];
Log::history($this->getField('tickets_id'), 'Ticket', $changes, $this->getType(),
Log::HISTORY_ADD_SUBITEM);
}
// SPECIFIC FUNCTIONS
/**
* @see CommonDBTM::getRawName()
*
* @since version 0.85
**/
function getRawName() {
if (isset($this->fields['requesttypes_id'])) {
if ($this->fields['requesttypes_id']) {
return Dropdown::getDropdownName('glpi_requesttypes', $this->fields['requesttypes_id']);
}
return $this->getTypeName();
}
return '';
}
/**
* @param $ticket Tichet object
* @param $rand
* @param $showprivate
**/
function showInTicketSumnary(Ticket $ticket, $rand, $showprivate) {
global $DB, $CFG_GLPI;
$canedit = $this->canEdit($this->fields['id']);
echo "
fields['id'].
$this->fields['id']."$rand();\""
: '') .
" id='viewfollowup" . $this->fields['tickets_id'] . $this->fields["id"] . "$rand'>";
$name = $this->getTypeName();
if ($this->fields['requesttypes_id']) {
$name = sprintf(__('%1$s - %2$s'), $name,
Dropdown::getDropdownName('glpi_requesttypes',
$this->fields['requesttypes_id']));
}
echo "| ".$name." | ";
echo "";
if ($canedit) {
echo "\n\n";
}
echo Html::convDateTime($this->fields["date"]) . " | ";
echo "" . nl2br($this->fields["content"]) . " | ";
echo "" . getUserName($this->fields["users_id"]) . " | ";
if ($showprivate) {
echo "".Dropdown::getYesNo($this->fields["is_private"])." | ";
}
echo "
\n";
}
/**
* Form for Followup on Massive action
**/
static function showFormMassiveAction() {
echo " ".__('Source of followup')." ";
RequestType::dropdown(array('value' => RequestType::getDefault('followup'), 'condition' => 'is_active = 1 AND is_ticketfollowup = 1'));
echo "
".__('Description')." ";
echo " ";
echo "";
echo "";
}
/**
* @since version 0.85
*
* @see CommonDBTM::showMassiveActionsSubForm()
**/
static function showMassiveActionsSubForm(MassiveAction $ma) {
switch ($ma->getAction()) {
case 'add_followup' :
static::showFormMassiveAction();
return true;
}
return parent::showMassiveActionsSubForm($ma);
}
/**
* @since version 0.85
*
* @see CommonDBTM::processMassiveActionsForOneItemtype()
**/
static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $item,
array $ids) {
switch ($ma->getAction()) {
case 'add_followup' :
$input = $ma->getInput();
$fup = new self();
foreach ($ids as $id) {
if ($item->getFromDB($id)) {
$input2 = array('tickets_id' => $id,
'is_private' => $input['is_private'],
'requesttypes_id' => $input['requesttypes_id'],
'content' => $input['content']);
if ($fup->can(-1, CREATE, $input2)) {
if ($fup->add($input2)) {
$ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK);
} else {
$ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO);
$ma->addMessage($item->getErrorMessage(ERROR_ON_ACTION));
}
} else {
$ma->itemDone($item->getType(), $id, MassiveAction::ACTION_NORIGHT);
$ma->addMessage($item->getErrorMessage(ERROR_RIGHT));
}
} else {
$ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO);
$ma->addMessage($item->getErrorMessage(ERROR_NOT_FOUND));
}
}
}
parent::processMassiveActionsForOneItemtype($ma, $item, $ids);
}
/** form for Followup
*
*@param $ID integer : Id of the followup
*@param $options array of possible options:
* - ticket Object : the ticket
**/
function showForm($ID, $options=array()) {
global $DB, $CFG_GLPI;
if (isset($options['parent']) && !empty($options['parent'])) {
$ticket = $options['parent'];
}
if ($ID > 0) {
$this->check($ID, READ);
} else {
// Create item
$options['tickets_id'] = $ticket->getField('id');
$this->check(-1, CREATE, $options);
}
$tech = (Session::haveRight(self::$rightname, self::ADDALLTICKET)
|| $ticket->isUser(CommonITILActor::ASSIGN, Session::getLoginUserID())
|| (isset($_SESSION["glpigroups"])
&& $ticket->haveAGroup(CommonITILActor::ASSIGN, $_SESSION['glpigroups'])));
$requester = ($ticket->isUser(CommonITILActor::REQUESTER, Session::getLoginUserID())
|| (isset($_SESSION["glpigroups"])
&& $ticket->haveAGroup(CommonITILActor::REQUESTER, $_SESSION['glpigroups'])));
$reopen_case = false;
if ($this->isNewID($ID)) {
if (in_array($ticket->fields["status"], $ticket->getClosedStatusArray())
&& $ticket->isAllowedStatus($ticket->fields['status'], Ticket::INCOMING)) {
$reopen_case = true;
echo "".__('If you want to reopen the ticket, you must specify a reason')."
";
}
// the reqester triggers the reopening on close/solve/waiting status
if ($requester
&& in_array($ticket->fields['status'], Ticket::getReopenableStatusArray())) {
$reopen_case = true;
}
}
if ($tech) {
$this->showFormHeader($options);
$rand = mt_rand();
echo "";
echo "| ".__('Description')." | ";
echo "";
echo "";
echo Html::scriptBlock("$(document).ready(function() { $('#content$rand').autogrow(); });");
if ($this->fields["date"]) {
echo " | ".__('Date')." | ";
echo "".Html::convDateTime($this->fields["date"]);
} else {
echo " | ";
}
echo "";
// Reopen case
if ($reopen_case) {
echo "";
}
echo " |
\n";
echo "";
echo "| ".__('Source of followup')." | ";
RequestType::dropdown(array('value' => $this->fields["requesttypes_id"], 'condition' => 'is_active =1 AND is_ticketfollowup = 1'));
echo " |
\n";
echo "";
echo "| ".__('Private')." | ";
Dropdown::showYesNo('is_private', $this->fields["is_private"]);
echo " |
";
if ($ID <= 0) {
Document_Item::showSimpleAddForItem($this);
}
$this->showFormButtons($options);
} else {
$options['colspan'] = 1;
$this->showFormHeader($options);
echo "";
echo "| ".__('Description')." | ";
echo "";
echo "";
echo "";
echo "";
// Reopen case
if ($reopen_case) {
echo "";
}
echo " |
\n";
if ($ID <= 0) {
Document_Item::showSimpleAddForItem($ticket);
}
$this->showFormButtons($options);
}
return true;
}
/**
* @since version 0.90
*
* @see CommonDBTM::showFormButtons()
**/
function showFormButtons($options=array()) {
global $CFG_GLPI;
// for single object like config
$ID = 1;
if (isset($this->fields['id'])) {
$ID = $this->fields['id'];
}
$params['colspan'] = 2;
$params['candel'] = true;
$params['canedit'] = true;
if (is_array($options) && count($options)) {
foreach ($options as $key => $val) {
$params[$key] = $val;
}
}
if (!$this->isNewID($ID)) {
echo "";
}
Plugin::doHook("post_item_form", ['item' => $this, 'options' => &$params]);
echo "";
echo "| ";
if ($this->isNewID($ID)) {
echo Ticket::getSplittedSubmitButtonHtml($this->fields['tickets_id'], 'add');
} else {
if ($params['candel']
&& !$this->can($ID, DELETE)
&& !$this->can($ID, PURGE)) {
$params['candel'] = false;
}
if ($params['canedit'] && $this->can($ID, UPDATE)) {
echo Ticket::getSplittedSubmitButtonHtml($this->fields['tickets_id'], 'update');
echo " |
\n";
}
if ($params['candel']) {
echo "| \n";
if ($this->can($ID, PURGE)) {
echo Html::submit(_x('button','Delete permanently'),
array('name' => 'purge',
'confirm' => __('Confirm the final deletion?')));
}
}
if ($this->isField('date_mod')) {
echo "";
}
}
echo " |
";
Html::closeForm();
}
/**
* Show the current ticketfollowup summary
*
* @param $ticket Ticket object
**/
function showSummary($ticket) {
global $DB, $CFG_GLPI;
if (!Session::haveRightsOr(self::$rightname,
array(self::SEEPUBLIC, self::SEEPRIVATE, self::ADDMYTICKET))) {
return false;
}
$tID = $ticket->fields['id'];
// Display existing Followups
$showprivate = Session::haveRight(self::$rightname, self::SEEPRIVATE);
$caneditall = Session::haveRight(self::$rightname, self::UPDATEALL);
$tmp = array('tickets_id' => $tID);
$canadd = $this->can(-1, CREATE, $tmp);
$showuserlink = 0;
if (User::canView()) {
$showuserlink = 1;
}
$techs = $ticket->getAllUsers(CommonITILActor::ASSIGN);
$reopen_case = false;
if (in_array($ticket->fields["status"], $ticket->getClosedStatusArray())
&& $ticket->isAllowedStatus($ticket->fields['status'], Ticket::INCOMING)) {
$reopen_case = true;
}
$tech = (Session::haveRight(self::$rightname, self::ADDALLTICKET)
|| $ticket->isUser(CommonITILActor::ASSIGN, Session::getLoginUserID())
|| (isset($_SESSION["glpigroups"])
&& $ticket->haveAGroup(CommonITILActor::ASSIGN, $_SESSION['glpigroups'])));
$RESTRICT = "";
if (!$showprivate) {
$RESTRICT = " AND (`is_private` = '0'
OR `users_id` ='" . Session::getLoginUserID() . "') ";
}
$query = "SELECT `glpi_ticketfollowups`.*, `glpi_users`.`picture`
FROM `glpi_ticketfollowups`
LEFT JOIN `glpi_users` ON (`glpi_ticketfollowups`.`users_id` = `glpi_users`.`id`)
WHERE `tickets_id` = '$tID'
$RESTRICT
ORDER BY `date` DESC";
$result = $DB->query($query);
$rand = mt_rand();
if ($caneditall || $canadd) {
echo "\n";
}
if ($canadd) {
echo "\n";
// Not closed ticket or closed
if (!in_array($ticket->fields["status"],
array_merge($ticket->getSolvedStatusArray(), $ticket->getClosedStatusArray()))
|| $reopen_case) {
if (isset($_GET['_openfollowup']) && $_GET['_openfollowup']) {
echo Html::scriptBlock("viewAddFollowup".$ticket->fields['id']."$rand()");
} else {
echo "\n";
}
}
}
if ($DB->numrows($result) == 0) {
echo "";
echo "| " . __('No followup for this ticket.')." |
";
} else {
$today = strtotime('today');
$lastmonday = strtotime('last monday');
$lastlastmonday = strtotime('last monday', strtotime('last monday'));
// Case of monday
if (($today-$lastmonday)==7*DAY_TIMESTAMP) {
$lastlastmonday = $lastmonday;
$lastmonday = $today;
}
$steps = array(0 => array('end' => $today,
'name' => __('Today')),
1 => array('end' => $lastmonday,
'name' => __('This week')),
2 => array('end' => $lastlastmonday,
'name' => __('Last week')),
3 => array('end' => strtotime('midnight first day of'),
'name' => __('This month')),
4 => array('end' => strtotime('midnight first day of last month'),
'name' => __('Last month')),
5 => array('end' => 0,
'name' => __('Before the last month')),
);
$currentpos = -1;
while ($data = $DB->fetch_assoc($result)) {
$this->getFromDB($data['id']);
$options = array( 'parent' => $ticket,
'rand' => $rand
);
Plugin::doHook('pre_show_item', array('item' => $this, 'options' => &$options));
$data = array_merge( $data, $this->fields );
$candelete = $this->canPurge() && $this->canPurgeItem();
$canedit = $this->canUpdate() && $this->canUpdateItem();
$time = strtotime($data['date']);
if (!isset($steps[$currentpos])
|| ($steps[$currentpos]['end'] > $time)) {
$currentpos++;
while (($steps[$currentpos]['end'] > $time) && isset($steps[$currentpos+1])) {
$currentpos++;
}
if (isset($steps[$currentpos])) {
echo "".$steps[$currentpos]['name']."
";
}
}
$id = 'followup'.$data['id'].$rand;
$color = 'byuser';
if (isset($techs[$data['users_id']])) {
$color = 'bytech';
}
$classtoadd = '';
if ($canedit) {
$classtoadd = " pointer";
}
echo "";
echo "
";
echo "

";
echo "
"; // boxnoteleft
echo "
";
echo "
";
$username = NOT_AVAILABLE;
if ($data['users_id']) {
$username = getUserName($data['users_id'], $showuserlink);
}
$name = sprintf(__('Create by %1$s on %2$s'), $username,
Html::convDateTime($data['date']));
if ($data['requesttypes_id']) {
$name = sprintf(__('%1$s - %2$s'), $name,
Dropdown::getDropdownName('glpi_requesttypes',
$data['requesttypes_id']));
}
if ($showprivate && $data["is_private"]) {
$name = sprintf(__('%1$s - %2$s'), $name, __('Private'));
}
echo $name;
echo "
"; // floatright
echo "
fields['id'].
$data['id']."$rand(); ".Html::jsHide("view$id")." ".
Html::jsShow("viewfollowup" . $ticket->fields['id'].$data["id"]."$rand")."\" ";
}
echo ">";
$content = nl2br($data['content']);
if (empty($content)) $content = NOT_AVAILABLE;
echo $content.'
'; // boxnotetext
echo "
"; // boxnotecontent
echo "
";
if ($candelete) {
Html::showSimpleForm(Toolbox::getItemTypeFormURL('TicketFollowup'),
array('purge' => 'purge'),
_x('button', 'Delete permanently'),
array('id' => $data['id']),
$CFG_GLPI["root_doc"]."/pics/delete.png",
'',
__('Confirm the final deletion?'));
}
echo "
"; // boxnoteright
echo "
"; // boxnote
if ($canedit) {
echo "\n";
echo "\n\n";
}
Plugin::doHook('post_show_item', array('item' => $this, 'options' => $options));
}
}
}
/**
* @param $ID integer ID of the ticket
**/
static function showShortForTicket($ID) {
global $DB, $CFG_GLPI;
// Print Followups for a job
$showprivate = Session::haveRight(self::$rightname, self::SEEPRIVATE);
$RESTRICT = "";
if (!$showprivate) {
$RESTRICT = " AND (`is_private` = '0'
OR `users_id` ='".Session::getLoginUserID()."') ";
}
// Get Number of Followups
$query = "SELECT *
FROM `glpi_ticketfollowups`
WHERE `tickets_id` = '$ID'
$RESTRICT
ORDER BY `date` DESC";
$result = $DB->query($query);
$out = "";
if ($DB->numrows($result) > 0) {
$out .= "\n
| ".__('Date')." | ".__('Requester')." |
".__('Description')." |
\n";
$showuserlink = 0;
if (Session::haveRight('user', READ)) {
$showuserlink = 1;
}
while ($data = $DB->fetch_assoc($result)) {
$out .= "
| ".Html::convDateTime($data["date"])." |
".getUserName($data["users_id"], $showuserlink)." |
".Html::resume_text($data["content"],
$CFG_GLPI["cut"])."
|
";
}
$out .= "
";
}
return $out;
}
/** form for soluce's approbation
*
* @param $ticket Object : the ticket
**/
function showApprobationForm($ticket) {
global $DB, $CFG_GLPI;
$input = array('tickets_id' => $ticket->getField('id'));
if (($ticket->fields["status"] == CommonITILObject::SOLVED)
&& $ticket->canApprove()
&& $ticket->isAllowedStatus($ticket->fields['status'], Ticket::CLOSED)) {
echo "