.
* ---------------------------------------------------------------------
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
/**
* ProjectTask_Ticket Class
*
* Relation between ProjectTasks and Tickets
*
* @since 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 = self::countForItem($item);
}
return self::createTabEntry(Ticket::getTypeName(Session::getPluralNumber()), $nb);
case 'Ticket' :
if ($_SESSION['glpishow_count_on_tabs']) {
$nb = self::countForItem($item);
}
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;
$iterator = $DB->request([
'SELECT' => new QueryExpression('SUM(glpi_tickets.actiontime) AS duration'),
'FROM' => self::getTable(),
'INNER JOIN' => [
'glpi_tickets' => [
'FKEY' => [
self::getTable() => 'tickets_id',
'glpi_tickets' => 'id'
]
]
],
'WHERE' => ['projecttasks_id' => $projecttasks_id]
]);
if ($row = $iterator->next()) {
return $row['duration'];
}
return 0;
}
/**
* Show tickets for a projecttask
*
* @param $projecttask ProjectTask object
**/
static function showForProjectTask(ProjectTask $projecttask) {
$ID = $projecttask->getField('id');
if (!$projecttask->can($ID, READ)) {
return false;
}
$canedit = $projecttask->canEdit($ID);
$rand = mt_rand();
$iterator = self::getListForItem($projecttask);
$numrows = count($iterator);
$tickets = [];
$used = [];
while ($data = $iterator->next()) {
$tickets[$data['id']] = $data;
$used[$data['id']] = $data['id'];
}
if ($canedit) {
echo "
";
}
echo "";
if ($canedit && $numrows) {
Html::openMassiveActionsForm('mass'.__CLASS__.$rand);
$massiveactionparams = ['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'], ['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();
$iterator = self::getListForItem($ticket);
$numrows = count($iterator);
$pjtasks = [];
$used = [];
while ($data = $iterator->next()) {
$pjtasks[$data['id']] = $data;
$used[$data['id']] = $data['id'];
}
if ($canedit
&& !in_array($ticket->fields['status'], array_merge($ticket->getClosedStatusArray(),
$ticket->getSolvedStatusArray()))) {
echo "";
}
echo "";
if ($numrows) {
$columns = ['projectname' => Project::getTypeName(Session::getPluralNumber()),
'name' => ProjectTask::getTypeName(Session::getPluralNumber()),
'tname' => _n('Type', 'Types', 1),
'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'];
}
$iterator = $DB->request([
'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'
]
],
'glpi_projectstates' => [
'ON' => [
'glpi_projectstates' => 'id',
'glpi_projecttasks' => 'projectstates_id'
]
],
'glpi_projecttasks AS father' => [
'ON' => [
'father' => 'id',
'glpi_projecttasks' => 'projecttasks_id'
]
],
'glpi_projecttasks_tickets' => [
'ON' => [
'glpi_projecttasks_tickets' => 'projecttasks_id',
'glpi_projecttasks' => 'id'
]
],
'glpi_projects' => [
'ON' => [
'glpi_projecttasks' => 'projects_id',
'glpi_projects' => 'id'
]
]
],
'WHERE' => [
'glpi_projecttasks_tickets.tickets_id' => $ID
],
'ORDERBY' => [
"$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 (count($iterator)) {
echo "
";
echo "| ".ProjectTask::getTypeName($numrows)." | ";
echo "
";
$header = '';
foreach ($columns as $key => $val) {
// Non order column
if ($key[0] == '_') {
$header .= "| $val | ";
} else {
$header .= "".
"$val | ";
}
}
$header .= "
\n";
echo $header;
while ($data = $iterator->next()) {
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'],
['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'],
['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 "
";
}
}
}