grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026. -------------------------------------------------------------------------- */ /** @file * @brief */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * ProjectTask Class * * @since version 0.85 **/ class ProjectTask extends CommonDBChild { // From CommonDBTM public $dohistory = true; // From CommonDBChild static public $itemtype = 'Project'; static public $items_id = 'projects_id'; protected $team = array(); static $rightname = 'projecttask'; protected $usenotepad = true; public $can_be_translated = true; const READMY = 1; const UPDATEMY = 1024; static function getTypeName($nb=0) { return _n('Project task', 'Project tasks', $nb); } static function canView() { return (Session::haveRightsOr('project', array(Project::READALL, Project::READMY)) || Session::haveRight(self::$rightname, ProjectTask::READMY)); } /** * Is the current user have right to show the current task ? * * @return boolean **/ function canViewItem() { if (!Session::haveAccessToEntity($this->getEntityID())) { return false; } $project = new Project(); if ($project->getFromDB($this->fields['projects_id'])) { return (Session::haveRight('project', Project::READALL) || (Session::haveRight('project', Project::READMY) && (($project->fields["users_id"] === Session::getLoginUserID()) || $project->isInTheManagerGroup() || $project->isInTheTeam())) || (Session::haveRight(self::$rightname, self::READMY) && (($this->fields["users_id"] === Session::getLoginUserID()) || $this->isInTheTeam()))); } return false; } static function canCreate() { return (Session::haveRight('project', UPDATE)); } static function canUpdate() { return (parent::canUpdate() || Session::haveRight(self::$rightname, self::UPDATEMY)); } /** * Is the current user have right to edit the current task ? * * @return boolean **/ function canUpdateItem() { if (!Session::haveAccessToEntity($this->getEntityID())) { return false; } $project = new Project(); if ($project->getFromDB($this->fields['projects_id'])) { return (Session::haveRight('project', UPDATE) || (Session::haveRight(self::$rightname, self::UPDATEMY) && (($this->fields["users_id"] === Session::getLoginUserID()) || $this->isInTheTeam()))); } return false; } function cleanDBonPurge() { global $DB; $pt = new ProjectTaskTeam(); $pt->cleanDBonItemDelete(__CLASS__, $this->fields['id']); $pt = new ProjectTask_Ticket(); $pt->cleanDBonItemDelete(__CLASS__, $this->fields['id']); parent::cleanDBonPurge(); } /** * @see commonDBTM::getRights() **/ function getRights($interface='central') { $values = array(); $values[self::READMY] = __('See (actor)'); $values[self::UPDATEMY] = __('Update (actor)'); return $values; } function defineTabs($options=array()) { $ong = array(); $this->addDefaultFormTab($ong); $this->addStandardTab(__CLASS__,$ong, $options); $this->addStandardTab('ProjectTaskTeam',$ong, $options); $this->addStandardTab('Document_Item', $ong, $options); $this->addStandardTab('ProjectTask_Ticket',$ong, $options); $this->addStandardTab('Notepad',$ong, $options); $this->addStandardTab('Log',$ong, $options); return $ong; } function post_getFromDB() { // Team $this->team = ProjectTaskTeam::getTeamFor($this->fields['id']); } function post_getEmpty() { $this->fields['percent_done'] = 0; } function post_updateItem($history=1) { global $CFG_GLPI; if (!isset($this->input['_disablenotif']) && $CFG_GLPI["use_mailing"]) { // Read again project to be sure that all data are up to date $this->getFromDB($this->fields['id']); NotificationEvent::raiseEvent("update", $this); } } function post_addItem() { global $DB, $CFG_GLPI; if (!isset($this->input['_disablenotif']) && $CFG_GLPI["use_mailing"]) { // Clean reload of the project $this->getFromDB($this->fields['id']); NotificationEvent::raiseEvent('new', $this); } } /** * Is the current user in the team? * * @return boolean **/ function isInTheTeam() { if (isset($this->team['User']) && count($this->team['User'])) { foreach ($this->team['User'] as $data) { if ($data['items_id'] == Session::getLoginUserID()) { return true; } } } if (isset($_SESSION['glpigroups']) && count($_SESSION['glpigroups']) && isset($this->team['Group']) && count($this->team['Group'])) { foreach ($_SESSION['glpigroups'] as $groups_id) { foreach ($this->team['Group'] as $data) { if ($data['items_id'] == $groups_id) { return true; } } } } return false; } /** * Get team member count * * @return number */ function getTeamCount() { $nb = 0; if (is_array($this->team) && count($this->team)) { foreach ($this->team as $val) { $nb += count($val); } } return $nb; } function pre_deleteItem() { global $CFG_GLPI; if (!isset($this->input['_disablenotif']) && $CFG_GLPI['use_mailing']) { NotificationEvent::raiseEvent('delete', $this); } return true; } function prepareInputForUpdate($input) { if (isset($input["plan"])) { $input["plan_start_date"] = $input['plan']["begin"]; $input["plan_end_date"] = $input['plan']["end"]; } if (isset($input['is_milestone']) && $input['is_milestone']){ $input['plan_end_date'] = $input['plan_start_date']; $input['real_end_date'] = $input['real_start_date']; } return Project::checkPlanAndRealDates($input); } function prepareInputForAdd($input) { if (!isset($input['users_id'])) { $input['users_id'] = Session::getLoginUserID(); } if (!isset($input['date'])) { $input['date'] = $_SESSION['glpi_currenttime']; } if (isset($input['is_milestone']) && $input['is_milestone']){ $input['plan_end_date'] = $input['plan_start_date']; $input['real_end_date'] = $input['real_start_date']; } return Project::checkPlanAndRealDates($input); } /** * Get all tasks for a project * * @param $ID integer Id of the project * * @return array of tasks ordered by dates **/ static function getAllForProject($ID) { global $DB; $tasks = array(); foreach ($DB->request('glpi_projecttasks', array("projects_id" => $ID, 'ORDER' => array('plan_start_date', 'real_start_date'))) as $data) { $tasks[] = $data; } return $tasks; } /** * Get all linked tickets for a project * * @param $ID integer Id of the project * * @return array of tickets **/ static function getAllTicketsForProject($ID) { global $DB; $tasks = array(); foreach ($DB->request(array('glpi_projecttasks_tickets', 'glpi_projecttasks'), array("`glpi_projecttasks`.`projects_id`" => $ID, "`glpi_projecttasks_tickets`.`projecttasks_id`" => "`glpi_projecttasks`.`id`", 'FIELDS' => "tickets_id" )) as $data) { $tasks[] = $data['tickets_id']; } return $tasks; } /** * Print the Project task form * * @param $ID integer Id of the project task * @param $options array of possible options: * - target form target * - projects_id ID of the software for add process * * @return true if displayed false if item not found or not right to display **/ function showForm($ID, $options=array()) { global $CFG_GLPI; if ($ID > 0) { $this->check($ID, READ); $projects_id = $this->fields['projects_id']; $projecttasks_id = $this->fields['projecttasks_id']; } else { $this->check(-1, CREATE, $options); $projects_id = $options['projects_id']; $projecttasks_id = $options['projecttasks_id']; $recursive = $this->fields['is_recursive']; } $this->showFormHeader($options); echo ""._n('Project', 'Projects', Session::getPluralNumber()).""; echo ""; if ($this->isNewID($ID)) { echo ""; echo ""; } echo "". Dropdown::getDropdownName("glpi_projects", $projects_id).""; echo ""; echo "".__('As child of').""; echo ""; $this->dropdown(array('entity' => $this->fields['entities_id'], 'value' => $projecttasks_id, 'condition' => "`glpi_projecttasks`.`projects_id`='". $this->fields['projects_id']."'", 'used' => array($this->fields['id']))); echo ""; $showuserlink = 0; if (Session::haveRight('user', READ)) { $showuserlink = 1; } if ($ID) { echo ""; echo "".__('Creation date').""; echo ""; echo sprintf(__('%1$s by %2$s'), Html::convDateTime($this->fields["date"]), getUserName($this->fields["users_id"], $showuserlink)); echo ""; echo "".__('Last update').""; echo ""; echo Html::convDateTime($this->fields["date_mod"]); echo ""; } echo "".__('Name').""; echo ""; Html::autocompletionTextField($this,"name", array('size' => 80)); echo "\n"; echo ""; echo ""._x('item', 'State').""; echo ""; ProjectState::dropdown(array('value' => $this->fields["projectstates_id"])); echo ""; echo "".__('Type').""; echo ""; ProjectTaskType::dropdown(array('value' => $this->fields["projecttasktypes_id"])); echo ""; echo ""; echo "".__('Percent done').""; echo ""; Dropdown::showNumber("percent_done", array('value' => $this->fields['percent_done'], 'min' => 0, 'max' => 100, 'step' => 5, 'unit' => '%')); echo ""; echo ""; _e('Milestone'); echo ""; echo ""; $rand = mt_rand(); Dropdown::showYesNo("is_milestone", $this->fields["is_milestone"], -1, ['rand' => $rand]); $js = "$('#dropdown_is_milestone$rand').on('change', function(e) { $('tr.is_milestone').toggleClass('starthidden'); })"; echo Html::scriptBlock($js); echo ""; echo ""; echo "".__('Planning').""; echo ""; echo "".__('Planned start date').""; echo ""; Html::showDateTimeField("plan_start_date", array('value' => $this->fields['plan_start_date'])); echo ""; echo "".__('Real start date').""; echo ""; Html::showDateTimeField("real_start_date", array('value' => $this->fields['real_start_date'])); echo "\n"; echo ""; echo "".__('Planned end date').""; echo ""; Html::showDateTimeField("plan_end_date", array('value' => $this->fields['plan_end_date'])); echo ""; echo "".__('Real end date').""; echo ""; Html::showDateTimeField("real_end_date", array('value' => $this->fields['real_end_date'])); echo "\n"; echo ""; echo "".__('Planned duration').""; echo ""; Dropdown::showTimeStamp("planned_duration", array('min' => 0, 'max' => 100*HOUR_TIMESTAMP, 'step' => HOUR_TIMESTAMP, 'value' => $this->fields["planned_duration"], 'addfirstminutes' => true, 'inhours' => true)); echo ""; echo "".__('Effective duration').""; echo ""; Dropdown::showTimeStamp("effective_duration", array('min' => 0, 'max' => 100*HOUR_TIMESTAMP, 'step' => HOUR_TIMESTAMP, 'value' => $this->fields["effective_duration"], 'addfirstminutes' => true, 'inhours' => true)); if ($ID) { $ticket_duration = ProjectTask_Ticket::getTicketsTotalActionTime($this->getID()); echo "
"; printf(__('%1$s: %2$s'),__('Tickets duration'), Html::timestampToString($ticket_duration, false)); echo '
'; printf(__('%1$s: %2$s'),__('Total duration'), Html::timestampToString($ticket_duration+$this->fields["effective_duration"], false)); } echo "\n"; echo ""; echo "".__('Description').""; echo ""; echo ""; echo "\n"; echo ""; echo "".__('Comments').""; echo ""; echo ""; echo "\n"; $this->showFormButtons($options); return true; } /** * Get total effective duration of a project task (sum of effective duration + sum of action time of tickets) * * @param $projecttasks_id integer $projecttasks_id ID of the project task * * @return integer total effective duration **/ static function getTotalEffectiveDuration($projecttasks_id) { global $DB; $item = new static(); $time = 0; if ($item->getFromDB($projecttasks_id)) { $time += $item->fields['effective_duration']; } $query = "SELECT SUM(`glpi_tickets`.`actiontime`) FROM `glpi_projecttasks` LEFT JOIN `glpi_projecttasks_tickets` ON (`glpi_projecttasks`.`id` = `glpi_projecttasks_tickets`.`projecttasks_id`) LEFT JOIN `glpi_tickets` ON (`glpi_projecttasks_tickets`.`tickets_id` = `glpi_tickets`.`id`) WHERE `glpi_projecttasks`.`id` = '$projecttasks_id';"; if ($result = $DB->query($query)) { if ($DB->numrows($result)) { $time += $DB->result($result, 0, 0); } } return $time; } /** * Get total effective duration of a project (sum of effective duration + sum of action time of tickets) * * @param $projects_id integer $project_id ID of the project * * @return integer total effective duration **/ static function getTotalEffectiveDurationForProject($projects_id) { global $DB; $query = "SELECT `id` FROM `glpi_projecttasks` WHERE `glpi_projecttasks`.`projects_id` = '$projects_id';"; $time = 0; foreach ($DB->request($query) as $data) { $time += static::getTotalEffectiveDuration($data['id']); } return $time; } /** * Get total planned duration of a project * * @param $projects_id integer $project_id ID of the project * * @return integer total effective duration **/ static function getTotalPlannedDurationForProject($projects_id) { global $DB; $query = "SELECT SUM(`planned_duration`) as SUM FROM `glpi_projecttasks` WHERE `glpi_projecttasks`.`projects_id` = '$projects_id';"; foreach ($DB->request($query) as $data) { return $data['SUM']; } return 0; } function getSearchOptions() { $tab = array(); $tab['common'] = __('Characteristics'); $tab[1]['table'] = $this->getTable(); $tab[1]['field'] = 'name'; $tab[1]['name'] = __('Name'); $tab[1]['datatype'] = 'itemlink'; $tab[1]['massiveaction'] = false; // implicit key==1 $tab[2]['table'] = $this->getTable(); $tab[2]['field'] = 'id'; $tab[2]['name'] = __('ID'); $tab[2]['massiveaction'] = false; // implicit field is id $tab[2]['datatype'] = 'number'; $tab[2]['table'] = 'glpi_projects'; $tab[2]['field'] = 'name'; $tab[2]['name'] = __('Project'); $tab[2]['massiveaction'] = false; $tab[2]['datatype'] = 'dropdown'; $tab[13]['table'] = $this->getTable(); $tab[13]['field'] = 'name'; $tab[13]['name'] = __('Father'); $tab[13]['datatype'] = 'dropdown'; $tab[13]['massiveaction'] = false; // Add virtual condition to relink table $tab[13]['joinparams'] = array('condition' => "AND 1=1"); $tab[21]['table'] = $this->getTable(); $tab[21]['field'] = 'content'; $tab[21]['name'] = __('Description'); $tab[21]['massiveaction'] = false; $tab[21]['datatype'] = 'text'; $tab[12]['table'] = 'glpi_projectstates'; $tab[12]['field'] = 'name'; $tab[12]['name'] = _x('item', 'State'); $tab[12]['datatype'] = 'dropdown'; $tab[14]['table'] = 'glpi_projecttasktypes'; $tab[14]['field'] = 'name'; $tab[14]['name'] = __('Type'); $tab[14]['datatype'] = 'dropdown'; $tab[15]['table'] = $this->getTable(); $tab[15]['field'] = 'date'; $tab[15]['name'] = __('Opening date'); $tab[15]['datatype'] = 'datetime'; $tab[15]['massiveaction'] = false; $tab[19]['table'] = $this->getTable(); $tab[19]['field'] = 'date_mod'; $tab[19]['name'] = __('Last update'); $tab[19]['datatype'] = 'datetime'; $tab[19]['massiveaction'] = false; $tab[5]['table'] = $this->getTable(); $tab[5]['field'] = 'percent_done'; $tab[5]['name'] = __('Percent done'); $tab[5]['datatype'] = 'number'; $tab[5]['unit'] = '%'; $tab[5]['min'] = 0; $tab[5]['max'] = 100; $tab[5]['step'] = 5; $tab[24]['table'] = 'glpi_users'; $tab[24]['field'] = 'name'; $tab[24]['linkfield'] = 'users_id'; $tab[24]['name'] = __('Creator'); $tab[24]['datatype'] = 'dropdown'; $tab[7]['table'] = $this->getTable(); $tab[7]['field'] = 'plan_start_date'; $tab[7]['name'] = __('Planned start date'); $tab[7]['datatype'] = 'datetime'; $tab[8]['table'] = $this->getTable(); $tab[8]['field'] = 'plan_end_date'; $tab[8]['name'] = __('Planned end date'); $tab[8]['datatype'] = 'datetime'; $tab[9]['table'] = $this->getTable(); $tab[9]['field'] = 'real_start_date'; $tab[9]['name'] = __('Real start date'); $tab[9]['datatype'] = 'datetime'; $tab[10]['table'] = $this->getTable(); $tab[10]['field'] = 'real_end_date'; $tab[10]['name'] = __('Real end date'); $tab[10]['datatype'] = 'datetime'; $tab[11]['table'] = $this->getTable(); $tab[11]['field'] = 'planned_duration'; $tab[11]['name'] = __('Planned duration'); $tab[11]['datatype'] = 'timestamp'; $tab[11]['min'] = 0; $tab[11]['max'] = 100*HOUR_TIMESTAMP; $tab[11]['step'] = HOUR_TIMESTAMP; $tab[11]['addfirstminutes'] = true; $tab[11]['inhours'] = true; $tab[17]['table'] = $this->getTable(); $tab[17]['field'] = 'effective_duration'; $tab[17]['name'] = __('Effective duration'); $tab[17]['datatype'] = 'timestamp'; $tab[17]['min'] = 0; $tab[17]['max'] = 100*HOUR_TIMESTAMP; $tab[17]['step'] = HOUR_TIMESTAMP; $tab[17]['addfirstminutes'] = true; $tab[17]['inhours'] = true; $tab[16]['table'] = $this->getTable(); $tab[16]['field'] = 'comment'; $tab[16]['name'] = __('Comments'); $tab[16]['datatype'] = 'text'; $tab[18]['table'] = $this->getTable(); $tab[18]['field'] = 'is_milestone'; $tab[18]['name'] = __('Milestone'); $tab[18]['datatype'] = 'bool'; $tab[80]['table'] = 'glpi_entities'; $tab[80]['field'] = 'completename'; $tab[80]['name'] = __('Entity'); $tab[80]['datatype'] = 'dropdown'; $tab[86]['table'] = $this->getTable(); $tab[86]['field'] = 'is_recursive'; $tab[86]['name'] = __('Child entities'); $tab[86]['datatype'] = 'bool'; $tab += Notepad::getSearchOptionsToAdd(); return $tab; } /** * Show tasks of a project * * @param $item Project or ProjectTask object * * @return nothing **/ static function showFor($item) { global $DB, $CFG_GLPI; $ID = $item->getField('id'); if (!$item->canViewItem()) { return false; } $columns = array('name' => self::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`"; } $canedit = false; if ($item->getType() =='Project') { $canedit = $item->canEdit($ID); } switch ($item->getType()) { case 'Project' : $where = "WHERE `glpi_projecttasks`.`projects_id` = '$ID'"; break; case 'ProjectTask' : $where = "WHERE `glpi_projecttasks`.`projecttasks_id` = '$ID'"; break; default : // Not available type return; } echo "
"; if ($canedit) { echo "
"; echo "". _x('button', 'Add a task').""; echo "
"; } if (($item->getType() == 'ProjectTask') && $item->can($ID, UPDATE)) { $rand = mt_rand(); echo "
"; echo "
"; $projet = $item->fields['projects_id']; echo ""; _e('Create a sub task from this task of project'); echo ""; Html::closeForm(); echo "
"; } $addselect = ''; $addjoin = ''; if (Session::haveTranslations('ProjectTaskType', 'name')) { $addselect .= ", `namet2`.`value` AS transname2"; $addjoin .= " LEFT JOIN `glpi_dropdowntranslations` AS namet2 ON (`namet2`.`itemtype` = 'ProjectTaskType' AND `namet2`.`items_id` = `glpi_projecttasks`.`projecttasktypes_id` AND `namet2`.`language` = '".$_SESSION['glpilanguage']."' AND `namet2`.`field` = 'name')"; } if (Session::haveTranslations('ProjectState', 'name')) { $addselect .= ", `namet3`.`value` AS transname3"; $addjoin .= "LEFT JOIN `glpi_dropdowntranslations` AS namet3 ON (`namet3`.`itemtype` = 'ProjectState' AND `namet3`.`language` = '".$_SESSION['glpilanguage']."' AND `namet3`.`field` = 'name')"; $where .= " AND `namet3`.`items_id` = `glpi_projectstates`.`id` "; } $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 $addselect FROM `glpi_projecttasks` $addjoin 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`) $where 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'), $item::getTypeName(1), $item->getName())); if ($result = $DB->query($query)) { if ($DB->numrows($result)) { echo ""; $sort_img = ""; $header = ''; foreach ($columns as $key => $val) { // Non order column if ($key[0] == '_') { $header .= ""; } else { $header .= ""; } } $header .= "\n"; echo $header; while ($data=$DB->fetch_assoc($result)) { Session::addToNavigateListItems('ProjectTask',$data['id']); $rand = mt_rand(); echo ""; echo ""; $name = !empty($data['transname2'])?$data['transname2']:$data['tname']; echo ""; echo "".$statename.""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } echo $header; echo "
$val".(($sort == "`$key`") ?$sort_img:""). "$val
"; $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 "".$name.""; 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(self::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 "
"; } function getTabNameForItem(CommonGLPI $item, $withtemplate=0) { if (!$withtemplate) { $nb = 0; switch ($item->getType()) { case 'Project' : if ($_SESSION['glpishow_count_on_tabs']) { $nb = countElementsInTable($this->getTable(), "projects_id = '".$item->getID()."'"); } return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), $nb); case __CLASS__ : if ($_SESSION['glpishow_count_on_tabs']) { $nb = countElementsInTable($this->getTable(), "projecttasks_id = '".$item->getID()."'"); } return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), $nb); } } return ''; } static function displayTabContentForItem(CommonGLPI $item, $tabnum=1, $withtemplate=0) { switch ($item->getType()) { case 'Project' : self::showFor($item); break; case __CLASS__ : self::showFor($item); break; } return true; } /** * Show team for a project task * * @param $task ProjectTask object * * @return boolean **/ function showTeam(ProjectTask $task) { global $DB, $CFG_GLPI; /// TODO : permit to simple add member of project team ? $ID = $task->fields['id']; $canedit = $task->canEdit($ID); $rand = mt_rand(); $nb = 0; $nb = $task->getTeamCount(); if ($canedit) { echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
".__('Add a team member')."
"; $params = array('itemtypes' => ProjectTeam::$available_types, 'entity_restrict' => ($task->fields['is_recursive'] ? getSonsOf('glpi_entities', $task->fields['entities_id']) : $task->fields['entities_id']), ); $addrand = Dropdown::showSelectItemFromItemtypes($params); echo ""; echo ""; echo "
"; Html::closeForm(); echo "
"; } echo "
"; if ($canedit && $nb) { Html::openMassiveActionsForm('mass'.__CLASS__.$rand); $massiveactionparams = array('num_displayed' => min($_SESSION['glpilist_limit'], $nb), 'container' => 'mass'.__CLASS__.$rand); // 'specific_actions' // => array('delete' => _x('button', 'Delete permanently')) ); // // if ($this->fields['users_id'] != Session::getLoginUserID()) { // $massiveactionparams['confirm'] // = __('Caution! You are not the author of this element. Delete targets can result in loss of access to that element.'); // } Html::showMassiveActions($massiveactionparams); } echo ""; $header_begin = ""; $header_top = ''; $header_bottom = ''; $header_end = ''; if ($canedit && $nb) { $header_top .= ""; $header_bottom .= ""; } $header_end .= ""; $header_end .= ""; $header_end .= ""; echo $header_begin.$header_top.$header_end; foreach (ProjectTaskTeam::$available_types as $type) { if (isset($task->team[$type]) && count($task->team[$type])) { if ($item = getItemForItemtype($type)) { foreach ($task->team[$type] as $data) { $item->getFromDB($data['items_id']); echo ""; if ($canedit) { echo ""; } echo ""; echo ""; echo ""; } } } } if ($nb) { echo $header_begin.$header_bottom.$header_end; } echo "
".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); $header_top .= "".Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); $header_bottom .= "".__('Type').""._n('Member', 'Members', Session::getPluralNumber())."
"; Html::showMassiveActionCheckBox('ProjectTaskTeam',$data["id"]); echo "".$item->getTypeName(1)."".$item->getLink()."
"; if ($canedit && $nb) { $massiveactionparams['ontop'] =false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } echo "
"; // Add items return true; } /** Get data to display on GANTT for a project task * * @param $ID ID of the project task */ static function getDataToDisplayOnGantt($ID) { global $DB; $todisplay = array(); $task = new self(); // echo $ID.'
'; if ($task->getFromDB($ID)) { $subtasks = array(); foreach ($DB->request('glpi_projecttasks', array('projecttasks_id' => $ID, 'ORDER' => array('plan_start_date', 'real_start_date'))) as $data) { $subtasks += static::getDataToDisplayOnGantt($data['id']); } $real_begin = NULL; $real_end = NULL; // Use real if set if (!is_null($task->fields['real_start_date'])) { $real_begin = $task->fields['real_start_date']; } // Determine begin / end date of current task if not set (min/max sub projects / tasks) if (is_null($real_begin)) { if (!is_null($task->fields['plan_start_date'])) { $real_begin = $task->fields['plan_start_date']; } else { foreach($subtasks as $subtask) { if (is_null($real_begin) || (!is_null($subtask['from']) && ($real_begin > $subtask['from']))) { $real_begin = $subtask['from']; } } } } // Use real if set if (!is_null($task->fields['real_end_date'])) { $real_end = $task->fields['real_end_date']; } if (is_null($real_end)) { if (!is_null($task->fields['plan_end_date'])) { $real_end = $task->fields['plan_end_date']; } else { foreach($subtasks as $subtask) { if (is_null($real_end) || (!is_null($subtask['to']) && ($real_end < $subtask['to']))) { $real_end = $subtask['to']; } } } } $parents = 0; if ($task->fields['projecttasks_id'] > 0) { $parents = count(getAncestorsOf("glpi_projecttasks", $ID)); } if ($task->fields['is_milestone']){ $percent = ""; }else{ $percent = isset($task->fields['percent_done'])?$task->fields['percent_done']:0; } // Add current task $todisplay[$real_begin.'#'.$real_end.'#task'.$task->getID()] = array('id' => $task->getID(), 'name' => $task->fields['name'], 'desc' => $task->fields['content'], 'link' => $task->getlink(['linkoption' => " title='{$task->fields['name']}'"]), 'type' => 'task', 'percent' => $percent, 'from' => $real_begin, 'parents' => $parents, 'to' => $real_end, 'is_milestone' => $task->fields['is_milestone']); // Add ordered subtasks foreach($subtasks as $key => $val) { $todisplay[$key] = $val; } } return $todisplay; } /** Get data to display on GANTT for a project * * @param $ID ID of the project */ static function getDataToDisplayOnGanttForProject($ID) { global $DB; $todisplay = array(); $task = new self(); // Get all tasks without father foreach ($DB->request('glpi_projecttasks', array('projects_id' => $ID, 'projecttasks_id' => 0, 'ORDER' => array('plan_start_date', 'real_start_date'))) as $data) { if ($task->getFromDB($data['id'])) { $todisplay += static::getDataToDisplayOnGantt($data['id']); } } return $todisplay; } /** * Display debug information for current object **/ function showDebug() { NotificationEvent::debugEvent($this); } /** * Populate the planning with planned project tasks * * @since version 0.85 * * @param $options array of possible options: * - who ID of the user (0 = undefined) * - who_group ID of the group of users (0 = undefined) * - begin Date * - end Date * - color * - event_type_color * * @return array of planning item **/ static function populatePlanning($options=array()) { global $DB, $CFG_GLPI; $interv = array(); $ttask = new self; if (!isset($options['begin']) || ($options['begin'] == 'NULL') || !isset($options['end']) || ($options['end'] == 'NULL')) { return $interv; } $default_options = array( 'genical' => false, 'color' => '', 'event_type_color' => '', ); $options = array_merge($default_options, $options); $who = $options['who']; $who_group = $options['who_group']; $begin = $options['begin']; $end = $options['end']; // Get items to print $ASSIGN = ""; if ($who_group === "mine") { if (!$options['genical'] && count($_SESSION["glpigroups"])) { $groups = implode("','",$_SESSION['glpigroups']); $ASSIGN = "`glpi_projecttaskteams`.`itemtype` = 'Group' AND `glpi_projecttaskteams`.`items_id` IN (SELECT DISTINCT `groups_id` FROM `glpi_groups` WHERE `groups_id` IN ('$groups') AND `glpi_groups`.`is_assign`) AND "; } else { // Only personal ones $ASSIGN = "`glpi_projecttaskteams`.`itemtype` = 'User' AND `glpi_projecttaskteams`.`items_id` = '$who' AND "; } } else { if ($who > 0) { $ASSIGN = "`glpi_projecttaskteams`.`itemtype` = 'User' AND `glpi_projecttaskteams`.`items_id` = '$who' AND "; } if ($who_group > 0) { $ASSIGN = "`glpi_projecttaskteams`.`itemtype` = 'Group' AND `glpi_projecttaskteams`.`items_id` IN ('$who_group') AND "; } } if (empty($ASSIGN)) { $ASSIGN = "`glpi_projecttaskteams`.`itemtype` = 'User' AND `glpi_projecttaskteams`.`items_id` IN (SELECT DISTINCT `glpi_profiles_users`.`users_id` FROM `glpi_profiles` LEFT JOIN `glpi_profiles_users` ON (`glpi_profiles`.`id` = `glpi_profiles_users`.`profiles_id`) WHERE `glpi_profiles`.`interface` = 'central' ". getEntitiesRestrictRequest("AND", "glpi_profiles_users", '', $_SESSION["glpiactive_entity"], 1).") AND "; } $query = "SELECT `glpi_projecttasks`.* FROM `glpi_projecttaskteams` INNER JOIN `glpi_projecttasks` ON (`glpi_projecttasks`.`id` = `glpi_projecttaskteams`.`projecttasks_id`) WHERE $ASSIGN '$begin' < `glpi_projecttasks`.`plan_end_date` AND '$end' > `glpi_projecttasks`.`plan_start_date` ORDER BY `glpi_projecttasks`.`plan_start_date`"; $result = $DB->query($query); $interv = array(); $task = new self(); if ($DB->numrows($result) > 0) { for ($i=0 ; $data=$DB->fetch_assoc($result) ; $i++) { if ($task->getFromDB($data["id"])) { $key = $data["plan_start_date"]."$$$"."ProjectTask"."$$$".$data["id"]; $interv[$key]['color'] = $options['color']; $interv[$key]['event_type_color'] = $options['event_type_color']; $interv[$key]['itemtype'] = 'ProjectTask'; $interv[$key]["url"] = $CFG_GLPI["root_doc"]."/front/project.form.php?id=". $task->fields['projects_id']; $interv[$key]["ajaxurl"] = $CFG_GLPI["root_doc"]."/ajax/planning.php". "?action=edit_event_form". "&itemtype=ProjectTask". "&id=".$data['id']. "&url=".$interv[$key]["url"]; $interv[$key][$task->getForeignKeyField()] = $data["id"]; $interv[$key]["id"] = $data["id"]; $interv[$key]["users_id"] = $data["users_id"]; if (strcmp($begin,$data["plan_start_date"]) > 0) { $interv[$key]["begin"] = $begin; } else { $interv[$key]["begin"] = $data["plan_start_date"]; } if (strcmp($end,$data["plan_end_date"]) < 0) { $interv[$key]["end"] = $end; } else { $interv[$key]["end"] = $data["plan_end_date"]; } $interv[$key]["name"] = $task->fields["name"]; $interv[$key]["content"] = Html::resume_text($task->fields["content"], $CFG_GLPI["cut"]); $interv[$key]["status"] = $task->fields["percent_done"]; $ttask->getFromDB($data["id"]); $interv[$key]["editable"] = $ttask->canUpdateItem(); } } } return $interv; } /** * Display a Planning Item * * @since version 9.1 * * @param $val array of the item to display * @param $who ID of the user (0 if all) * @param $type position of the item in the time block (in, through, begin or end) * (default '') * @param $complete complete display (more details) (default 0) * * @return Nothing (display function) **/ static function displayPlanningItem(array $val, $who, $type="", $complete=0) { global $CFG_GLPI; $html = ""; $rand = mt_rand(); $users_id = ""; // show users_id project task $img = "rdv_private.png"; // default icon for project task if ($val["users_id"] != Session::getLoginUserID()) { $users_id = "
".sprintf(__('%1$s: %2$s'), __('By'), getUserName($val["users_id"])); $img = "rdv_public.png"; } $html.= " "; $html.= ""; switch ($type) { case "in" : //TRANS: %1$s is the start time of a planned item, %2$s is the end $beginend = sprintf(__('From %1$s to %2$s'), date("H:i",strtotime($val["begin"])), date("H:i",strtotime($val["end"]))); $html.= sprintf(__('%1$s: %2$s'), $beginend, Html::resume_text($val["name"],80)) ; break; case "through" : $html.= Html::resume_text($val["name"],80); break; case "begin" : $start = sprintf(__('Start at %s'), date("H:i", strtotime($val["begin"]))); $html.= sprintf(__('%1$s: %2$s'), $start, Html::resume_text($val["name"],80)) ; break; case "end" : $end = sprintf(__('End at %s'), date("H:i", strtotime($val["end"]))); $html.= sprintf(__('%1$s: %2$s'), $end, Html::resume_text($val["name"],80)) ; break; } $html.= $users_id; $html.= ""; $html.= "
"; $html.= sprintf(__('%1$s: %2$s'), __('Percent done'), $val["status"]."%") ; $html.= "
"; $html.= "
".html_entity_decode($val["content"])."
"; return $html; } }