grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026.
--------------------------------------------------------------------------
*/
/** @file
* @brief
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
/**
* ProjectTask_Ticket Class
*
* Relation between ProjectTasks and Tickets
*
* @since version 0.85
**/
class ProjectTask_Ticket extends CommonDBRelation{
// From CommonDBRelation
static public $itemtype_1 = 'ProjectTask';
static public $items_id_1 = 'projecttasks_id';
static public $itemtype_2 = 'Ticket';
static public $items_id_2 = 'tickets_id';
function getForbiddenStandardMassiveAction() {
$forbidden = parent::getForbiddenStandardMassiveAction();
$forbidden[] = 'update';
return $forbidden;
}
static function getTypeName($nb=0) {
return _n('Link Ticket/Project task','Links Ticket/Project task',$nb);
}
function getTabNameForItem(CommonGLPI $item, $withtemplate=0) {
if (static::canView()) {
$nb = 0;
switch ($item->getType()) {
case 'ProjectTask' :
if ($_SESSION['glpishow_count_on_tabs']) {
$nb = countElementsInTable('glpi_projecttasks_tickets',
"`projecttasks_id` = '".$item->getID()."'");
}
return self::createTabEntry(Ticket::getTypeName(Session::getPluralNumber()), $nb);
case 'Ticket' :
if ($_SESSION['glpishow_count_on_tabs']) {
$nb = countElementsInTable('glpi_projecttasks_tickets',
"`tickets_id` = '".$item->getID()."'");
}
return self::createTabEntry(ProjectTask::getTypeName(Session::getPluralNumber()), $nb);
}
}
return '';
}
static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) {
switch ($item->getType()) {
case 'ProjectTask' :
self::showForProjectTask($item);
break;
case 'Ticket' :
self::showForTicket($item);
break;
}
return true;
}
/**
* Get total duration of tickets linked to a project task
*
* @param $projecttasks_id integer $projecttasks_id ID of the project task
*
* @return integer total actiontime
**/
static function getTicketsTotalActionTime($projecttasks_id) {
global $DB;
$query = "SELECT SUM(`glpi_tickets`.`actiontime`)
FROM `glpi_projecttasks_tickets`
INNER JOIN `glpi_tickets`
ON (`glpi_projecttasks_tickets`.`tickets_id` = `glpi_tickets`.`id`)
WHERE `glpi_projecttasks_tickets`.`projecttasks_id` = '$projecttasks_id';";
if ($result = $DB->query($query)) {
if ($DB->numrows($result)) {
return $DB->result($result, 0, 0);
}
}
return 0;
}
/**
* Show tickets for a projecttask
*
* @param $projecttask ProjectTask object
**/
static function showForProjectTask(ProjectTask $projecttask) {
global $DB, $CFG_GLPI;
$ID = $projecttask->getField('id');
if (!$projecttask->can($ID, READ)) {
return false;
}
$canedit = $projecttask->canEdit($ID);
$rand = mt_rand();
$query = "SELECT DISTINCT `glpi_projecttasks_tickets`.`id` AS linkID,
`glpi_tickets`.*
FROM `glpi_projecttasks_tickets`
LEFT JOIN `glpi_tickets`
ON (`glpi_projecttasks_tickets`.`tickets_id` = `glpi_tickets`.`id`)
WHERE `glpi_projecttasks_tickets`.`projecttasks_id` = '$ID'
ORDER BY `glpi_tickets`.`name`";
$result = $DB->query($query);
$tickets = array();
$used = array();
if ($numrows = $DB->numrows($result)) {
while ($data = $DB->fetch_assoc($result)) {
$tickets[$data['id']] = $data;
$used[$data['id']] = $data['id'];
}
}
if ($canedit) {
echo "
";
}
echo "";
if ($canedit && $numrows) {
Html::openMassiveActionsForm('mass'.__CLASS__.$rand);
$massiveactionparams = array('num_displayed' => min($_SESSION['glpilist_limit'], $numrows),
'container' => 'mass'.__CLASS__.$rand);
Html::showMassiveActions($massiveactionparams);
}
echo "
";
echo "| ".Ticket::getTypeName($numrows)." | ";
echo "
";
if ($numrows) {
Ticket::commonListHeader(Search::HTML_OUTPUT,'mass'.__CLASS__.$rand);
Session::initNavigateListItems('Ticket',
//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'), ProjectTask::getTypeName(1),
$projecttask->fields["name"]));
$i = 0;
foreach ($tickets as $data) {
Session::addToNavigateListItems('Ticket', $data["id"]);
Ticket::showShort($data['id'], array('followups' => false,
'row_num' => $i,
'type_for_massiveaction' => __CLASS__,
'id_for_massiveaction' => $data['linkID']));
$i++;
}
}
echo "
";
if ($canedit && $numrows) {
$massiveactionparams['ontop'] = false;
Html::showMassiveActions($massiveactionparams);
Html::closeForm();
}
echo "
";
}
/**
* Show projecttasks for a ticket
*
* @param $ticket Ticket object
**/
static function showForTicket(Ticket $ticket) {
global $DB, $CFG_GLPI;
$ID = $ticket->getField('id');
if (!$ticket->can($ID, READ)) {
return false;
}
$canedit = $ticket->canEdit($ID);
$rand = mt_rand();
$query = "SELECT DISTINCT `glpi_projecttasks_tickets`.`id` AS linkID,
`glpi_projecttasks`.*
FROM `glpi_projecttasks`
LEFT JOIN `glpi_projecttasks_tickets`
ON (`glpi_projecttasks_tickets`.`projecttasks_id` = `glpi_projecttasks`.`id`)
WHERE `glpi_projecttasks_tickets`.`tickets_id` = '$ID'
ORDER BY `glpi_projecttasks`.`name`";
$result = $DB->query($query);
$pjtasks = array();
$used = array();
if ($numrows = $DB->numrows($result)) {
while ($data = $DB->fetch_assoc($result)) {
$pjtasks[$data['id']] = $data;
$used[$data['id']] = $data['id'];
}
}
// if ($canedit) {
// echo "";
// }
echo "";
if ($numrows) {
$columns = array('projectname' => Project::getTypeName(Session::getPluralNumber()),
'name' => ProjectTask::getTypeName(Session::getPluralNumber()),
'tname' => __('Type'),
'sname' => __('Status'),
'percent_done' => __('Percent done'),
'plan_start_date' => __('Planned start date'),
'plan_end_date' => __('Planned end date'),
'planned_duration' => __('Planned duration'),
'_effect_duration' => __('Effective duration'),
'fname' => __('Father'),);
if (isset($_GET["order"]) && ($_GET["order"] == "DESC")) {
$order = "DESC";
} else {
$order = "ASC";
}
if (!isset($_GET["sort"]) || empty($_GET["sort"])) {
$_GET["sort"] = "plan_start_date";
}
if (isset($_GET["sort"]) && !empty($_GET["sort"]) && isset($columns[$_GET["sort"]])) {
$sort = "`".$_GET["sort"]."`";
} else {
$sort = "`plan_start_date` $order, `name`";
}
$query = "SELECT `glpi_projecttasks`.*,
`glpi_projecttasktypes`.`name` AS tname,
`glpi_projectstates`.`name` AS sname,
`glpi_projectstates`.`color`,
`father`.`name` AS fname,
`father`.`id` AS fID,
`glpi_projects`.`name` AS projectname,
`glpi_projects`.`content` AS projectcontent
FROM `glpi_projecttasks`
LEFT JOIN `glpi_projecttasktypes`
ON (`glpi_projecttasktypes`.`id` = `glpi_projecttasks`.`projecttasktypes_id`)
LEFT JOIN `glpi_projectstates`
ON (`glpi_projectstates`.`id` = `glpi_projecttasks`.`projectstates_id`)
LEFT JOIN `glpi_projecttasks` as father
ON (`father`.`id` = `glpi_projecttasks`.`projecttasks_id`)
LEFT JOIN `glpi_projecttasks_tickets`
ON (`glpi_projecttasks_tickets`.`projecttasks_id` = `glpi_projecttasks`.`id`)
LEFT JOIN `glpi_projects`
ON (`glpi_projecttasks`.`projects_id` = `glpi_projects`.`id`)
WHERE `glpi_projecttasks_tickets`.`tickets_id` = '$ID'
ORDER BY $sort $order";
Session::initNavigateListItems('ProjectTask',
//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'), $ticket::getTypeName(1),
$ticket->getName()));
if ($result = $DB->query($query)) {
if ($DB->numrows($result)) {
echo "
";
echo "| ".ProjectTask::getTypeName($numrows)." | ";
echo "
";
$sort_img = "
";
$header = '';
foreach ($columns as $key => $val) {
// Non order column
if ($key[0] == '_') {
$header .= "| $val | ";
} else {
$header .= "".(($sort == "`$key`") ?$sort_img:"").
"$val | ";
}
}
$header .= "
\n";
echo $header;
while ($data=$DB->fetch_assoc($result)) {
Session::addToNavigateListItems('ProjectTask',$data['id']);
$rand = mt_rand();
echo "";
echo "| ";
$link = "".$data['projectname'].
(empty($data['projectname'])?"(".$data['projects_id'].")":"")."";
echo sprintf(__('%1$s %2$s'), $link,
Html::showToolTip($data['projectcontent'],
array('display' => false,
'applyto' => "Project".$data["projects_id"].$rand)));
echo " | ";
echo "";
$link = "".$data['name'].
(empty($data['name'])?"(".$data['id'].")":"")."";
echo sprintf(__('%1$s %2$s'), $link,
Html::showToolTip($data['content'],
array('display' => false,
'applyto' => "ProjectTask".$data["id"].$rand)));
echo " | ";
echo "".$data['tname']." | ";
echo "".$data['sname']." | ";
echo "";
echo Dropdown::getValueWithUnit($data["percent_done"],"%");
echo " | ";
echo "".Html::convDateTime($data['plan_start_date'])." | ";
echo "".Html::convDateTime($data['plan_end_date'])." | ";
echo "".Html::timestampToString($data['planned_duration'], false)." | ";
echo "".Html::timestampToString(ProjectTask::getTotalEffectiveDuration($data['id']),
false)." | ";
echo "";
if ($data['projecttasks_id']>0) {
$father = Dropdown::getDropdownName('glpi_projecttasks', $data['projecttasks_id']);
echo "".$father.
(empty($father)?"(".$data['projecttasks_id'].")":"")."";
}
echo " |
";
}
echo $header;
echo "
\n";
} else {
echo "
";
echo "| ".__('No item found')." |
";
echo "
\n";
}
}
echo "
";
}
}
}
?>