00001 <?php if(!function_exists('startedIndexPhp')) { header("location:../index.php"); exit();}
00002
00003
00011 global $g_cache_tasks;
00012 $g_cache_tasks=array();
00013
00014
00015
00016
00017
00018
00019 class Task extends DbProjectItem
00020 {
00021
00022 public $level; # level if child of parent-tasks
00023 public $num_subtasks; # temp cache for tree-lists
00024
00025
00029 public static function init()
00030 {
00031 #self::$type= ITEM_TASK;
00032 addProjectItemFields(&self::$fields_static);
00033
00034 foreach(array(
00035 new FieldInternal(array( 'name'=>'id',
00036 'default'=>0,
00037 'in_db_object'=>1,
00038 'in_db_item'=>1,
00039 'log_changes'=>false,
00040 )),
00041 new FieldString (array('name'=>'name',
00042 'title'=>__('Name'),
00043 'view_in_forms'=>true,
00044 'required'=>true,
00045 )),
00046 new FieldString (array('name'=>'short',
00047 'title' =>__('Short'),
00048 'view_in_forms' =>true,
00049 )),
00050 new FieldDate (array('name'=>'date_start',
00051 'title' =>__('Date start'),
00052 'view_in_forms' =>true,
00053 'default' =>FINIT_TODAY,
00054 'log_changes' => false,
00055 )),
00056 new FieldDate (array('name'=>'date_closed',
00057 'title' =>__('Date closed'),
00058 'view_in_forms' =>true,
00059 'default' =>FINIT_NEVER,
00060 'log_changes' => false,
00061 )),
00062 new FieldOption (array('name'=>'status',
00063 'title'=>__('Status'),
00064 'view_in_forms'=>true,
00065 'default'=>2,
00066 )),
00067
00068 new FieldInt (array('name'=>'prio',
00069 'title'=>__('Priority'),
00070 'view_in_forms'=>true,
00071 'default'=>3,
00072 )),
00073 new FieldInt (array('name'=>'for_milestone',
00074 'title'=>__('For Milestone'),
00075 'view_in_forms'=>true,
00076 'default'=>0,
00077 )),
00078 new FieldInt (array('name'=>'resolved_version',
00079 'title'=>__('resolved in version'),
00080 'view_in_forms'=>true,
00081 'default'=>0,
00082 )),
00083 new FieldInt (array('name'=>'resolve_reason',
00084 'title'=>__('Resolve reason'),
00085 'view_in_forms'=>true,
00086 'default'=> RESOLVED_UNDEFINED,
00087 )),
00088
00089 new FieldText (array('name'=>'description',
00090 'title'=>__('Description'),
00091 'view_in_forms'=>true,
00092 )),
00093
00097 new FieldBool( array('name'=>'is_folder',
00098 'title'=>__('show as folder (may contain other tasks)'),
00099 'view_in_forms'=>true,
00100 'default' =>0,
00101 )),
00102 new FieldBool( array('name'=>'is_milestone',
00103 'title'=>__('is a milestone'),
00104 'tooltip'=> __('milestones are shown in a different list'),
00105 'view_in_forms'=>false,
00106 'default' =>0,
00107 )),
00108
00109 new FieldInternal( array('name'=>'is_released',
00110 'title' =>__('released'),
00111 'view_in_forms' =>false,
00112 'default' =>RELEASED_UNDEFINED,
00113 'log_changes' => true,
00114 )),
00115 new FieldDatetime( array('name'=>'time_released',
00116 'title' =>__('release time'),
00117 'view_in_forms' =>true,
00118 'default' =>FINIT_NEVER
00119 )),
00120
00121 new FieldPercentage(array('name'=>'completion',
00122 'title'=>__('Completion'),
00123 'view_in_forms'=>true,
00124 'default' =>0,
00125 )),
00126 new FieldInternal( array('name'=>'parent_task',
00127 'view_in_forms'=>true,
00128 'log_changes' => true,
00129 )),
00134 new FieldInt( array('name'=>'estimated',
00135 'title'=>__('Estimated time'),
00136 'view_in_forms'=>true,
00137 )),
00138 new FieldInt( array('name'=>'estimated_max',
00139 'title'=>__('Estimated worst case'),
00140 'view_in_forms'=>true,
00141 )),
00142
00143 new FieldHidden( array('name'=>'issue_report',
00144 'log_changes'=>false,
00145 )),
00146 new FieldOption (array('name'=>'label',
00147 'title'=>__('Label'),
00148 'view_in_forms'=>true,
00149 'log_changes'=>true,
00150 )),
00151 new FieldDateTime (array('name'=>'planned_start',
00152 'title'=>__('Planned Start'),
00153 'view_in_forms'=>true,
00154 'default'=>FINIT_NEVER,
00155 )),
00156 new FieldDateTime (array('name'=>'planned_end',
00157 'title'=>__('Planned End'),
00158 'view_in_forms'=>true,
00159 'default'=>FINIT_NEVER,
00160 )),
00161 new FieldInternal (array('name'=>'view_collapsed',
00162 'default'=>0,
00163 'log_changes'=>false,
00164 )),
00165 new FieldInternal (array('name'=>'category',
00166 'default'=>TCATEGORY_TASK,
00167 'log_changes' => true,
00168 )),
00169
00173 new FieldInt (array('name'=>'order_id',
00174 'title'=>__('Order Id'),
00175 'default' => 0,
00176 'log_changes' => true,
00177 )),
00178
00179 ) as $f) {
00180 self::$fields_static[$f->name] = $f;
00181 }
00182 }
00183
00184
00185
00186 function __construct ($id_or_array=false)
00187 {
00188 $this->fields= &self::$fields_static;
00189
00190 parent::__construct($id_or_array);
00191 if(!$this->type){
00192 $this->type= ITEM_TASK;
00193 }
00194
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00233 static function getById($id)
00234 {
00235 if($id) {
00236 $t= new Task($id);
00237 if($t->type != ITEM_TASK) {
00238 return NULL;
00239 }
00240 if($t->id) {
00241 return $t;
00242 }
00243 }
00244 return NULL;
00245 }
00246
00247
00253 static function getVisibleById($id)
00254 {
00255 if($id && $t= Task::getById($id)) {
00256 if($p= Project::getById($t->project)) {
00257 if($p->validateViewItem($t)) {
00258 return $t;
00259 }
00260 }
00261 }
00262 return NULL;
00263 }
00264
00268 static function getEditableById($id)
00269 {
00270 if($t= Task::getById($id)) {
00271 if($p= Project::getById($t->project)) {
00272 if($p->validateEditItem($t, false)) {
00273 return $t;
00274 }
00275 }
00276 }
00277 return NULL;
00278 }
00279
00280
00281
00282 function getProject()
00283 {
00284 require_once(confGet('DIR_STREBER') . 'db/class_project.inc.php');
00285 if(!$project= Project::getById($this->project)) {
00286 trigger_error("Task:getProject. project-id not set",E_USER_WARNING);
00287 }
00288 return $project;
00289 }
00290
00291
00292
00293 function getProjectLink()
00294 {
00295 if($project= $this->getProject()) {
00296 return "<nobr>".$project->getLink().'</nobr>';
00297 }
00298 else {
00299 return '';
00300 }
00301 }
00302
00303
00304 function renderTypeAsBreadcrumbs()
00305 {
00306 global $g_status_names;
00307 $status= $this->status != STATUS_OPEN && isset($g_status_names[$this->status])
00308 ? $g_status_names[$this->status]
00309 : '';
00310
00311 $type=$this->getLabel();
00312
00313 if($folder= $this->getFolderLinks()) {
00314 $buffer= $folder ." > " . $type . ' (' . $status . ')';
00315 }
00316 else {
00317 $buffer= $status .' '. $type ;
00318 }
00319 return $buffer;
00320 }
00321
00322
00326 function getSubtasks($order_by=NULL)
00327 {
00328
00329 if(!$project = Project::getById($this->project)) {
00330 $PH->abortWarning(__("task without project?"), ERROR_BUG);
00331 }
00332
00333
00334 return $project->getTasks(array(
00335 'order_by' => $order_by,
00336 'sort_hierarchical'=>false,
00337 'parent_task'=> $this->id,
00338 'show_folders'=>true,
00339 'status_min'=> STATUS_UPCOMING,
00340 'status_max'=> STATUS_CLOSED,
00341 ));
00342 }
00343
00344 function getSubtasksRecursive()
00345 {
00346
00347 if(!$project = Project::getById($this->project)) {
00348 $PH->abortWarning(__("task without project?"), ERROR_BUG);
00349 }
00350
00351 $tasks= array();
00352
00353 foreach($project->getTasks(array(
00354 'sort_hierarchical'=>false,
00355 'parent_task'=> $this->id,
00356 'show_folders'=>true,
00357 'status_min'=> STATUS_UPCOMING,
00358 'status_max'=> STATUS_CLOSED,
00359 )) as $t) {
00360 $tasks[]= $t;
00361 if($t->category == TCATEGORY_FOLDER) {
00362 foreach($t->getSubtasksRecursive() as $st) {
00363 $tasks[] = $st;
00364 }
00365 }
00366 }
00367 return $tasks;
00368 }
00369
00370
00371
00372 function getMilestoneTasks($order_by=NULL)
00373 {
00374
00375 if(!$project = Project::getById($this->project)) {
00376 $PH->abortWarning(__("task without project?"), ERROR_BUG);
00377 }
00378
00379 return $project->getTasks(array(
00380 'order_by' => $order_by,
00381 'sort_hierarchical'=>false,
00382 'for_milestone'=> $this->id,
00383 'show_folders'=>true,
00384 ));
00385 }
00386
00393 function getNumSubtasks()
00394 {
00395 global $auth;
00396
00397 if(!$project= Project::getById($this->project)) {
00398 $PH->abortWarning(__("task without project?"), ERROR_BUG);
00399 }
00400 $subtasks = Task::getAll(array(
00401 'folders_only' =>false,
00402 'show_folders' =>true,
00403 'sort_hierarchical' =>true,
00404 'use_collapsed' =>false,
00405 'parent_task' =>$this->id,
00406
00407 ));
00408 $count= 0;
00409 foreach($subtasks as $t) {
00410 if(!$t->is_folder) {
00411 $count++;
00412 }
00413 }
00414 return $count;
00415 }
00416
00417
00418
00419 #----------------------------
00420 # get folder
00421 #----------------------------
00422 # returns array of tasks
00423 function getFolder()
00424 {
00425 $folder=array();
00426 $folder_ids=array(); #hash to detect cycle-lock
00427
00428 $cur_task=$this;
00429 while($cur_task && intval($cur_task->parent_task)) {
00430 if(isset($folder_ids[$cur_task->parent_task])) {
00431 trigger_error('Cycle lock for task '.$cur_task->parent_task.'! Possibly invalid database structure', E_USER_WARNING);
00432 break;
00433
00434 }
00435 else if($cur_task=Task::getVisibleById(intval($cur_task->parent_task))) {
00436 $folder_ids[$cur_task->id]= true;
00437 $folder[]=$cur_task;
00438 }
00439 }
00440 return array_reverse($folder);
00441 }
00442
00443
00447 function getFolderLinks($shortnames=true, $project= NULL)
00448 {
00449 measure_start('col_TaskFolderlinks');
00450 global $PH;
00451 $link_list= array();
00452
00453 if($project) {
00454 $link_list[]= "<b>". $project->getLink() . "</b>";
00455 }
00456
00457 foreach($this->getFolder() as $f) {
00458 if($shortnames) {
00459 $link_list[]= $PH->getLink('taskView',$f->getShort(),array('tsk'=>$f->id));
00460 }
00461 else {
00462 $link_list[]= $PH->getLink('taskView',$f->name,array('tsk'=>$f->id));
00463 }
00464 }
00465 measure_stop('col_TaskFolderlinks');
00466 return implode('<em> > </em>', $link_list);
00467 }
00468
00469 #------------------------------------------------------------------------------------------------
00470 # ungroup subtasks
00471 # - when deleting a folder (or changing it into a normal task) we need to ungroup the subtasks
00472 # - returns number of ungrouped tasks
00473 #------------------------------------------------------------------------------------------------
00474 public function ungroupSubtasks()
00475 {
00476 $tasks=$this->getSubtasks();
00477 foreach($tasks as $t) {
00478 $t->parent_task= $this->parent_task;
00479 $t->update();
00480 }
00481
00482 if($this->is_milestone) {
00483 $tasks= $this->getMilestoneTasks();
00484 foreach($tasks as $t) {
00485 $t->for_milestone= 0;
00486 $t->update();
00487 }
00488 }
00489 return count($tasks);
00490 }
00491
00492
00493 #----------------------------------------------------
00494 # getComments()
00495 #----------------------------------------------------
00496 function &getComments($args=array())
00497 {
00498 if($project= Project::getVisibleById($this->project)) {
00499 $args['on_task']= $this->id;
00500
00501 $comments= $project->getComments($args);
00502 return $comments;
00503 }
00504 }
00505
00506
00507 function &getLatestComment($args=array())
00508 {
00509 if($project= Project::getVisibleById($this->project)) {
00510 $args['on_task']= $this->id;
00511 $args['order_by']= 'created ASC';
00512 #$args['limit']= 1;
00513
00514 $comments= $project->getComments($args);
00515 return $comments[0];
00516 }
00517 }
00518
00522 function &getNumComments()
00523 {
00524 global $auth;
00525 $prefix= confGet('DB_TABLE_PREFIX');
00526 require_once(confGet('DIR_STREBER') . 'db/class_comment.inc.php');
00527 $dbh = new DB_Mysql;
00528 $sth= $dbh->prepare(
00529 "SELECT COUNT(*) from {$prefix}item i, {$prefix}comment c, {$prefix}projectperson upp
00530 WHERE
00531 upp.person = {$auth->cur_user->id}
00532 AND upp.project = $this->project
00533 AND upp.state = 1
00534
00535 AND i.type = '".ITEM_COMMENT."'
00536 AND i.project = $this->project
00537 AND i.state = 1
00538 AND ( i.pub_level >= upp.level_view
00539 OR
00540 i.created_by = {$auth->cur_user->id}
00541 )
00542
00543 AND c.id = i.id
00544 AND c.task=$this->id /* only task-comments*/
00545 "
00546 );
00547 $sth->execute("",1);
00548 $tmp=$sth->fetchall_assoc();
00549 return $tmp[0]['COUNT(*)'];
00550 }
00551
00552
00560 function &getSumEfforts()
00561 {
00562 global $auth;
00563 $sum=0;
00564
00565 $prefix= confGet('DB_TABLE_PREFIX');
00566 require_once(confGet('DIR_STREBER') . 'db/class_effort.inc.php');
00567 $dbh = new DB_Mysql;
00568 $query_str=
00569
00570 "SELECT SUM(unix_timestamp(e.time_end) - unix_timestamp(e.time_start)) from {$prefix}item i, {$prefix}effort e, {$prefix}projectperson upp
00571 WHERE
00572 upp.person = {$auth->cur_user->id}
00573 AND upp.project = $this->project
00574 AND upp.state = 1
00575
00576 AND i.type = '".ITEM_EFFORT."'
00577 AND i.state=1
00578 AND i.project = $this->project
00579 AND ( i.pub_level >= upp.level_view
00580 OR
00581 i.created_by = {$auth->cur_user->id}
00582 )
00583
00584 AND e.id = i.id
00585 AND e.task=$this->id /* only task-efforts*/
00586 ";
00587
00588 $sth= $dbh->prepare($query_str);
00589 $sth->execute("",1);
00590 $tmp= $sth->fetch_row();
00591 if($tmp) {
00592 $sum+= $tmp[0];
00593 }
00594
00595 ### recursively go through sub-tasks ###
00596 if($subtasks=$this->getSubtasks()) {
00597 foreach($subtasks as $st){
00598 $sum+= $st->getSumEfforts();
00599 }
00600 }
00601 return $sum;
00602 }
00603
00604 function &getSumTaskEfforts()
00605 {
00606 global $auth;
00607 $sum=0;
00608
00609 $prefix= confGet('DB_TABLE_PREFIX');
00610 require_once(confGet('DIR_STREBER') . 'db/class_effort.inc.php');
00611 $dbh = new DB_Mysql;
00612 $query_str=
00613
00614 "SELECT SUM(unix_timestamp(e.time_end) - unix_timestamp(e.time_start)) from {$prefix}item i, {$prefix}effort e
00615 WHERE
00616 i.type = '".ITEM_EFFORT."'
00617 AND i.state=1
00618 AND i.project = $this->project
00619 AND e.id = i.id
00620 AND e.task=$this->id /* only task-efforts*/
00621 ";
00622
00623 $sth= $dbh->prepare($query_str);
00624 $sth->execute("",1);
00625 $tmp= $sth->fetch_row();
00626 if($tmp) {
00627 $sum+= $tmp[0];
00628 }
00629
00630 ### recursively go through sub-tasks ###
00631 if($subtasks=$this->getSubtasks()) {
00632 foreach($subtasks as $st){
00633 # $sum+= $st->getSumEfforts2();
00634 $sum+= $st->getSumEfforts();
00635 }
00636 }
00637 return $sum;
00638 }
00639
00640
00641
00645 public static function &getHomeTasks($order_by=" is_folder DESC, parent_task, prio ASC, project, name")
00646 {
00647 global $auth;
00648 $prefix= confGet('DB_TABLE_PREFIX');
00649 $dbh = new DB_Mysql;
00650
00651 #--- select all visible tasks in home ---
00652 switch($auth->cur_user->show_tasks_at_home) {
00653 case SHOW_ASSIGNED_ONLY:
00654
00655 $query_str= "
00656 SELECT i.*, t.* from {$prefix}item i, {$prefix}task t, {$prefix}project p, {$prefix}projectperson upp, {$prefix}taskperson tp, {$prefix}item itp
00657 WHERE
00658 upp.person = {$auth->cur_user->id}
00659 AND upp.state = 1
00660 AND upp.project = p.id /* all user projectpersons */
00661
00662 AND p.state = 1
00663 AND p.status >=1
00664 AND p.status <= ".STATUS_OPEN."
00665
00666 AND p.id = i.project
00667
00668 AND i.type = '".ITEM_TASK."'
00669 AND t.is_folder = 0
00670 AND i.pub_level >= upp.level_view
00671 AND i.state = 1
00672 AND i.project = p.id
00673
00674 AND t.id= i.id
00675 AND t.status <= ". STATUS_COMPLETED."
00676
00677 /* filter assigned */
00678 AND t.id = tp.task
00679 AND tp.person = {$auth->cur_user->id}
00680 AND tp.id = itp.id
00681 AND itp.state = 1
00682 AND (itp.pub_level >= upp.level_view
00683 OR
00684 itp.created_by = {$auth->cur_user->id}
00685 )
00686
00687
00688
00689 ". getOrderByString($order_by);
00690 break;
00691
00692
00693
00694 case SHOW_ALSO_UNASSIGNED:
00695 trigger_error("filtering unassigned tasks has not been implemented yet",E_USER_NOTICE);
00696 case SHOW_ALL_OPEN:
00697
00698 $query_str= "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t, {$prefix}project p, {$prefix}projectperson upp
00699 WHERE
00700 upp.person = {$auth->cur_user->id}
00701 AND upp.state = 1
00702 AND upp.project = p.id /* all user projectpersons */
00703
00704 AND p.state = 1
00705 AND p.status >=1
00706 AND p.status <= ".STATUS_OPEN."
00707
00708 AND p.id = i.project
00709
00710 AND i.type = '".ITEM_TASK."'
00711 AND t.is_folder = 0
00712 AND i.pub_level >= upp.level_view /* @@@ add created_by support */
00713 AND i.state = 1
00714 AND i.project = p.id
00715
00716 AND t.id= i.id
00717 AND t.status <= ".STATUS_BLOCKED."
00718
00719 ". getOrderByString($order_by);
00720 break;
00721 default:
00722 trigger_error("Unknown setting for home task-list",E_USER_NOTICE);
00723 }
00724
00725 $sth= $dbh->prepare($query_str);
00726 $sth->execute("",1);
00727 $tmp=$sth->fetchall_assoc();
00728
00729 $tasks=array();
00730 foreach($tmp as $t) {
00731
00732 unset($t['due_sort']); # remove temporary sql-variable
00733 $task=new Task($t);
00734
00735 $tasks[]=$task;
00736 }
00737 return $tasks;
00738 }
00739
00740
00755 static function &getAll( $args=NULL)
00756 {
00757 global $auth;
00758 $prefix = confGet('DB_TABLE_PREFIX');
00759
00760 ### default params ###
00761 $project = NULL;
00762 $show_folders = true;
00763 $order_by = "is_folder DESC, parent_task, prio ASC,project,name";
00764 $status_min = STATUS_NEW;
00765 $status_max = STATUS_BLOCKED;
00766 $visible_only = NULL; # use project rights settings
00767 $alive_only = true; # ignore deleted
00768 $parent_task = NULL; #
00769 $sort_hierarchical= false;
00770 $use_collapsed = false; # by default ignore collapsed folders
00771 $issues_only = false;
00772 $folders_only = false;
00773 $level = 0; # hierarchical depth in trees
00774 $assigned_to_person=0; # skip by default
00775 $search = NULL;
00776 $name = NULL;
00777 $is_milestone = 0;
00778 $for_milestone = NULL;
00779 $resolved_version = NULL;
00780 $is_released_min= NULL;
00781 $is_released_max= NULL;
00782 $id = NULL;
00783 $modified_by = NULL;
00784 $not_modified_by = NULL;
00785 $resolve_reason_min= NULL;
00786 $category = NULL;
00787 $category_in = NULL;
00788 $label = NULL;
00789
00790 ### filter params ###
00791 if($args) {
00792 foreach($args as $key=>$value) {
00793 if(!isset($$key) && !is_null($$key) && !$$key==="") {
00794 trigger_error("unknown parameter",E_USER_NOTICE);
00795 }
00796 else {
00797 $$key= $value;
00798 }
00799 }
00800 }
00801
00802 if($sort_hierarchical && is_null($parent_task)) {
00803 $parent_task=0;
00804 }
00805 $str_project= $project
00806 ? 'AND upp.project='.intval($project)
00807 : '';
00808 $str_project2= $project
00809 ? 'AND i.project='.intval($project)
00810 : '';
00811
00812 $str_is_alive= $alive_only
00813 ? 'AND i.state='. ITEM_STATE_OK
00814 : '';
00815
00816 $str_is_issue= $issues_only
00817 ? 'AND t.issue_report!=0'
00818 : '';
00819
00820 $str_is_folder= $show_folders
00821 ? ''
00822 : 'AND t.is_folder=0';
00823
00824
00825 $str_modified_by= $modified_by
00826 ? 'AND i.modified_by ='. intval($modified_by)
00827 : '';
00828
00829 $str_not_modified_by= $not_modified_by
00830 ? 'AND i.modified_by !='. intval($not_modified_by)
00831 : '';
00832
00833
00834 $str_id= $id
00835 ? 'AND t.id='.intval($id)
00836 : '';
00837
00838
00839 if(!is_null($label)) {
00840 $str_label= 'AND t.label=' . intval($label);
00841 }
00842 else {
00843 $str_label= '';
00844 }
00845
00846
00847 if(!is_null($is_milestone)) {
00848 $str_is_milestone= $is_milestone
00849 ? 'AND t.is_milestone=1'
00850 : 'AND t.is_milestone=0';
00851 }
00852 else {
00853 $str_is_milestone='';
00854 }
00855
00856 if(!is_null($category)) {
00857 $str_category='AND t.category='. intval($category);
00858 }
00859 else {
00860 $str_category='';
00861 }
00862 if(!is_null($category_in)) {
00863 $str_category_in='AND t.category IN('. join(",",$category_in) .')';
00864 }
00865 else {
00866 $str_category_in='';
00867 }
00868
00869 $str_is_released_min= $is_released_min
00870 ? 'AND t.is_released >= '. intval($is_released_min)
00871 : '';
00872
00873
00874 if($resolve_reason_min !== NULL) {
00875 $str_resolve_reason_min= $resolve_reason_min
00876 ? 'AND t.resovle_reason >= '. intval($resolve_reason_min)
00877 : '';
00878 }
00879 else {
00880 $str_reasolve_reason_min= '';
00881 }
00882
00883
00884 $str_is_released_max= $is_released_max
00885 ? 'AND t.is_released <= '. intval($is_released_max)
00886 : '';
00887
00888 $str_has_name= $name
00889 ? "AND (t.name='".asSecureString($name)."' or t.short='".asSecureString($name)."')"
00890 : "";
00891
00892 if(!is_null($for_milestone)) {
00893 $str_for_milestone= 'AND t.for_milestone='. intval($for_milestone);
00894 }
00895 else {
00896 $str_for_milestone= '';
00897 }
00898
00899
00900 if(!is_null($resolved_version)) {
00901 $str_resolved_version= 'AND t.resolved_version='.intval($resolved_version);
00902 }
00903 else {
00904 $str_resolved_version= '';
00905 }
00906
00907
00908 if($folders_only) {
00909 $str_is_folder= 'AND t.is_folder=1';
00910 }
00911
00912 $str_parent_task= !is_null($parent_task)
00913 ? 'AND t.parent_task='.intval($parent_task)
00914 : '';
00915
00916 $str_match= $search
00917 ? "AND MATCH (t.name,t.short,t.description) AGAINST ('". asCleanString($search) ."*' IN BOOLEAN MODE)"
00918 : '';
00919
00920 if(is_null($visible_only)) {
00921
00922 $visible_only = $auth->cur_user && $auth->cur_user->user_rights & RIGHT_VIEWALL
00923 ? false
00924 : true ;
00925 }
00926 if($visible_only) {
00927
00928 ### only filter assigned to person ###
00929 if($assigned_to_person) {
00930 $str_query=
00931 "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t, {$prefix}taskperson tp, {$prefix}projectperson upp, {$prefix}item itp
00932 WHERE
00933 upp.person = {$auth->cur_user->id}
00934 $str_project
00935 AND i.type = '".ITEM_TASK."'
00936 AND i.project=upp.project
00937 $str_is_alive
00938 $str_project2
00939 $str_modified_by
00940 $str_not_modified_by
00941
00942 $str_is_issue
00943
00944 AND ( i.pub_level >= upp.level_view
00945 OR
00946 i.created_by = {$auth->cur_user->id}
00947 )
00948
00949 AND t.id = i.id
00950 $str_id
00951 $str_is_folder
00952 $str_is_issue
00953 $str_label
00954 $str_parent_task
00955 $str_has_name
00956 $str_is_milestone
00957 $str_is_released_min
00958 $str_is_released_max
00959 $str_for_milestone
00960 $str_resolved_version
00961 $str_category
00962 $str_category_in
00963 AND t.status >= ". intval($status_min)."
00964 AND t.status <= ". intval($status_max)."
00965
00966 AND i.id = tp.task
00967 AND tp.person = $assigned_to_person
00968 AND itp.id = tp.id
00969 AND itp.state = 1
00970 ".
00971 # AND (itp.pub_level >= upp.level_view
00972 # OR
00973 # itp.created_by = {$auth->cur_user->id}
00974 # )
00975 "
00976 $str_match
00977
00978 " . getOrderByString($order_by);
00979 }
00980 else {
00981 $str_query=
00982 "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t, {$prefix}projectperson upp
00983 WHERE
00984 upp.person = {$auth->cur_user->id}
00985 $str_project
00986 AND i.type = '".ITEM_TASK."'
00987 AND i.project = upp.project
00988 $str_is_alive
00989 $str_project2
00990 $str_modified_by
00991 $str_not_modified_by
00992 $str_is_issue
00993 $str_is_milestone
00994 $str_is_released_min
00995 $str_is_released_max
00996 $str_for_milestone
00997 $str_label
00998 $str_resolved_version
00999 $str_category
01000 $str_category_in
01001 AND ( i.pub_level >= upp.level_view
01002 OR
01003 i.created_by = {$auth->cur_user->id}
01004 )
01005
01006 AND t.id = i.id
01007 $str_is_folder
01008 $str_is_issue
01009 $str_parent_task
01010 $str_has_name
01011 $str_id
01012 AND t.status >= ".intval($status_min)."
01013 AND t.status <= ".intval($status_max)."
01014 $str_match
01015
01016 " . getOrderByString($order_by);
01017 }
01018 }
01019 ### show all ###
01020 else {
01021 if($assigned_to_person) {
01022 $str_query=
01023 "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t, {$prefix}taskperson tp ,{$prefix}item itp
01024 WHERE
01025 i.type = '".ITEM_TASK."'
01026 $str_project2
01027 $str_is_alive
01028 $str_modified_by
01029 $str_not_modified_by
01030
01031 AND t.id = i.id
01032 $str_id
01033 $str_is_folder
01034 $str_is_issue
01035 $str_parent_task
01036 $str_has_name
01037 $str_label
01038 $str_is_milestone
01039 $str_is_released_min
01040 $str_is_released_max
01041 $str_for_milestone
01042 $str_resolved_version
01043 $str_category
01044 $str_category_in
01045
01046 AND t.status >= ".intval($status_min)."
01047 AND t.status <= ".intval($status_max)."
01048 $str_match
01049 AND i.id = tp.task
01050 AND tp.person = $assigned_to_person
01051 AND tp.id = itp.id
01052 AND itp.state = 1
01053 " . getOrderByString($order_by);
01054 }
01055 else {
01056 $str_query=
01057 "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t
01058 WHERE
01059 i.type = '".ITEM_TASK."'
01060 $str_project2
01061 $str_is_alive
01062 $str_modified_by
01063 $str_not_modified_by
01064
01065 AND t.id = i.id
01066 $str_id
01067 $str_is_folder
01068 $str_is_issue
01069 $str_is_milestone
01070 $str_for_milestone
01071 $str_label
01072 $str_resolved_version
01073 $str_category
01074 $str_category_in
01075
01076 $str_is_released_min
01077 $str_is_released_max
01078 $str_parent_task
01079 $str_has_name
01080 AND t.status >= ".intval($status_min)."
01081 AND t.status <= ".intval($status_max)."
01082 $str_match
01083
01084 " . getOrderByString($order_by);
01085 }
01086 }
01087
01088 $dbh = new DB_Mysql;
01089 $sth= $dbh->prepare($str_query);
01090
01091 $sth->execute("",1);
01092 $tmp=$sth->fetchall_assoc();
01093
01094 $tasks=array();
01095 foreach($tmp as $t) {
01096 $task=new Task($t);
01097 $task->level= $level;
01098 $tasks[]=$task;
01099
01100 ### hierarchical / recursive sorting ###
01101 if($sort_hierarchical && $task->is_folder && (!$use_collapsed || !$task->view_collapsed)) {
01102 if($sub_tasks=Task::getAll(array(
01103 'sort_hierarchical' =>true,
01104
01105 'use_collapsed'=> $use_collapsed,
01106 'parent_task' => $task->id,
01107 'order_by' => $order_by,
01108 'visible_only' => $visible_only,
01109 'alive_only' => $alive_only,
01110 'issues_only' => $issues_only,
01111 'status_min' => $status_min,
01112 'status_max' => $status_max,
01113 'level' => $level+1,
01114 'folders_only' => $folders_only,
01115 'project' => $project,
01116 ))) {
01117 foreach($sub_tasks as &$st) {
01118 $tasks[]= $st;
01119 }
01120 }
01121 }
01122 }
01123 return $tasks;
01124 }
01125
01129 function getAssignments() {
01130 $prefix = confGet('DB_TABLE_PREFIX');
01131 require_once(confGet('DIR_STREBER') . 'db/class_taskperson.inc.php');
01132 $dbh = new DB_Mysql;
01133
01134 $order_by="pers.name";
01135
01136 ### all projects ###
01137 #
01138 # TODO @@@ CHECK projeckt-assigment / visible persons...
01139 # if( $auth->cur_user->user_rights & RIGHT_PROJECT_ASSIGN) {
01140 $query_str=
01141 "SELECT itp.*, tp.* from {$prefix}item itp, {$prefix}person pers, {$prefix}taskperson tp
01142 WHERE
01143 pers.state = 1
01144
01145 AND pers.id = tp.person
01146 AND tp.task= $this->id
01147 AND tp.id = itp.id
01148 AND itp.state = 1
01149
01150 ORDER BY $order_by";
01151
01152 $sth= $dbh->prepare($query_str);
01153 $sth->execute("",1);
01154 $tmp=$sth->fetchall_assoc();
01155 $tps=array();
01156 foreach($tmp as $tp) {
01157 $tps[]=new TaskPerson($tp);
01158 }
01159 return $tps;
01160 }
01161
01162
01166 function isAssignedToPerson($person)
01167 {
01168
01169 if($person instanceof Person) {
01170 $person_id= $person->id;
01171 }
01172 else {
01173 $person_id= intval($person);
01174 }
01175
01176 $prefix = confGet('DB_TABLE_PREFIX');
01177 $dbh = new DB_Mysql;
01178
01179 ### all projects ###
01180 $query_str=
01181 "SELECT COUNT(*) from {$prefix}item itp, {$prefix}taskperson tp
01182 WHERE
01183 itp.state= 1
01184 AND itp.id = tp.id
01185 AND tp.person= $person_id
01186 AND tp.task= $this->id";
01187
01188
01189 $sth= $dbh->prepare($query_str);
01190 $sth->execute("",1);
01191
01192 $tmp=$sth->fetchall_assoc();
01193 return $tmp[0]['COUNT(*)'];
01194 }
01195
01196
01197
01201 function getAssignedPersons($visible_only=true) {
01202 global $auth;
01203
01204 $prefix = confGet('DB_TABLE_PREFIX');
01205 $dbh = new DB_Mysql;
01206
01207 $order_by="pers.name";
01208
01209 $query_str=
01210 "SELECT i.*, pers.* from {$prefix}item i, {$prefix}person pers, {$prefix}taskperson tp, {$prefix}item itp
01211 WHERE
01212 pers.state = 1
01213
01214 AND pers.id = i.id
01215 AND pers.id = tp.person
01216 AND tp.task= $this->id
01217 AND tp.id = itp.id
01218 AND itp.state = 1
01219
01220 ORDER BY $order_by";
01221
01222 $sth= $dbh->prepare($query_str);
01223 $sth->execute("",1);
01224 $tmp=$sth->fetchall_assoc();
01225
01226 $persons=array();
01227
01228
01229 #--- return all ---
01230 if(!$visible_only || $auth->cur_user->user_rights & RIGHT_PROJECT_ASSIGN) {
01231 foreach($tmp as $t) {
01232 $persons[]=new Person($t);
01233 }
01234
01235 return $persons;
01236 }
01237 else {
01238 $project= Project::getById($this->project);
01239 foreach($tmp as $t) {
01240
01241 $p=new Person($t);
01242 if($project->isPersonVisibleTeamMember($p)) {
01243 $persons[]= $p;
01244 }
01245 }
01246 return $persons;
01247 }
01248 }
01249
01250 public function getLink($short_name= true)
01251 {
01252
01253 $style_isdone= $this->status >= STATUS_COMPLETED
01254 ? 'isDone'
01255 : '';
01256
01257 global $PH;
01258 if($short_name) {
01259 return '<span title="'.asHtml($this->name).'" class="item task">'.$PH->getLink('taskView',$this->getShort(),array('tsk'=>$this->id),$style_isdone).'</span>';
01260 }
01261 else {
01262 return '<span class="item task">'.$PH->getLink('taskView',$this->name,array('tsk'=>$this->id),$style_isdone).'</span>';
01263 }
01264 }
01265
01266
01267 public function getLabel()
01268 {
01269 if($this->is_folder) {
01270 return __('Folder');
01271 }
01272 else if($this->category == TCATEGORY_MILESTONE) {
01273 return __('Milestone');
01274
01275 }
01276 else if ($this->category == TCATEGORY_VERSION) {
01277 return __('Released Milestone');
01278 }
01279 else if ($this->category == TCATEGORY_DOCU) {
01280 return __('Documentation');
01281 }
01282 else if ($this->category == TCATEGORY_BUG) {
01283 return __('Bug');
01284 }
01285
01286 else if($this->label) {
01287 if(!$project= Project::getById($this->project)) {
01288 trigger_error("task without project?", E_USER_WARNING);
01289 }
01290 $labels=split(",",$project->labels);
01291 $value= $labels[$this->label-1];
01292 return $value;
01293 }
01294 else {
01295 return '';
01296 }
01297 }
01298
01314 static function &getTaskById( $args=NULL)
01315 {
01316 global $auth;
01317 $prefix = confGet('DB_TABLE_PREFIX');
01318
01319 ### default params ###
01320 $id = NULL;
01321 $project = NULL;
01322 $show_folders = true;
01323 $order_by = "is_folder DESC, parent_task, prio ASC,project,name";
01324 $status_min = STATUS_NEW;
01325 $status_max = STATUS_BLOCKED;
01326 $visible_only = true; # use project rights settings
01327 $alive_only = true; # ignore deleted
01328 $parent_task = NULL; #
01329 $sort_hierarchical= false;
01330 $use_collapsed = false; # by default ignore collapsed folders
01331 $issues_only = false;
01332 $folders_only = false;
01333 $level = 0; # hierarchical depth in trees
01334 $assigned_to_person=0; # skip by default
01335 $search = NULL;
01336 $name = NULL;
01337 $is_milestone = 0;
01338 $for_milestone = NULL;
01339
01340 ### filter params ###
01341 if($args) {
01342 foreach($args as $key=>$value) {
01343 if(!isset($$key) && !is_null($$key) && !$$key==="") {
01344 trigger_error("unknown parameter",E_USER_NOTICE);
01345 }
01346 else {
01347 $$key= $value;
01348 }
01349 }
01350 }
01351
01352 if($sort_hierarchical && is_null($parent_task)) {
01353 $parent_task=0;
01354 }
01355 $str_project= $project
01356 ? 'AND upp.project='.intval($project)
01357 : '';
01358 $str_project2= $project
01359 ? 'AND i.project='.intval($project)
01360 : '';
01361
01362 $str_is_alive= $alive_only
01363 ? 'AND i.state='. ITEM_STATE_OK
01364 : '';
01365
01366 $str_is_issue= $issues_only
01367 ? 'AND t.issue_report!=0'
01368 : '';
01369
01370 $str_is_folder= $show_folders
01371 ? ''
01372 : 'AND t.is_folder=0';
01373
01374
01375 $str_id = "AND i.id='" . intval($id) ."'";
01376
01377
01378 if(!is_null($is_milestone)) {
01379 $str_is_milestone= $is_milestone
01380 ? 'AND t.is_milestone=1'
01381 : 'AND t.is_milestone=0';
01382 }
01383 else {
01384 $str_is_milestone='';
01385 }
01386
01387 $str_has_name= $name
01388 ? "AND (t.name='".asSecureString($name)."' or t.short='".asSecureString($name)."')"
01389 : "";
01390
01391 if(!is_null($for_milestone)) {
01392 $str_for_milestone= $for_milestone
01393 ? 'AND t.for_milestone='.intval($for_milestone)
01394 : '';
01395 }
01396 else {
01397 $str_for_milestone= '';
01398 }
01399
01400
01401 if($folders_only) {
01402 $str_is_folder= 'AND t.is_folder=1';
01403 }
01404
01405 $str_parent_task= !is_null($parent_task)
01406 ? 'AND t.parent_task='.intval($parent_task)
01407 : '';
01408
01409 $str_match= $search
01410 ? "AND MATCH (t.name,t.short,t.description) AGAINST ('". asCleanString($search) ."*' IN BOOLEAN MODE)"
01411 : '';
01412
01413 if($visible_only) {
01414 if($assigned_to_person) {
01415 $str_query=
01416 "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t, {$prefix}taskperson tp, {$prefix}projectperson upp, {$prefix}item itp
01417 WHERE
01418 upp.person = {$auth->cur_user->id}
01419 $str_project
01420 AND i.type = '".ITEM_TASK."'
01421 AND i.project=upp.project
01422 $str_id
01423
01424 $str_is_alive
01425 $str_project2
01426
01427 $str_is_issue
01428 AND ( i.pub_level >= upp.level_view
01429 OR
01430 i.created_by = {$auth->cur_user->id}
01431 )
01432
01433 AND t.id = i.id
01434
01435 $str_is_folder
01436 $str_is_issue
01437 $str_parent_task
01438 $str_has_name
01439 $str_is_milestone
01440 $str_for_milestone
01441 AND t.status >= ". intval($status_min)."
01442 AND t.status <= ". intval($status_max)."
01443
01444 AND i.id = tp.task
01445 AND tp.person = $assigned_to_person
01446 AND itp.id = tp.id
01447 AND itp.state = 1
01448 AND (itp.pub_level >= upp.level_view
01449 OR
01450 itp.created_by = {$auth->cur_user->id}
01451 )
01452 $str_match
01453
01454 " . getOrderByString($order_by);
01455 }
01456 else {
01457 $str_query=
01458 "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t, {$prefix}projectperson upp
01459 WHERE
01460
01461 upp.person = {$auth->cur_user->id}
01462 $str_project
01463 AND i.type = '".ITEM_TASK."'
01464 AND i.project = upp.project
01465 $str_id
01466 $str_is_alive
01467 $str_project2
01468 $str_is_issue
01469 $str_is_milestone
01470 $str_for_milestone
01471 AND ( i.pub_level >= upp.level_view
01472 OR
01473 i.created_by = {$auth->cur_user->id}
01474 )
01475 AND t.id = i.id
01476 $str_is_folder
01477 $str_is_issue
01478 $str_parent_task
01479 $str_has_name
01480
01481 AND t.status >= ".intval($status_min)."
01482 AND t.status <= ".intval($status_max)."
01483 $str_match
01484
01485 " . getOrderByString($order_by);
01486
01487 }
01488 }
01489 ### show all ###
01490 else {
01491 if($assigned_to_person) {
01492 $str_query=
01493 "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t, {$prefix}taskperson tp ,{$prefix}item itp
01494 WHERE
01495 i.type = '".ITEM_TASK."'
01496 $str_id
01497
01498 $str_project2
01499 $str_is_alive
01500
01501 #AND t.id = i.id
01502 $str_id
01503 $str_is_folder
01504 $str_is_issue
01505 $str_parent_task
01506 $str_has_name
01507 $str_is_milestone
01508 $str_for_milestone
01509
01510 AND t.status >= ".intval($status_min)."
01511 AND t.status <= ".intval($status_max)."
01512 $str_match
01513 AND i.id = tp.task
01514 AND tp.person = $assigned_to_person
01515 AND tp.id = itp.id
01516 AND itp.state = 1
01517 " . getOrderByString($order_by);
01518 }
01519 else {
01520 $str_query=
01521 "SELECT i.*, t.* from {$prefix}item i, {$prefix}task t
01522 WHERE
01523 i.type = '".ITEM_TASK."'
01524 $str_id
01525
01526 $str_project2
01527 $str_is_alive
01528
01529 #AND t.id = i.id
01530 $str_id
01531 $str_is_folder
01532 $str_is_issue
01533 $str_is_milestone
01534 $str_for_milestone<