. * --------------------------------------------------------------------- */ 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 "
"; echo ""; echo ""; echo ""; echo "
".__('Add a ticket')."
"; echo ""; $condition = [ 'NOT' => [ 'glpi_tickets.status' => array_merge( Ticket::getSolvedStatusArray(), Ticket::getClosedStatusArray() ) ] ]; Ticket::dropdown([ 'used' => $used, 'entity' => $projecttask->getEntityID(), 'entity_sons' => $projecttask->isRecursive(), 'condition' => $condition, 'displaywith' => ['id'] ]); echo ""; echo ""; echo __('Create a ticket from this task'); echo ""; echo ""; echo ""; echo "
"; Html::closeForm(); 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 ""; 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 "
".Ticket::getTypeName($numrows)."
"; 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 ""; echo ""; echo ""; $rand = mt_rand(); $finished_states_it = $DB->request( [ 'SELECT' => ['id'], 'FROM' => ProjectState::getTable(), 'WHERE' => [ 'is_finished' => 1 ], ] ); $finished_states_ids = []; foreach ($finished_states_it as $finished_state) { $finished_states_ids[] = $finished_state['id']; } echo ""; if (count($finished_states_ids)) { $where = [ 'OR' => [ 'projectstates_id' => $finished_states_ids, 'is_template' => 1 ] ]; } else { $where = ['is_template' => 1]; } $excluded_projects_it = $DB->request( [ 'SELECT' => ['id'], 'FROM' => Project::getTable(), 'WHERE' => $where ] ); $excluded_projects_ids = []; foreach ($excluded_projects_it as $excluded_project) { $excluded_projects_ids[] = $excluded_project['id']; } echo ""; echo "
".__('Add a project task')."
"; echo Html::hidden('tickets_id', ['value' => $ID]); Project::dropdown([ 'entity' => $ticket->getEntityID(), 'entity_sons' => $ticket->isRecursive(), 'condition' => ['NOT' => ['glpi_projects.projectstates_id' => $finished_states_ids]], 'rand' => $rand ]); $p = ['projects_id' => '__VALUE__', 'entity_restrict' => $ticket->getEntityID(), 'used' => $used, 'rand' => $rand, 'myname' => "projects"]; Ajax::updateItemOnSelectEvent("dropdown_projects_id$rand", "results_projects$rand", $CFG_GLPI["root_doc"]. "/ajax/dropdownProjectTaskTicket.php", $p); echo ""; echo ""; $dd_params = [ 'used' => $used, 'entity' => $ticket->getEntityID(), 'entity_sons' => $ticket->isRecursive(), 'displaywith' => ['id'] ]; $condition = []; if (count($finished_states_ids)) { $condition['glpi_projecttasks.projectstates_id'] = $finished_states_ids; } if (count($excluded_projects_ids)) { $condition['glpi_projecttasks.projects_id'] = $excluded_projects_ids; } if (count($condition)) { $dd_params['condition'] = ['NOT' => $condition]; } ProjectTask::dropdown($dd_params); echo ""; echo ""; echo ""; echo Html::submit(_sx('button', 'Add'), ['name' => 'add']); echo "
"; Html::closeForm(); 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 ""; echo ""; $header = ''; foreach ($columns as $key => $val) { // Non order column if ($key[0] == '_') { $header .= ""; } else { $header .= "". "$val"; } } $header .= "\n"; echo $header; while ($data = $iterator->next()) { Session::addToNavigateListItems('ProjectTask', $data['id']); $rand = mt_rand(); echo ""; echo ""; echo ""; echo ""; echo "".$data['sname'].""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } echo $header; echo "
".ProjectTask::getTypeName($numrows)."
$val
"; $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 ""; $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 "".$data['tname'].""; echo Dropdown::getValueWithUnit($data["percent_done"], "%"); echo "".Html::convDateTime($data['plan_start_date'])."".Html::convDateTime($data['plan_end_date'])."".Html::timestampToString($data['planned_duration'], false)."".Html::timestampToString(ProjectTask::getTotalEffectiveDuration($data['id']), false).""; if ($data['projecttasks_id']>0) { $father = Dropdown::getDropdownName('glpi_projecttasks', $data['projecttasks_id']); echo "".$father. (empty($father)?"(".$data['projecttasks_id'].")":"").""; } echo "
\n"; } else { echo ""; echo ""; echo "
".__('No item found')."
\n"; } echo "
"; } } }