db/class_task.inc.php

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 // Task
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     //=== constructor ================================================
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 Task::query(array(
00199     Task::Filter('project','=',0),
00200     Task::Filter('name','matches','tom'),
00201 ))
00202 -> url go=tasksQuery&filter_project_is=0&filter_name_matches=tom
00203 
00204 $filters_str= get('filter_*');
00205 $f= array();
00206 foreach($filters_str as $fs=>$value) {
00207   preg_matches("/(.*)_(.*)/", $fs, $matches);
00208   list($count, $name, $type)= $matches;
00209   if($count == 2) {
00210     $f[]= new Filter($name, $type, $value);
00211   }
00212 }
00213 
00214     public static function Filter($field_name, $type, $value)
00215     {
00216         if(isset(self::$fields_static[$field_name])) {
00217             $field= self::$fields_static[$field_name];
00218             switch($type) {
00219                 case '=': return new FilterIs($field, $value);
00220                 case '!=': return new FilterIsNot($field, $value);
00221                 case '<=': return new FilterLessEqual($field, $value);
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 ." &gt; " . $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> &gt; </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<