00001 <?php if(!function_exists('startedIndexPhp')) { header("location:../index.php"); exit();}
00002 # streber - a php5 based project management system (c) 2005-2007 / www.streber-pm.org
00003 # Distributed under the terms and conditions of the GPL as stated in lang/license.html
00004
00005
00020 global $g_cache_projects;
00021 $g_cache_projects=array();
00022
00023
00024
00025
00026
00027
00031 class Project extends DbProjectItem
00032 {
00033 public $_visible_team=NULL; # assoc array for optimized visibility-check
00034
00035
00036 function __construct ($id_or_array=NULL)
00037 {
00038 global $g_project_fields;
00039 $this->fields= &$g_project_fields;
00040
00041 parent::__construct($id_or_array);
00042 $this->type= ITEM_PROJECT;
00043 }
00044
00045
00046 static function initFields()
00047 {
00048
00049 global $g_project_fields;
00050 $g_project_fields=array();
00051 addProjectItemFields(&$g_project_fields);
00052
00053 foreach(array(
00054 new FieldInternal(array( 'name'=>'id',
00055 'default'=>0,
00056 'in_db_object'=>1,
00057 'in_db_item'=>1,
00058 )),
00059 new FieldInternal(array( 'name'=>'state', ### cached in project-table to speed up queries ###
00060 'default'=>1,
00061 'in_db_object'=>1,
00062 'in_db_item'=>1,
00063 )),
00064 new FieldString(array( 'name'=>'name',
00065 'title'=>__('Name'),
00066 'required'=>true,
00067 )),
00068 new FieldString(array( 'name'=>'short',
00069 'title'=>__('Short'),
00070 )),
00071 new FieldString(array( 'name'=>'status_summary',
00072 'title'=>__('Status summary'),
00073 )),
00074 new FieldString(array( 'name'=>'color',
00075 'title'=>__('Color'),
00076 )),
00077 new FieldDate(array( 'name'=>'date_start',
00078 'title'=>__('Date start'),
00079 'default'=>FINIT_TODAY
00080 )),
00081 new FieldDate(array( 'name'=>'date_closed',
00082 'title'=>__('Date closed'),
00083 'default'=>FINIT_NEVER
00084 )),
00085 new FieldOption(array( 'name'=>'status',
00086 'title'=>__('Status'),
00087 'default'=>3
00088 )),
00089 new FieldString(array( 'name'=>'projectpage',
00090 'title'=>__('Project page'),
00091 )),
00092 new FieldString(array( 'name'=>'wikipage',
00093 'title'=>__('Wiki page'),
00094 )),
00095 new FieldInt(array( 'name'=>'prio',
00096 'title'=>__('Priority'),
00097 'default'=>3
00098 )), # @@@ todo: default-status and prio should be project-setting!
00099 new FieldText(array( 'name'=>'description',
00100 'title'=>__('Description'),
00101 )),
00102 new FieldInt(array( 'name'=>'company',
00103 'title'=>__('Company'),
00104 )),
00105 new FieldBool(array( 'name'=>'show_in_home',
00106 'default'=>1,
00107 'title'=>__('show tasks in home'),
00108 )),
00109
00113 new FieldInternal(array( 'name'=>'settings',
00114 'default'=> confGet('PROJECT_DEFAULT_SETTINGS'),
00115 'log_changes'=>true,
00116 )),
00117
00118
00122 new FieldHidden(array( 'name'=>'labels',
00123 'default'=> confGet("PROJECT_DEFAULT_LABELS"),
00124 )),
00125
00126 new FieldInternal(array( 'name'=>'default_pub_level', # level of new items
00127 'view_in_forms'=>false,
00128 'default'=>PUB_LEVEL_OPEN,
00129 )),
00130 ) as $f) {
00131 $g_project_fields[$f->name]=$f;
00132 }
00133 }
00134
00140 static function getById($id, $use_cache=false)
00141 {
00142 global $g_cache_projects;
00143 if($use_cache && isset($g_cache_projects[$id])) {
00144 $p= $g_cache_projects[$id];
00145 }
00146 else {
00147 $p= new Project($id);
00148 $g_cache_projects[$p->id]= $p;
00149 }
00150
00151 if(!$p->id) {
00152 return NULL;
00153 }
00154 return $p;
00155 }
00156
00157
00158
00164 static function getVisibleById($id, $for_person=NULL, $use_cache=true)
00165 {
00166 if(!$for_person) {
00167 global $auth;
00168 $for_person= $auth->cur_user;
00169 }
00170
00171 if($id) {
00172 $p= Project::getById($id, $use_cache);
00173 $g_cache_projects[$p->id]= $p;
00174
00175
00176 if($p && $p->validateView(
00177 STATUS_UPCOMING,
00178 STATUS_CLOSED,
00179 false, #$abort_page=true
00180 $for_person
00181 )) {
00182
00183 return $p;
00184 }
00185 }
00186 return NULL;
00187 }
00188
00192 static function getEditableById($id)
00193 {
00194 global $auth;
00195 if(
00196 $auth->cur_user->user_rights & RIGHT_PROJECT_EDIT
00197 ) {
00198 return Project::getVisibleById($id, NULL, false);
00199 }
00200 return NULL;
00201 }
00202
00203
00204
00209 function getFolders($order_by=NULL)
00210 {
00211 return $this->getTasks(array(
00212 'folders_only' =>true,
00213 'sort_hierarchical' =>true,
00214 'use_collapsed' =>false,
00215 ));
00216 }
00217
00218
00219
00220 function getEfforts($order_by=NULL, $visible_only=true, $alive_only=true)
00221 {
00222 require_once(confGet('DIR_STREBER') . 'db/class_effort.inc.php');
00223 $efforts= Effort::getAll(array(
00224 'project' => $this->id
00225 ));
00226 return $efforts;
00227 }
00228
00229
00230 function getTaskPersons($order_by=NULL, $visible_only=true, $alive_only=true)
00231 {
00232 global $auth;
00233 $prefix= confGet('DB_TABLE_PREFIX');
00234 if(!$order_by) {
00235 $order_by="comment";
00236 }
00237 require_once(confGet('DIR_STREBER') . 'db/class_taskperson.inc.php');
00238 $dbh = new DB_Mysql;
00239
00240 $str_is_alive= $alive_only
00241 ? 'AND i.state='. ITEM_STATE_OK
00242 : '';
00243
00244 if($visible_only) {
00245 $str_query=
00246 "SELECT i.*, tp.* from {$prefix}item i, {$prefix}taskperson tp, {$prefix}projectperson upp
00247 WHERE
00248 upp.person = {$auth->cur_user->id}
00249 AND upp.project = $this->id
00250 AND upp.state = 1
00251
00252
00253 AND i.type = '".ITEM_TASKPERSON."'
00254 AND i.project = $this->id
00255 $str_is_alive
00256
00257 AND ( i.pub_level >= upp.level_view
00258 OR
00259 i.created_by = {$auth->cur_user->id}
00260 )
00261
00262 AND tp.id = i.id
00263 ORDER BY $order_by";
00264 }
00265 else {
00266 $str_query=
00267 "SELECT i.*, tp.* from {$prefix}item i, {$prefix}taskperson tp
00268 WHERE
00269
00270 i.type = '".ITEM_TASKPERSON."'
00271 AND i.project = $this->id
00272 $str_is_alive
00273
00274 AND tp.id = i.id
00275 ORDER BY $order_by";
00276 }
00277
00278 $sth= $dbh->prepare($str_query);
00279 $sth->execute("",1);
00280 $tmp=$sth->fetchall_assoc();
00281 $taskpersons=array();
00282 foreach($tmp as $t) {
00283 $taskpersons[]=new TaskPerson($t);
00284 }
00285
00286 return $taskpersons;
00287 }
00288
00289
00293 function getEffortsSum()
00294 {
00295
00296 $sum=0.0;
00297 if($efforts= $this->getEfforts()) {
00298 foreach($efforts as $e) {
00299 $sum+= 1.0*strToGMTime($e->time_end)-1.0*strToGMTime($e->time_start);
00300 }
00301 }
00302 return $sum;
00303 }
00304
00308 function getProgressSum()
00309 {
00310
00311 $sum=0;
00312 if($tasknum = $this->getNumTasks()) {
00313 if($tasksum = $this->getSumTasksProgress()) {
00314 $sum=($tasksum/$tasknum*100)/100;
00315 }
00316 }
00317 return $sum;
00318 }
00319
00320
00321
00336 function &getTasks( $args=array())
00337 {
00338 $args['project']= $this->id;
00339 $result= Task::getAll($args);
00340 return $result;
00341 }
00342
00348 function getNumTasks()
00349 {
00350 $prefix= confGet('DB_TABLE_PREFIX');
00351 $dbh = new DB_Mysql;
00352 $sth= $dbh->prepare("SELECT COUNT(*) FROM {$prefix}item i, {$prefix}task t
00353 WHERE
00354 i.project = \"$this->id\"
00355 AND i.type= ". ITEM_TASK . "
00356 AND i.state= ". ITEM_STATE_OK . "
00357 AND t.is_folder = 0
00358 AND t.id= i.id
00359 AND t.status < ". STATUS_CLOSED );
00360 $sth->execute("",1);
00361 $tmp=$sth->fetchall_assoc();
00362 return $tmp[0]['COUNT(*)'];
00363 }
00364
00370 function getSumTasksProgress()
00371 {
00372 $prefix= confGet('DB_TABLE_PREFIX');
00373 $dbh = new DB_Mysql;
00374 $sth= $dbh->prepare("SELECT SUM(t.completion) CSUM FROM {$prefix}item i, {$prefix}task t
00375 WHERE
00376 i.project = \"$this->id\"
00377 AND i.type= ". ITEM_TASK . "
00378 AND i.state= ". ITEM_STATE_OK . "
00379 AND t.is_folder = 0
00380 AND t.id= i.id
00381 AND t.status < ". STATUS_CLOSED );
00382 $sth->execute("",1);
00383 $tmp=$sth->fetchall_assoc();
00384 return $tmp[0]['CSUM'];
00385 }
00386
00387
00393 function &getComments($args=Array())
00394 {
00395 global $auth;
00396 $prefix = confGet('DB_TABLE_PREFIX');
00397
00398 ### default params ###
00399 $order_by= 'name';
00400 $visible_only= true; # use project rights settings
00401 $alive_only= true; # ignore deleted
00402 $on_task= 0; # only project-tasks by default
00403 $limit= NULL; # limit number of results
00404
00405
00406 ### filter params ###
00407 if($args) {
00408 foreach($args as $key=>$value) {
00409 if(!isset($$key) && !is_null($$key) && !$$key==="") {
00410 trigger_error("unknown parameter",E_USER_NOTICE);
00411 }
00412 else {
00413 $$key= $value;
00414 }
00415 }
00416 }
00417
00418 $str_parent_task="";
00419 if($on_task) {
00420 $str_parent_task='AND c.task='. intVal($on_task);
00421 }
00422 else {
00423 $str_parent_task="AND c.task=0";
00424 }
00425
00426 $str_limit= $limit
00427 ? "LIMIT " . intval($limit) .",0"
00428 : '';
00429
00430
00431 require_once(confGet('DIR_STREBER') . 'db/class_comment.inc.php');
00432 $dbh = new DB_Mysql;
00433
00434 $str_is_alive= $alive_only
00435 ? 'AND i.state=' . ITEM_STATE_OK
00436 : '';
00437
00438 if($visible_only) {
00439 $str_query=
00440 "SELECT i.*, c.* from {$prefix}item i, {$prefix}comment c, {$prefix}projectperson upp
00441 WHERE
00442 upp.person = {$auth->cur_user->id}
00443 AND upp.project = $this->id
00444 AND upp.state = 1
00445
00446 AND i.type = '".ITEM_COMMENT."'
00447 AND i.project = $this->id
00448 $str_is_alive
00449 AND ( i.pub_level >= upp.level_view
00450 OR
00451 i.created_by = {$auth->cur_user->id}
00452 )
00453
00454 AND c.id = i.id
00455 $str_parent_task
00456
00457 ". getOrderByString($order_by, 'i.created') ."
00458 $str_limit";
00459
00460 }
00461 else {
00462 $str_query=
00463 "SELECT i.*, c.* from {$prefix}item i, {$prefix}comment c
00464 WHERE
00465 i.type = '".ITEM_COMMENT."'
00466 AND i.project = $this->id
00467 $str_is_alive
00468
00469 AND c.id = i.id
00470 $str_parent_task
00471
00472 ". getOrderByString($order_by, 'i.created') ."
00473 $str_limit";
00474
00475 }
00476
00477 $sth= $dbh->prepare($str_query);
00478 $sth->execute("",1);
00479 $tmp=$sth->fetchall_assoc();
00480 $comments=array();
00481 foreach($tmp as $n) {
00482 $comment=new Comment($n);
00483 $comments[]= $comment;
00484 }
00485
00486 ### sort hierarchical ###
00487
00497 $dict_id_comment=array();
00498
00499 $dummy= new Comment(array(
00500 'id'=> 0
00501
00502 ));
00503 $dict_id_dict=array(); # zero id item as root
00504
00505 ### 1st pass: build dict for all ids ###
00506 foreach($comments as $c) {
00507 $c->children= array(1=>2);
00508 $dict_id_dict[$c->id] = $c;
00509 $dict_id_dict[$c->id]->children = array();
00510
00511 }
00512
00513 ### 2nd pass: build up tree structure ###
00514 foreach($dict_id_dict as $id=>$c) {
00515 if(isset($dict_id_dict[$c->comment])) {
00516 $dict_id_dict[$c->comment]->children[$c->id]= $c;
00517 }
00518 else {
00519 $dict_id_dict[0]->children[$c->id]= $c;
00520 }
00521 }
00522
00523 ### 3rd pass: roll out tree
00524 $list=array();
00525 if(isset($dict_id_dict[0]->children)) {
00526 foreach($dict_id_dict[0]->children as $c) {
00527 sortObjectsRecursively(&$c, &$list);
00528 }
00529 }
00530 return $list;
00531 }
00532
00533
00534
00535
00539 function &getIssues($order_by=NULL, $visible_only=true, $alive_only=true){
00540
00541 global $auth;
00542 $prefix= confGet('DB_TABLE_PREFIX');
00543
00544
00545 require_once(confGet('DIR_STREBER') . 'db/class_issue.inc.php');
00546 $dbh = new DB_Mysql;
00547
00548 $str_is_alive= $alive_only
00549 ? 'AND state=' . ITEM_STATE_OK
00550 : '';
00551
00552
00553 if($visible_only) {
00554 $str_query=
00555 "SELECT i.*, iss.* from {$prefix}item i, {$prefix}issue iss, {$prefix}projectperson upp
00556 WHERE
00557 upp.person = {$auth->cur_user->id}
00558 AND upp.project = $this->id
00559 AND upp.state = 1
00560
00561 AND i.type = '".ITEM_ISSUE."'
00562 AND i.project = $this->id
00563 $str_is_alive
00564
00565 AND ( i.pub_level >= upp.level_view
00566 OR
00567 i.created_by = {$auth->cur_user->id}
00568 )
00569
00570 AND iss.id = i.id
00571
00572 ". getOrderByString($order_by, 'iss.id')
00573 ;
00574 }
00575 else {
00576 $str_query=
00577 "SELECT i.*, iss.* from {$prefix}item i, {$prefix}issue iss
00578 WHERE
00579 i.type = '".ITEM_ISSUE."'
00580 AND i.project = $this->id
00581 $str_is_alive
00582
00583 AND iss.id = i.id
00584
00585 ". getOrderByString($order_by, 'iss.id')
00586 ;
00587 }
00588
00589
00590 $sth= $dbh->prepare($str_query);
00591 $sth->execute("",1);
00592 $tmp=$sth->fetchall_assoc();
00593 $issues=array();
00594 foreach($tmp as $n) {
00595 $i=new Issue($n);
00596 $issues[]= $i;
00597 }
00598 return $issues;
00599 }
00600
00604 private function &getVisibleTeam() {
00605 $a= array();
00606 $persons= $this->getPersons();
00607 foreach($persons as $p) {
00608 if($p->id) {
00609 $a[floor($p->id)] = $p;
00610 }
00611 }
00612 return $a;
00613 }
00614
00618 function isPersonVisibleTeamMember($person_or_id) {
00619
00623 if(!isset($this->_visible_team)) {
00624 $this->_visible_team= $this->getVisibleTeam();
00625 }
00626 if(is_object($person_or_id)) {
00627 return isset($this->_visible_team[$person_or_id->id]);
00628 }
00629 else {
00630 return isset($this->_visible_team[$person_or_id]);
00631 }
00632 }
00633
00645 function getVisiblePersonById($id) {
00646 $p=Person::getById($id);
00647 if($p->id && $this->isPersonVisibleTeamMember($p->id)) {
00648 return $p;
00649 }
00650 return NULL;
00651 }
00652
00653
00659 function &getProjectPersons($args=NULL)
00660 {
00661 global $auth;
00662 $prefix = confGet('DB_TABLE_PREFIX');
00663
00664 ### default parameter ###
00665 $order_by=NULL;
00666 $alive_only=true;
00667 $visible_only=true;
00668 $person_id = NULL;
00669
00670 ### filter parameter ###
00671 if($args) {
00672 foreach($args as $key=>$value) {
00673 if(!isset($$key) && !is_null($$key) && !$$key==="") {
00674 trigger_error("unknown parameter",E_USER_NOTICE);
00675 }
00676 else {
00677 $$key= $value;
00678 }
00679 }
00680 }
00681
00682 $s_alive_only= $alive_only
00683 ? "AND i.state=1"
00684 : "";
00685
00686 $s_person = $person_id
00687 ? "AND person.id = " . $person_id
00688 : "";
00689
00690 ### all users ###
00691 if($auth->cur_user->user_rights & RIGHT_PROJECT_ASSIGN) {
00692 $s_query=
00693 "SELECT i.*, pp.* from {$prefix}item i, {$prefix}projectperson pp, {$prefix}person person
00694 WHERE
00695 i.type = '".ITEM_PROJECTPERSON."'
00696 AND i.project = $this->id
00697 $s_alive_only
00698 AND pp.id = i.id
00699 AND person.id = pp.person
00700 $s_person
00701 ". getOrderByString($order_by, 'person.name')
00702 ;
00703 }
00704 ### only visibile for current user ###
00705 elseif($visible_only) {
00706 $s_query=
00707 "SELECT i.*, pp.* from {$prefix}item i, {$prefix}projectperson pp, {$prefix}projectperson upp, {$prefix}person person
00708 WHERE
00709 upp.person = {$auth->cur_user->id}
00710 AND upp.project = $this->id
00711 AND upp.state = 1
00712
00713 AND i.type = '".ITEM_PROJECTPERSON."'
00714 AND i.project = $this->id
00715 $s_alive_only
00716 AND pp.id = i.id
00717 AND (
00718 i.pub_level >= upp.level_view
00719 OR
00720 i.created_by = {$auth->cur_user->id}
00721 OR
00722 pp.person = {$auth->cur_user->id}
00723 )
00724 AND person.id = pp.person
00725 $s_person
00726 ". getOrderByString($order_by, 'person.name')
00727 ;
00728 }
00729
00730 ### all including deleted ###
00731 else {
00732 $s_query=
00733 "SELECT i.*, pp.* from {$prefix}item i, {$prefix}projectperson pp, {$prefix}person person
00734 WHERE
00735 i.type = '".ITEM_PROJECTPERSON."'
00736 AND i.project = $this->id
00737 $s_alive_only
00738 AND i.id = pp.id
00739 AND person.id = pp.person
00740 $s_person
00741 ". getOrderByString($order_by, 'person.name')
00742 ;
00743 }
00744 require_once(confGet('DIR_STREBER') . 'db/class_projectperson.inc.php');
00745
00746 $dbh = new DB_Mysql;
00747
00748
00749 $sth= $dbh->prepare($s_query);
00750 $sth->execute("",1);
00751
00752 $tmp=$sth->fetchall_assoc();
00753 $ppersons=array();
00754 foreach($tmp as $n) {
00755 $pperson=new ProjectPerson($n);
00756 $ppersons[]= $pperson;
00757 }
00758
00759 return $ppersons;
00760 }
00761
00762
00851 function &getPersons($visible_only=true)
00852 {
00853 $ppersons= $this->getProjectPersons(NULL, true, $visible_only);
00854 $persons= array();
00855 foreach($ppersons as $pp) {
00856 if($p= Person::getById($pp->person)) {
00857 $persons[]= $p;
00858 }
00859 }
00860 return $persons;
00861 }
00862
00863
00864
00865
00869 public function getLink($show_shortname=true) {
00870 global $PH;
00871 if($show_shortname) {
00872 return '<span class="item project">'.$PH->getLink('projView',$this->getShort(),array('prj'=>$this->id)).'</span>';
00873 }
00874 else {
00875 return '<span class="item project">'.$PH->getLink('projView',$this->name,array('prj'=>$this->id)).'</span>';
00876 }
00877 }
00878
00879
00883 function getCompanyLink($show_long=false)
00884 {
00885 global $PH;
00886 if(!$this->company) {
00887 return "";
00888 }
00889 require_once(confGet('DIR_STREBER') . 'db/class_company.inc.php');
00890 if($company= Company::getVisibleById($this->company)) {
00891 return $company->getLink($show_long);
00892 }
00893 else {
00894 return "-";
00895 }
00896 }
00897
00901 static function &queryFromDb($query_string)
00902 {
00903 $dbh = new DB_Mysql;
00904
00905 $sth= $dbh->prepare($query_string);
00906
00907 $sth->execute("",1);
00908 $tmp=$sth->fetchall_assoc();
00909 $projects=array();
00910 foreach($tmp as $t) {
00911 $project=new Project($t);
00912 $projects[]=$project;
00913 }
00914 return $projects;
00915 }
00916
00917
00918
00919
00923 public static function &getAll($args=NULL)
00924 {
00925 global $auth;
00926 $prefix= confGet('DB_TABLE_PREFIX');
00927
00928
00929 if($args && !is_array($args)) {
00930 trigger_error("requires array as parameter", E_USER_WARNING);
00931 return;
00932 }
00933
00934 ### default params ###
00935 $order_by= "prio, name";
00936 $status_min= STATUS_UNDEFINED;
00937 $status_max= STATUS_OPEN;
00938 $company= NULL;
00939 $visible_only= ($auth->cur_user->user_rights & RIGHT_VIEWALL)
00940 ? false
00941 : true;
00942 $search= NULL;
00943 $id= NULL;
00944
00945
00946 ### filter params ###
00947 if($args) {
00948 foreach($args as $key=>$value) {
00949 if(!isset($$key) && !is_null($$key) && !$$key==="") {
00950 trigger_error("unknown parameter",E_USER_NOTICE);
00951 }
00952 else {
00953 $$key= $value;
00954 }
00955 }
00956 }
00957
00958 $AND_id = $id
00959 ? 'AND p.id=' . intval($id)
00960 : '';
00961
00962 $AND_match= $search
00963 ? "AND (MATCH (p.name,p.status_summary,p.description) AGAINST ('" . asCleanString($search) . "*' IN BOOLEAN MODE))"
00964 : '';
00965
00966 if(!is_null($company)) {
00967 $AND_company= $company
00968 ? 'AND p.company=' . intval($company)
00969 : '';
00970 }
00971 else {
00972 $AND_company= "";
00973 }
00974
00979 ### only assigned projects ###
00980 if($visible_only) {
00981 $str=
00982 "SELECT DISTINCT i.*, p.* from {$prefix}item i, {$prefix}projectperson upp, {$prefix}project p left join {$prefix}company c on p.company = c.id
00983 WHERE
00984 upp.person = '{$auth->cur_user->id}'
00985 AND upp.state = 1
00986
00987 AND upp.project = p.id
00988
00989 AND p.status <= ". intval($status_max) ."
00990 AND p.status >= ". intval($status_min) ."
00991 AND p.state = 1
00992 AND i.id = p.id
00993 AND (p.company = c.id OR p.company = 0)
00994 $AND_company
00995 $AND_match
00996 $AND_id
00997 ". getOrderByString($order_by) ;
00998 }
00999 ### all projects ###
01000 else {
01001 $str=
01002 "SELECT DISTINCT i.*, p.* from {$prefix}item i, {$prefix}project p left join {$prefix}company c on p.company = c.id
01003
01004 WHERE
01005 p.status <= ".intval($status_max)."
01006 AND p.status >= ".intval($status_min)."
01007 AND p.state = 1
01008 AND i.id = p.id
01009 AND (p.company = 0 OR p.company = c.id)
01010 $AND_company
01011 $AND_match
01012 $AND_id
01013 ". getOrderByString($order_by) ;
01014 }
01015
01016 $projects = self::queryFromDb($str);
01017 return $projects;
01018 }
01019
01020
01021
01025 public static function getActive($order_by=NULL)
01026 {
01027 if($order_by && !is_string($order_by)) {
01028 trigger_error("requires string", E_USER_WARNING);
01029 return;
01030 }
01031 return self::getAll(array(
01032 'order_by' => $order_by,
01033 ));
01034 }
01035
01036 public static function getClosed($order_by=NULL){
01037 if($order_by && !is_string($order_by)) {
01038 trigger_error("requires string", E_USER_WARNING);
01039 return;
01040 }
01041 return self::getAll(array(
01042 'order_by' => $order_by,
01043 'status_min'=> STATUS_BLOCKED,
01044 'status_max'=> STATUS_CLOSED,
01045 ));
01046 }
01047 public static function getTemplates($order_by=NULL){
01048 if($order_by && !is_string($order_by)) {
01049 trigger_error("requires string", E_USER_WARNING);
01050 return;
01051 }
01052 return self::getAll(array(
01053 'order_by' => $order_by,
01054 'status_min'=> STATUS_TEMPLATE,
01055 'status_max'=> STATUS_TEMPLATE,
01056 ));
01057 }
01058
01064 function &getCurrentProjectPerson()
01065 {
01066 global $auth;
01067 $prefix= confGet('DB_TABLE_PREFIX');
01068
01069 require_once(confGet('DIR_STREBER') . 'db/class_projectperson.inc.php');
01070 $dbh = new DB_Mysql;
01071 $sth= $dbh->prepare(
01072 "SELECT i.*, pp.* from {$prefix}item i, {$prefix}projectperson pp
01073 WHERE
01074 pp.person = {$auth->cur_user->id}
01075 AND pp.project = $this->id
01076 AND pp.state = 1
01077
01078 AND i.id = pp.id
01079 AND i.state = 1
01080 AND i.type = '".ITEM_PROJECTPERSON."'"
01081
01082 );
01083 $sth->execute("",1);
01084 $tmp=$sth->fetchall_assoc();
01085 $ppersons=array();
01086 foreach($tmp as $n) {
01087 $pperson=new ProjectPerson($n);
01088 $ppersons[]= $pperson;
01089 }
01090 if(count($ppersons) >1 ){
01091 trigger_error("internal error: person assigned twice to project",E_USER_WARNING);
01092
01093 $tmp_null=NULL;
01094 return $tmp_null; # only var-refs can be returned
01095 }
01096 else if (!$ppersons) {
01100 #trigger_error("internal error: person is not assigned to project",E_USER_WARNING);
01101 $tmp_null=NULL;
01102 return $tmp_null; # only var-refs might be returned
01103 }
01104 return $ppersons[0];
01105 }
01106
01112 public function getCurrentLevelCreate()
01113 {
01114 global $PH;
01115 if(!$pp= $this->getCurrentProjectPerson()) {
01119 $PH->abortWarning(__('only team members can create items'),ERROR_RIGHTS); ## user may never have reached this point
01120
01121 }
01122 $new_level= $this->default_pub_level;
01123 if($new_level > $pp->level_create) {
01124 $new_level = $pp->level_create;
01125 }
01126 return $new_level;
01127
01128 }
01129
01137 public function validateViewItem($item=NULL, $abort_on_error=false)
01138 {
01139 global $PH;
01140 global $auth;
01141
01142 if(!$item) {
01143 if($abort_on_error) {
01144 $PH->abortWarning(__("validating invalid item"),ERROR_BUG);
01145 exit();
01146 }
01147 return false;
01148 }
01149
01150 if($auth->cur_user->user_rights & RIGHT_EDITALL) {
01151 return true;
01152 }
01153 if($auth->cur_user->user_rights & RIGHT_VIEWALL) {
01154 return true;
01155 }
01156
01157 if(!$pp= $this->getCurrentProjectPerson()) {
01158 if($abort_on_error) {
01159 $PH->abortWarning(__("insuffient rights (not in project)"),ERROR_RIGHTS);
01160 exit();
01161 }
01162 return false;
01163 }
01164
01165 $l= $item->pub_level;
01166 if($item->created_by == $pp->person) {
01167 $l= PUB_LEVEL_OWNED;
01168 }
01169 # \TODO check different items-types here...
01170 if($l < $pp->level_view) {
01171 if($abort_on_error) {
01172 $PH->abortWarning(__("insuffient rights"),ERROR_RIGHTS);
01173 exit();
01174 }
01175 return false;
01176 }
01177 return true;
01178 }
01179
01180
01189 public function validateEditItem($item=NULL, $abort_on_error=true)
01190 {
01191 global $PH;
01192 global $auth;
01193
01194 if(!$item) {
01195 if($abort_on_error) {
01196 $PH->abortWarning(__("validating invalid item"),ERROR_BUG);
01197 exit();
01198 }
01199 return false;
01200 }
01201
01202 if($auth->cur_user->user_rights & RIGHT_EDITALL) {
01203 return true;
01204 }
01205
01206 if(!$pp= $this->getCurrentProjectPerson()) {
01207 if($abort_on_error) {
01208 $PH->abortWarning(__("insuffient rights (not in project)"),ERROR_RIGHTS);
01209 exit();
01210 }
01211 return false;
01212 }
01213
01214
01215 $l= $item->pub_level;
01216 if($item->created_by == $pp->person) {
01217 $l= PUB_LEVEL_OWNED;
01218 }
01219
01220 # \TODO check different items-types here...
01221 if($item->id != 0 && $l < $pp->level_edit) {
01222 if($abort_on_error) {
01223 $PH->abortWarning(__("insuffient rights"),ERROR_RIGHTS);
01224 exit();
01225 }
01226 return false;
01227 }
01228 return true;
01229
01230 }
01231
01232
01236 public function validateView($status_min=STATUS_UPCOMING, $status_max=STATUS_APPROVED, $abort_page=true, $for_person=NULL)
01237 {
01238 if(!$for_person) {
01239 global $auth;
01240 $for_person= $auth->cur_user;
01241 }
01242 global $PH;
01243 $prefix= confGet('DB_TABLE_PREFIX');
01244
01245 ### all projects ###
01246 if($for_person->user_rights & RIGHT_VIEWALL) {
01247 return true;
01248 }
01249
01250 $str=
01251 "SELECT p.* from {$prefix}project p, {$prefix}projectperson upp
01252 WHERE
01253 upp.person = {$for_person->id}
01254 AND upp.state = 1
01255
01256 AND upp.project = p.id
01257 AND p.id = $this->id
01258 AND p.status <= ".intval($status_max)."
01259 AND p.status >= ".intval($status_min)."
01260 AND p.state = 1
01261 ";
01262
01263 $projects= self::queryFromDb($str);
01264
01265 if(count($projects) == 1) {
01266 return true;
01267 }
01268 else if($abort_page) {
01269 $PH->abortWarning(__("insuffient rights"),ERROR_RIGHTS);
01270 }
01271 return NULL;
01272 }
01273
01277 public function delete() {
01278
01279 #--- first delete all tasks ---
01280 foreach($this->getTasks() as $t) {
01281 $t->delete();
01282 }
01283
01284 #--- delete myself ---
01285 return parent::delete();
01286 }
01287
01288
01289
01293 public function getStatusType()
01294 {
01295 if($this->status == STATUS_TEMPLATE) {
01296 return __("Project Template");
01297 }
01298 else if ($this->status >= STATUS_COMPLETED){
01299 return __("Inactive Project");
01300 }
01301 else {
01302 return __("Project","Page Type");
01303 }
01304 }
01305
01306
01307
01308 public function getNextMilestone()
01309 {
01310 global $auth;
01311 $prefix= confGet('DB_TABLE_PREFIX');
01312
01313 $dbh = new DB_Mysql;
01314 $sth= $dbh->prepare(
01315 "SELECT i.id
01316 from {$prefix}item i, {$prefix}task t
01317 WHERE
01318 t.is_milestone=1
01319 AND t.id= i.id
01320 AND i.state = '".ITEM_STATE_OK."'
01321 AND i.project= $this->id
01322 AND t.status < ". STATUS_COMPLETED ."
01323 ORDER BY t.name, t.id
01324 "
01325 )->execute();
01326 $tmp=$sth->fetchall_assoc();
01327 if($tmp) {
01328 $tmp_values=array_values($tmp[0]);
01329 $next_milestone= Task::getVisibleById($tmp_values[0]);
01330 return $next_milestone;
01331 }
01332 else {
01333 return false;
01334 }
01335 }
01336 }
01337
01338 Project::initFields();
01339
01340
01341 function cmp_comments($a,$b) {
01342 if($a->path < $b->path) {
01343 return -1;
01344 }
01345 else if($a->path > $b->path) {
01346 return 1;
01347 }
01348 return 0;
01349 }
01350
01351
01352 ?>