name; $start = $task->s_start->getYYYYMMDD(); $end = $task->s_end->getYYYYMMDD(); $vol = $task->volume_done; #not used in coding, I guess... $planned = $task->volume; $todo = $task->volume_todo; $comp = $task->getcompletion(); $worker = $task->worker; for ($i = 1; $i < $depth; $i++) { $name = " ". $name; } $name .= " ["; $sep = ""; foreach ( $worker as $w => $f) { $name .= $sep . $f->GetFullname(); $sep = ", "; } $name .= "]"; #----workaround for presentation #if ( $todo == -1 ) { # $todo = "100 %"; #} else { # $todo = hour_format($todo,2); #} #------------------------------- if ($tutos[jpgraph_old] == 0) { $xx = array($name, hour_format($planned,2), $task->s_start->getDate(), $task->s_end->getDate()); } else { $xx = $name; } if ( $comp > 100.0 ) { $over = true; } if ($task->milestone == 1) { $bar = new MileStone($n, $xx, $end,sprintf("[%.0f %%]", $comp), 0.5); } else { $bar = new GanttBar($n, $xx, $start, $end,sprintf("[%.0f %%]", $comp), 0.5); if ( $over ) { $bar->progress->Set(1); $bar->SetColor("red"); $bar->SetPattern(BAND_RDIAG, "red"); $bar->progress->SetPattern(BAND_RDIAG, "red"); } } if ($tutos[jpgraph_old] == 0) { $bar->SetCSIMTarget(addSessionKey($task->getUrl()),myentities($task->getFullName())); } /* Outline first level tasks */ $bar->title->SetFont($font, FS_NORMAL, 8); if( $depth == 1 ) { $bar->title->SetFont($font, FS_BOLD, 8); } return $bar; } /* Recursive adding of project tasks */ function gantt_addTasks(&$parent, &$graph, &$count, $depth) { if ( $parent->getType() == "task" ) { $graph->Add(gantt_get_bar($parent, $count++, $depth)); } $parent->readTasks(); foreach($parent->tasklist as $i => $f) { $graph = gantt_addTasks($f, $graph, $count, $depth+1); } return $graph; } Function gantt_draw(&$parent) { global $lang , $font, $tutos; # # If we use a non western laguage encoding force the use of truetype fonts # if ($lang['content_encoding'] != "iso-8859-1") { $font = FF_ARIAL; } else { $font = FF_FONT1; } task_calc($parent); // Standard calls to create a new graph $graph = new GanttGraph(); //$graph->SetShadow(); $graph->SetBox(); // Titles for chart $graph->title->Set($lang['TaskGantt']." ". $lang['forphrase'] ." " . html_entity_decode($parent->getFullName()) ); $graph->title->SetFont($font,FS_BOLD,12); // For illustration we enable all headers. $graph->ShowHeaders(GANTT_HMONTH | GANTT_HDAY | GANTT_HWEEK); $graph->scale->week->SetStyle(WEEKSTYLE_FIRSTDAY); $graph->scale->month->SetStyle(MONTHSTYLE_LONGNAMEYEAR4); if (isset($graph->scale->actinfo)) { $graph->scale->actinfo->SetColTitles(array($lang['Task'] ." [". $lang['TaskWorker'] ."]",$lang['TaskVolumeFull'],$lang['TaskS_Start'],$lang['TaskS_End'])); } /* TODO: we could use locale */ // $graph->scale->SetDateLocale("fr_FR"); // Change the scale font $graph->scale->week->SetFont(FF_FONT0); $graph->scale->year->SetFont(FF_ARIAL,FS_BOLD,12); $count = 0; $graph = gantt_addTasks($parent, $graph, $count, 0); // Add a vertical line for the current day # $vline = new GanttVLine(strftime("%Y-%m-%d", time())); # $vline->SetDayOffset(0.5); # $graph->Add($vline); if ($tutos[jpgraph_old] == 0) { $graph->StrokeCSIM('gantt_png.php'); } else { $graph->Stroke(); } } /* --------------------------------------------------------------------------- * get the latest and earliest datetimes */ function task_calc (&$obj) { task::obj_read($obj); if ( ($obj->getType() == "address")||($obj->getType() == "team") ) { $recursive = false; } else { $recursive = true; } $obj->max_end = new DateTime(0); $obj->min_start = new DateTime(0); $obj->sum['volume'] = 0.0; $obj->sum['volume_done'] = 0.0; if ( $obj->getType() == "task") { $obj->max_end->setDateTimeTS($obj->s_end->ts); $obj->min_start->setDateTimeTS($obj->s_start->ts); $obj->sum['volume'] = $obj->volume; $obj->sum['volume_done'] = $obj->volume_done; } if ( count($obj->tasklist) > 0 ) { foreach ($obj->tasklist as $i => $f) { if ( $recursive ) { task_calc($f); $min = $f->min_start->ts; $max = $f->max_end->ts; } else { $min = $f->s_start->ts; $max = $f->s_end->ts; $f->sum['volume'] = $f->volume; $f->sum['volume_done'] = $f->volume_done; } // For address, we have to only count the work done by $obj... if( $obj->getType() == "address" ) { if( $obj->creator->id == $obj->id || array_key_exists((int)$obj->id, $f->worker) ) { $obj->sum['volume'] += $f->sum['volume']; $obj->sum['volume_done'] += computeWorkedHours($obj, $f); } } else { $obj->sum['volume'] += $f->sum['volume']; $obj->sum['volume_done'] += $f->sum['volume_done']; } if ( ($min != -1) ) { if ( ($obj->min_start->ts != -1) ) { $obj->min_start->setDateTimeTS(min($min,$obj->min_start->ts)); } else { $obj->min_start->setDateTimeTS($min); } } if ( ($max != -1) ) { if ( ($obj->max_end->ts != -1) ) { $obj->max_end->setDateTimeTS(max($max,$obj->max_end->ts)); } else { $obj->max_end->setDateTimeTS($max); } } } } } function tasks_clone_recursive( $tasklist, $newpid, $owner, $diff ) { global $tutos; foreach ($tasklist as $t) { $oldid = $t->id; $oldacl = $t->acl; $t->readTasks(); $t->id = -1; $t->p_id = $newpid; # add time diff to make dates relative to project's beginning $t->s_start->addDays($diff); $t->s_end->addDays($diff); # real dates are not welcome $t->r_start->setNoTime(); $t->r_end->setNoTime(); $t->save(); # set previous permissions and raise for current user $t->acl = $oldacl; acl_save($t); $t->modified = array (); $t->modified[] = array ( "field" => "CloneEntry" , "old" => $oldid , "new" => $t->id, "obj_id" => $nf->id ); history_save($t); if (function_exists('files_clone')) { files_clone( $t->dbconn, $oldid, $t->id, $owner ); } tasks_clone_recursive( $t->tasklist, $t->id, $owner, $diff ); } } /** * a task (something ToDo) * * @modulegroup task * @module task * @package task */ class task extends tutos_base { /* --------------------------------------------------------------------------- */ function task(&$dbconn) { global $current_user,$table; $this->init($dbconn); $this->p_id = -1; $this->parent = -1; $this->plist = array(); $this->name = ""; $this->desc = ""; $this->volume = 0; $this->volume_done = 0; $this->volume_todo = -1; $this->worker = array(); $this->s_start = new DateTime(); $this->s_end = new DateTime(); $this->r_start = new DateTime(0); $this->r_end = new DateTime(0); $this->state = TASK_PRE; $this->diff = 0; $this->milestone = 0; $this->email = 0; $this->tablename = $this->dbconn->prefix .$table['task'][name]; $this->tablename2 = $this->dbconn->prefix .$table['taskworker'][name]; } function exportXML_body ($only_ids = false) { global $lang; $r = parent::exportXML_body(); if (!$only_ids) { $r .= "". utf8_encode(htmlspecialchars($this->name)) ."\n"; $r .= "". utf8_encode(htmlspecialchars($this->desc)) ."\n"; $r .= "". $this->p_id ."\n"; $r .= "". $this->volume ."\n"; $r .= "". $this->volume_done ."\n"; $r .= "". $this->volume_todo ."\n"; $r .= "". $this->state ."\n"; $r .= "". utf8_encode(htmlspecialchars($lang['TaskStates'][$this->state])) ."\n"; $r .= "". $this->milestone ."\n"; $r .= "". $this->email ."\n"; if ( $this->s_start->notime != 1 ) { $r .= "". $this->s_start->exportXML_body() ."\n"; } else { $r .= ""; } if ( $this->s_end->notime != 1 ) { $r .= "". $this->s_end->exportXML_body() ."\n"; } else { $r .= ""; } if ( $this->r_start->notime != 1 ) { $r .= "". $this->r_start->exportXML_body() ."\n"; } else { $r .= ""; } if ( $this->r_end->notime != 1 ) { $r .= "". $this->r_end->exportXML_body() ."\n"; } else { $r .= ""; } foreach ( $this->worker as $i => $f) { $r .= ""; $r .= "". $f->id .""; $r .= "". utf8_encode(htmlspecialchars($f->GetFullname())) .""; $r .= "". utf8_encode(htmlspecialchars($f->GetType())) .""; $r.= ""; } } return $r; } /** * read a resultset */ function read_result (&$r, $pos ) { global $current_user, $tutos; $this->p_id = $r->get($pos, "p_id"); $this->parent = getObject($this->dbconn,$this->p_id); $this->state = $r->get($pos, "status"); $this->volume = $r->get($pos, "volume"); $this->volume_done = $r->get($pos, "volume_done"); $this->volume_todo = $r->get($pos, "volume_todo"); $this->name = $r->get($pos, "name"); $this->desc = $r->get($pos, "description"); $this->milestone = $r->get($pos, "milestone"); $this->r_start = $r->getDateTime($pos, "r_start"); $this->r_end = $r->getDateTime($pos, "r_end"); $this->s_start = $r->getDateTime($pos, "s_start"); $this->s_end = $r->getDateTime($pos, "s_end"); parent::read_result($r,$pos); $wid = $r->get($pos, "worker"); $w = GetObject($this->dbconn,$wid); if ( $w != -1 ) { $this->worker[$wid] = &$w; } $this->readWorker(); $cid = $r->get($pos, "creator"); $this->creator = getObject($this->dbconn,$cid); if ( $this->parent == -1 ) { # Project not found $this->parent = $this->worker[$wid]; } if ( $this->parent == -1 ) { # Project and worker not found $this->parent = $this->creator; } if ( $this->parent == -1 ) { # Project, worker and creator not found $this->parent = $current_user; } $this->p_id = $this->parent->id; if ( ($this->volume == "") ) { $this->volume = 0; } if ( ($this->volume_done == "") ) { $this->volume_done = 0; } if ( ($this->volume_todo == "") ) { $this->volume_todo = -1; } # If timetrack is used then the volume_done is read as the sum of all connected tt entries if ( ($tutos[usetimetrack] == 1) ) { $this->readTimetrackSum(); $this->volume_done = $this->timetracksum; if ( ($this->volume_done == "") ) { $this->volume_done = 0; } } # Tasks with used volume are not longer in prestate if ( ($this->volume_done > 0) && ($this->state == TASK_PRE) ) { $this->state = TASK_RUNNING; } return; } /** * get a list of possible new parents */ function read_relations ( ) { global $lang; $this->plist = array(); if ($this->parent != -1) { # Read possible new parents $this->plist = $this->parent->getNeighbours(); } # !!! FIX ME Remove own subtasks from list unset ($this->plist[$this->id]); task::obj_read($this); foreach ($this->fulltasklist as $a => $b) { unset ($this->plist[$a]); } } /** * fill the internal neighbour list with possible objects where a object * currently attached/referncing to THIS task could be reattached */ function getNeighbours () { global $lang; if (count ($this->neighbours) > 0 ) return $this->neighbours; parent::getNeighbours(); # Possible new parents are all parent tasks $x = $this; while ($x->getType() == "task") { if ($x->see_ok() ) { $this->neighbours[$x->id] = $x; } $x = $x->parent; } if ($x->getType() == "product") { $n = $x->getNeighbours() ; foreach($n as $i) { $this->neighbours[$i->id] = &$i; unset($i); } } return $this->neighbours; } /** * read worker */ function readWorker() { if ( empty($this->id) ) return; if ( -1 == $this->id ) return; $query = "SELECT w_id FROM ". $this->tablename2 ." WHERE t_id = ". $this->id; $result = $this->dbconn->Exec($query); $n = $result->numrows(); $a = 0; while ($a < $n) { $xx = $result->get($a, "w_id"); $p = getObject($this->dbconn,$xx); $this->worker[$xx] = &$p; $a++; unset($p); } $result->free(); } /** * save worker */ function saveWorker() { $q = "DELETE FROM ". $this->tablename2 ." WHERE t_id = ". $this->id; $this->dbconn->Exec($q); foreach ($this->worker as $i => $f) { $q = "INSERT INTO ". $this->tablename2 ." (t_id,w_id) VALUES (". $this->id .",". $i .")"; $this->dbconn->Exec($q); } } /** * search for a task * fill a array with possible tasks */ function search_by_name(&$arr,&$user,$name) { if ( trim($name) == "" ) return; $q = "SELECT * from ". $user->dbconn->prefix ."tasks WHERE". $user->dbconn->Like("name",$name); $q .= " order name "; check_dbacl( $q, $user->id); $r = $user->dbconn->Exec($q); $n = $r->numrows(); $a = 0; while ( $a < $n ) { $x = new task($user->dbconn); $x->read_result($r,$a); $arr[$x->id] = &$x; # echo $x->getFullName() ."
"; unset($x); $a++; } $r->free(); return; } /** * set the Name */ function setName($value) { return $this->setStrField("name",$value,"TaskName"); } /** * set the Description */ function setDescription($value) { return $this->setStrField("desc",$value,"TaskDesc"); } /** * set the State */ function setState($value) { return $this->setIntField("state",$value,"TaskState"); } /** * set the Mielstone flag */ function setMilestone($value) { return $this->setIntField("milestone",$value,"TaskMilestone"); } /** * set the Start */ function setRStart($value) { return $this->setDateField("r_start",$value,"TaskR_Start"); } /** * set the End */ function setREnd($value) { return $this->setDateField("r_end",$value,"TaskR_End"); } /** * set the scheduled Start */ function setSStart($value) { return $this->setDateField("s_start",$value,"TaskS_Start"); } /** * set the scheduled end */ function setSEnd($value) { return $this->setDateField("s_end",$value,"TaskS_End"); } /** * set the Volume */ function setVolume($value) { return $this->setFloatField("volume",$value,"TaskVolumeFull"); } /** * set the VolumeDone */ function setVolumeDone($value) { # Book the time to the task and users # timetrack $this->diff = $value - $this->volume_done; return $this->setFloatField("volume_done",$value,"TaskVolumeDone"); } /** * set the Volume Todo */ function setVolumeTodo($value) { return $this->setFloatField("volume_todo",$value,"TaskVolumeTodo"); } /** * set the parent */ function setParent($pid) { if ( $this->p_id != $pid ) { $this->modified[] = array ( "field" => "TaskSubTask" , "old" => $this->p_id , "new" => $pid); $this->p_id = $pid; } return; } /** * Replaces the strings in the mail body */ function make_mail_body(&$body,&$to) { global $lang; $url = getBaseURL(true). $this->getURL(); $body = eregi_replace("@CREATOR@",$this->creator->getFullName(),$body); $body = eregi_replace("@SHORT@",$this->name,$body); $body = eregi_replace("@DESC@",$this->desc,$body); $body = eregi_replace("@STATE@",$to->lg['TaskStates'][$this->state],$body); $body = eregi_replace("@VOLUME@",$this->volume,$body); $worker = ""; if (count($this->worker) > 1) { foreach ($this->worker as $i => $f) { $worker .= $f->GetFullname()."\n"; } $body = eregi_replace("@WORKERS@",$worker,$body); $body = eregi_replace("","",$body); $body = eregi_replace("","",$body); } else { $body = eregi_replace(".*","",$body); } $body = eregi_replace("@URL@",$url,$body); if ( $to->gettype() == "team" ) { $body = eregi_replace("@TO@",$lang[$to->gettype()] ." ".$to->getFullName(),$body); $body = eregi_replace("","",$body); $body = eregi_replace("","",$body); } else { $body = eregi_replace("@TO@",$to->getFullName(),$body); # Remove the TEAM part $body = eregi_replace(".*","",$body); } $body = eregi_replace("@START@",$this->s_start->getDateTime(),$body); $body = eregi_replace("@END@",$this->s_end->getDateTime(),$body); } /** * Save Task to DB */ function save() { global $tutos,$table,$current_user; $msg = ""; $q = new query($this->dbconn); $q->setTable($this->tablename); @reset($this->worker); $q->addFV("worker",current($this->worker),"OBJ"); $q->addFV("p_id",$this->p_id,"INT"); $q->addFV("status",$this->state,"INT"); $q->addFV("milestone",$this->milestone,"INT"); $q->addFV("volume",$this->volume,"FLOAT"); $q->addFV("volume_todo",$this->volume_todo,"FLOAT"); $q->addFV("name",$this->name,"STRING",$table['task']['name'][size]); $q->addFV("description",$this->desc,"TEXT"); $q->addFV("r_start",$this->r_start,"DATETIME"); $q->addFV("r_end",$this->r_end,"DATETIME"); $q->addFV("s_start",$this->s_start,"DATETIME"); $q->addFV("s_end",$this->s_end,"DATETIME"); $this->save_custom_fields($q); if ( $this->id < 0 ) { $task_is_new = true; $this->modified = array(); if ( isset($this->newid) ) { $this->id = $this->newid; $q->addFV("id",$this->id,""); } else { $this->id = $q->addFV("id",-1,"NEXTID"); # Defaut Access Control (get parents acl as default) $this->acl = $this->parent->acl; $this->modified[] = array ( "field" => "created" , "old" => $this->getType() , "new" => $this->id, "obj_id" => $this->id ); # to not trigger watchlist if parent is a address $this->modified[] = array ( "field" => "TaskCreate" , "old" => "-1" , "new" => $this->id, "obj_id" => $this->parent->id ); } $q->addFV("creator",$this->creator,"OBJ"); $q->addFV("creation",$this->creation,"DATETIME"); $query = $q->getInsert(); } else { $task_is_new = false; $q->addWC("id",$this->id,""); $query = $q->getUpdate(); } foreach ($this->worker as $i => $f) { acl_raise($this,$f->id,$tutos[modok]); // fix the fact that user that changes task are in solvers list if ($f->getType() == "address" && $f->id == $current_user->id) { $cw = $f; } } acl_raise($this,$this->creator->id,$tutos[delok]); $this->dbconn->Exec($query); $this->saveWorker(); $msg .= parent::save(); # If the volume_done has been changed, we add a timetrack entry if ( ($this->diff != 0) ) { $tt = new timetrack($this->dbconn); if( isset($cw) ) { // A worker has made the change $tt->worker = $cw; } else { // The task creator or a mod_ok tutos user made the change... $tt->worker = $current_user; } $tt->link_id = $this->id; $tt->ref = $this; $tt->volume = $this->diff; $tt->volume_todo = $this->volume_todo; $tt->desc = $this->name; $msg .= $tt->save($norec=1); } # Mail stuff if ( $this->email == 1 ) { $m = new mail($current_user); $m->setFrom($this->creator); foreach ($this->worker as $i => $f) { $m->addTo($f); $body = ""; if ( $task_is_new ) { if ( ! findMailTemplate("task_new.proto",$f,$body) ) { $msg .= sprintf($lang['Err0037'],$m->subject,$body) ."
\n"; continue; } $m->setSubject(sprintf($f->lg['EmailNewTask'],$this->getFullName(),sprintf($f->lg['TaskStates'][$this->state]))); $m->addHeader("X-PRIORITY","1"); $m->addHeader("priority","urgent"); } else { if ( ! findMailTemplate("task_mod.proto",$f,$body) ) { $msg .= sprintf($lang['Err0037'],$m->subject,$body) ."
\n"; continue; } $m->setSubject(sprintf($f->lg['EmailChangesTask'],$this->getFullName(),sprintf($f->lg['TaskStates'][$this->state]))); } $this->make_mail_body($body,$f); $m->addBody($body,"text/plain",$f->lg['TaskDetail'],"",$f->lg['content_encoding']); $msg .= $m->send(); $m->resetBody(); $m->resetTo(); } } return $msg; } /** * Delete tasks from DB */ function delete() { global $current_user; $msg = ""; $q = "UPDATE ". $this->tablename ." SET p_id = ". $this->p_id ." WHERE p_id = ". $this->id; $this->dbconn->Exec($q); $q = "DELETE FROM ". $this->tablename2 ." WHERE t_id = ". $this->id; $this->dbconn->Exec($q); $q = "DELETE FROM ". $this->tablename ." WHERE id = ". $this->id; $this->dbconn->Exec($q); $msg .= timetrack::obj_delete($current_user,$this); $msg .= parent::delete(); return $msg; } /** * Popup for overlib */ function getPopInfo() { global $lang; $n =str_replace("\n","
",myentities(wordwrap($this->desc,80))); $n =str_replace("\r","",$n); $n =str_replace("'","\'",$n); $t =myentities($this->name); $t =str_replace("'","\'",$t); $info = ""; $info .= ""; $info .= ""; $info .= ""; $x = $this->parent; if( $x == -1 ) unset($x); $pre = ""; $name = ""; while ( isset ( $x ) ) { $name = myentities($x->getFullName()) . $pre . $name; if (isset($x->parent) && $x->parent != -1) { $x = $x->parent; } else { unset($x); } $pre = " → "; } $name .= $pre . " " . $t; $info .= ""; if ( ($this->s_start->notime != 1) || ($this->s_end->notime != 1) ) { $info .= ""; } if ( $this->volume != 0 ) { $info .= ""; } $info .= ""; $info .= "
". $name ."
"; $info .= $this->s_start->getDate() ." - ". $this->s_end->getDate(); $info .= "
"; $info .= hour_format($this->volume) ." / ". hour_format($this->volume_done) ." ". $lang['hours'] . sprintf(" (%3.2f %%)", $this->getcompletion()); $info .= "
";
    $info .= $n;
    $info .= "
"; return $info; } /** * Return a link to this task */ function getURL() { return "task_show.php?id=".$this->id; } /** * Return a link to modify this task */ function getModURL() { return "task_new.php?id=".$this->id; } /** * Return a link to delete this task */ function getDelURL() { return "task_del.php?id=".$this->id; } /** * Return a link to this task */ function getLink($text = "") { global $lang; if ( $text == "" ) { $text = $this->getFullName(); } if ( $this->see_ok() ) { return makelink($this->getURL() , myentities($text) ,sprintf($lang['TaskLinkInfo'], $this->getFullName()),$this->getPopInfo()); } else { return myentities($text); } } /** * Return a fullname i.e name */ function getFullname() { global $lang; if ($this->milestone == 1) { return $lang['TaskMilestone']." ".$this->name; } return $this->name; } /** * get the info as text */ function getAsText (&$lang) { $r = ""; $r .= format_asText($lang['TaskName'],$this->name); $r .= format_asText($lang['TaskState'],$lang['TaskStates'][$this->state]); $r .= format_asText($lang['TaskDesc'],$this->desc); $r .= format_asText($lang['TaskSched']." / ". $lang['DateTimeFrom'],$this->s_start->getDate()); $r .= format_asText($lang['TaskSched']." / ". $lang['DateTimeTill'],$this->s_end->getDate()); return $r; } /** * get the timespan */ function getTimespan () { $r = array(); $r['start'] = $this->s_start->getYYYYMMDD() ."0000"; $r['end'] = $this->s_end->getYYYYMMDD() ."2359"; $r['desc'] = $this->s_start->getDate() ." - " . $this->s_end->getDate() ; return $r; } /** * Return Info about bugs in this task */ function bugSum() { return bugSummary($this); } /** * Add in the given array entries $task_id => $project_id * Returns the project */ function getProject(&$projects_tasks) { $project = -1; $obj = $this; $ptasks = array(); // Walk through parents to find project while( $project == -1 ) { if( array_key_exists($obj->p_id, $projects_tasks) ) { $ptasks[] = $obj->id; $project = getObject($this->dbconn, $projects_tasks[$obj->p_id]); } else { $t = getObject($this->dbconn, $obj->p_id); if( $t == -1 ) { // Parent no longer exists ? break; } $ptasks[] = $obj->id; if( $t->getType() != "task" ) { // found first node $project = &$t; } else { $obj = getObject($this->dbconn, $obj->p_id); } unset($t); } } foreach( $ptasks as $pid ) { $projects_tasks[$pid] = $project->id; } return $project; } /** * get the type of object */ function printRow (&$layout,$depth, &$parent, $fld = "", $slimit=0, $elimit=0) { global $lang, $tutos, $projects_tasks,$table; if( !isset($projects_tasks) ) $projects_tasks = array(); // I sometimes get -1 as $this->id if( $this->id == -1 ) return; if ( ($parent->getType() == "address")||($parent->getType() == "team")||($parent->getType() == "base") ) { $recursive = false; # print only unfinished tasks if ( $this->state == TASK_FINISH ) { return 1; } } else { $recursive = true; } /* we limit the date range of printed tasks */ if( $slimit == 0 && $elimit == 0 || ($slimit != 0 && $elimit != 0 && $slimit->datecmp($this->s_start) <= 0 && ($elimit->datecmp($slimit) == 0 || $elimit->datecmp($this->s_end) >= 0) )) { $c = $this->getcompletion(); echo $layout->OverviewRowStart($layout->line); switch( $parent->getType() ) { case "address": { /* We show the project name and the task name * As we already know the person name, we should not have the need * to display it (see Person Task Overview) * * That can take some times to complete... even with the * $projects_tasks static var, keeping projects associations in * memory, in order not to make too much data base access... */ $project = $this->getProject($projects_tasks); if( $this->getLink() != "" ) { echo " state . "\" valign=\"top\" colspan=\"2\" nowrap=\"nowrap\"> ". ($project != -1 ? $project->getLink() : "DTC") ."  → ". $this->getLink()." \n"; } break; } case "team": { echo " state ."\" valign=\"top\" colspan=\"2\" nowrap=\"nowrap\"> ". $parent->getLink() ." &8594; ". $this->getLink()." \n"; break; } default: { echo " state ."\" align=\"right\" valign=\"top\"> ". $depth ." \n"; echo "

 "; for ($i = 0; $i <= $depth; $i++) { echo "  "; } echo $this->getLink()." "; switch( $fld ) { case "worker": echo "

".$lang['TaskWorker']; $w = 0; foreach ($this->worker as $i => $x) { echo ($w %2 ? "
":" ").($w >0 ? ",":""). $this->worker[$i]->getLink(); $w++; } break; case "product": $project = $this->getProject($projects_tasks); echo "

".$lang['Product']." ".$project->getLink(); break; default: break; } echo "\n"; } } // end of switch $parent->getType() // I have some strange bug where I reach non existing entities. if( $this->getLink() == "" ) return 0; // When displaying an address time overview, we have to compute // the volume done by the $parent address ! if( $parent->getType() == "address" ) { $volume = $this->volume; $volume_done = computeWorkedHours($parent, $this); } else { $volume = $this->volume; $volume_done = $this->volume_done; } echo " " .sprintf("%3.2f %%",$c ) ." 
 " .hour_format($volume_done,2) ." / ". hour_format($volume,2) ." ". $lang['hours'] ." \n"; echo " " .$this->s_start->getDate() ." \n"; $w = 200; $h = 32; // height // seconds per pixel $t = time(); $max_end = max($parent->max_end->ts,$t); $min_start = min($parent->min_start->ts,$t); $p = ( ($max_end - $min_start) / $w); if ( $p == 0 ) { # $p = 1; } // from earliest to start $x1 = round(($this->s_start->ts - $min_start)/$p); $x1a = round( ($t - $min_start)/$p); $x1b = round(( $this->s_start->ts - $t )/$p); $x2 = round(($this->s_end->ts - $this->s_start->ts)/$p); $x3 = round(($max_end - $this->s_end->ts)/$p); $x3a = round(( $t - $this->s_end->ts)/$p); $x3b = round( ($max_end - $t )/$p); echo " "; if ( $x1a + $x1b > 0 ) { if ( $x1b < 0 ) { echo "\"\""; } else { if ( $x1a > 0 ) { echo "\"\""; } } if ( $x1b > 0 ) { echo "\"\""; } } if ( $x2 == 0 ) { $x2=1; } $x2a = Round($x2 * $c/100.0); $x2b = Round($x2 * (100 - $c)/100.0); if ( $x2a != 0 ) { echo "\"".getFullName()) ."\">"; } if ( $x2b > 0 ) { echo "\"".getFullName()) ."\">"; } if ( $x3a + $x3b > 0 ) { if ( $x3a > 0 ) { echo "\"\""; if ( $x3b > 0 ) { echo "\"\""; } } else { if ( ($x3b + $x3a) > 0 ) { echo "\"\""; } } } echo "\n"; echo "  ". $this->s_end->getDate() ." \n"; echo "  "; echo makelink("task_new.php?pid=".$this->id,$lang['NewEntry'],sprintf($lang['TaskCreateInfo'],$this->name)); echo " \n"; echo "  "; if ( $tutos[massupdate] == 1 ) { # Checkbox column for massupdate if ( $this->mod_ok() ) { echo "id ."\">"; } else { echo "-"; } } else { if ( $this->del_ok() ) { echo confirmlink("task_del.php?id=".$this->id,$lang['Delete'],sprintf($lang['TaskDelete'],$this->name)); } else { echo $lang['Delete']; } } echo " \n"; echo $layout->OverviewRowEnd($layout->line++); } if ( $recursive ) { task::obj_read($this); foreach($this->tasklist as $i => $f) { $f->printRow($layout,$depth +1,$parent, $fld, $slimit, $elimit); } } return 0; } /** * get the percentage of completion */ function getcompletion () { if( $this->state == TASK_FINISH ) return 100.0; if ( $this->volume <= 0 ) { return 0.0; } if( $this->volume_todo > -1 ) { if ( ($this->volume_todo + $this->volume_done) == 0 ) { return 0.0; } return (100.0*($this->volume_done/ ($this->volume_todo + $this->volume_done))); } return ( 100.0 * ( $this->volume_done / $this->volume )); } /** * output the formatted task in one table row */ function formatted () { global $lang,$tutos,$current_user; $class = "task". $this->state; echo " \n"; echo " ". $this->getLink() ."\n"; echo " \n"; echo " \n"; if ( $this->parent->getType() == "address" ) { if ( $this->parent->id == $current_user->id ) { echo " ".$lang['TaskStates'][$this->state] ."\n"; } else { echo " ".$lang['TaskStates'][$this->state]." (". $this->parent->getLink() .")\n"; } } else { echo " ".$lang['TaskStates'][$this->state]." → ". $this->parent->getLink() ."\n"; } echo " \n"; return; } /** * checks if the task is planned that day * Date d true if taks work should happen that day */ function inside (&$d) { $d->setDateTime($d->getYYYYMMDD() . "000000"); $x = $d->getYYYYMMDD(); if ( $x < $this->s_start->getYYYYMMDD() ) return false; if ( $x > $this->s_end->getYYYYMMDD() ) return false; return true; } /** * Transfer reference ids according to given table */ function transfer_ids (&$trans) { parent::transfer_ids ($trans); if (isset($trans[$this->p_id])) { $this->p_id = $trans[$this->p_id]; } foreach ($this->worker as $i => $f) { if (isset($trans[$i])) { $this->worker[$trans[$i]] = $this->worker[$i] ; $this->worker[$trans[$i]]->id = $trans[$i] ; unset($this->worker[$i]); } } if (isset($trans[$this->creator->id])) { $this->creator->id = $trans[$this->creator->id]; } return; } /** * get the type of object */ function getType () { return "task"; } /** * get the type id of object */ function gettypeid () { return usetaskmanagement; } /** * get name of icons */ function getHtmlIcon () { return 'task'; } /* --------------------------------------------------------------------------- * The following methods are abstract factory functions for groups * which handle the membership list of an object * --------------------------------------------------------------------------- */ /** * create a link to a overview page */ function getOverviewLink (&$user,$text = "") { global $lang,$tutos; if ( ! $user->feature_ok(usetaskmanagement,PERM_NEW) ) { return; } } /** * create a link where a note to for the given object could be added */ function getaddlink (&$user,&$obj,$text = "") { global $lang; if ( $obj == -1 ) return ""; if (! is_object($obj) ) return ""; if (! $user->feature_ok(usetaskmanagement,PERM_NEW) ) return ""; if (! $obj->mod_ok() ) return ""; $x = array( url => "task_new.php?pid=". $obj->id, confirm => false, text => ($text == "" ? $lang['TaskCreate']:$text), info => sprintf($lang['TaskCreateInfo'], $obj->getFullName()) ); if ( $obj->gettype() == "task" ) { $x[category] = array("task","new","obj"); } else { $x[category] = array("task","new","module"); } return $x; } /** * Return Info about connected tasks for given object */ function obj_read(&$obj) { global $table; if ( $obj == -1 ) return; if (! is_object($obj) ) return; if ( isset($obj->tasklist) ) return; $obj->tasklist = array(); $obj->fulltasklist = array(); $obj->tsum['Tasks'] = 0; $readall = false; if ( ($obj->getType() == "address") || ($obj->getType() == "user") ) { $q = "SELECT distinct t_id from ". $obj->dbconn->prefix .$table['taskworker'][name] ." WHERE "; # Select the workers and all his teams tasks team::obj_read($obj); $q .= " w_id in ( ". $obj->id; foreach ( $obj->teamlist as $i => $f) { $q .= ",". $i; } $q .= ")"; $readall = true; } else if ( $obj->getType() == "team" ) { $q = "SELECT distinct t_id from ". $obj->dbconn->prefix .$table['taskworker'][name] ." WHERE "; $q .= "w_id = ". $obj->id; $readall = true; } else { $q = "SELECT * from ". $obj->dbconn->prefix .$table['task'][name]." WHERE "; $q .= "p_id = ". $obj->id; $q .= " ORDER by s_start"; } $r = $obj->dbconn->Exec($q); $n = $r->numrows(); $a = 0; while ($a < $n) { $t = new task($obj->dbconn); if ( $readall ) { $id =$r->get($a,"t_id"); $t = $t->read($id,$t); } else { $t->read_result($r,$a); } task::obj_read($t); if ( class_exists('bug') ) { bug::obj_read($t); } else { $t->tsum['Bugs'] = 0; } $t->readTimetrackSum(); $obj->tsum['Tasks'] += $t->timetracksum; # Add Subtask-Sum $obj->tsum['Tasks'] += $t->tsum['Tasks']; $obj->tsum['Tasks'] += $t->tsum['Bugs']; $obj->tasklist[$t->id] = &$t; $obj->fulltasklist[$t->id] = &$t; foreach ($t->fulltasklist as $i => $f) { $obj->fulltasklist[$i] = &$f; unset($f); } $a++; unset($t); } $r->free(); return; } /** * a object that may hold tasks is deleted */ Function obj_delete(&$user,&$obj) { global $table; $msg = ""; $q = "DELETE FROM ". $obj->dbconn->prefix .$table['taskworker'][name] ." WHERE w_id = ". $obj->id; $obj->dbconn->Exec($q); if ( $obj->getType() != "address" ) { task::obj_read($obj); if ( count($obj->tasklist) > 0 ) { foreach ($obj->tasklist as $i => $f) { $msg .= $f->delete(); } } } return $msg; } /** * Read a list of tasks for a timerange and make it a array in the * given object (compare readAppsCal in appointment.pinc) * start is a TUTOS DateTime object */ function readCal(&$obj, &$from, &$to) { global $current_user,$table; //if ( ! $current_user->feature_ok(usetaskmanagement,PERM_SEE) ) { // return; //} $from->setDateTime($from->getYYYYMMDD() . "000000"); $to->setDateTime($to->getYYYYMMDD() . "000000"); $x1 = $obj->dbconn->DateTime($from); $x2 = $obj->dbconn->DateTime($to); echo $x1; # # # $q = "SELECT c.* FROM ". $obj->dbconn->prefix ."tasks c "; $pre = " WHERE"; if ( ($obj->getType() == "address") || ($obj->getType() == "user") ) { # Select the workers and all his teams tasks $q .= $pre. "( c.worker in ( ". $obj->id; foreach ($obj->teamlist as $i => $f) { $q .= ",". $i; } $q .= ")"; # $qq = "SELECT DISTINCT t_id FROM ". $obj->dbconn->prefix .$table['taskworker'][name]. " WHERE w_id in (".$obj->id; foreach ($obj->teamlist as $i => $f) { $qq .= "," . $i; } $qq .= ")"; $r = $obj->dbconn->Exec($qq); $n = $r->numrows(); $a = 0; if ( $n > 0 ) { $q .= " OR ( c.id in ("; $xpre = ""; while ( $a < $n ) { $x = $r->get($a,"t_id"); $q .= $xpre . $x; $xpre = ","; $a++; } $r->free(); $q .= ") )"; } # $q .= ")"; $pre = " AND"; } $q .= $pre. "("; $q .= " ( c.s_start < ". $x2 ." and c.s_start >= ". $x1 .")"; $q .= "or ( c.s_end < ". $x2 ." and c.s_end >= ". $x1 .")"; $q .= "or ( c.s_start < ". $x1 ." and c.s_end >= ". $x1 .")"; $q .= ")"; $q .= " ORDER by c.s_start"; $r = $obj->dbconn->Exec($q); $n = $r->numrows(); $a = 0; while ( $a < $n ) { $o = new task($obj->dbconn); $o->read_result($r,$a); $a++; if ( $o->see_ok() ) { $obj->callist[$o->id] = &$o; } unset($o); } $r->free(); } /** * get the help index */ function getHelpIndex () { global $lang; $r = ""; $r .= "

". makelink("help.php?p=glossary#tasks",$lang['Tasks'],$lang['Tasks']) ."

    \n"; $r .= "
  • ". makelink("help.php?p=task_new",$lang["NewEntry"]."/". $lang["Modify"],$lang["NewEntry"]."/". $lang["Modify"]) ."
  • \n"; $r .= "
  • ". makelink("help.php?p=task_show",$lang["show"],$lang["show"]) ."
  • \n"; $r .= "
  • ". makelink("help.php?p=res_cal",$lang['ResCal'],$lang['ResCal'])."
  • \n"; $r .= "
\n"; return $r; } } ?>