<?php if(!function_exists('startedIndexPhp')) { header("location:../index.php"); exit();}
# streber - a php5 based project management system (c) 2005-2007 / www.streber-pm.org
# Distributed under the terms and conditions of the GPL as stated in lang/license.html
/**\file pages for working with tasks */
require_once(confGet('DIR_STREBER') . 'db/class_issue.inc.php');
require_once(confGet('DIR_STREBER') . 'db/class_task.inc.php');
require_once(confGet('DIR_STREBER') . 'db/class_project.inc.php');
require_once(confGet('DIR_STREBER') . 'render/render_list.inc.php');
require_once(confGet('DIR_STREBER') . 'lists/list_taskfolders.inc.php');
require_once(confGet('DIR_STREBER') . 'lists/list_comments.inc.php');
require_once(confGet('DIR_STREBER') . 'lists/list_tasks.inc.php');
require_once(confGet('DIR_STREBER') . 'db/class_taskperson.inc.php');
require_once(confGet('DIR_STREBER') . 'db/class_effort.inc.php');
require_once(confGet('DIR_STREBER') . 'db/class_person.inc.php');
require_once(confGet('DIR_STREBER') . 'db/db_itemperson.inc.php');
/**
* Create a task as bug
*
* @ingroup pages
*/
function taskNewBug()
{
$foo=array(
'add_issue'=>1,
'task_category' =>TCATEGORY_BUG
);
addRequestVars($foo);
TaskNew();
exit();
}
/**
* Create a task as docu page
*
* @ingroup pages
*/
function taskNewDocu()
{
$foo=array(
'task_category' =>TCATEGORY_DOCU,
'show_folder_as_documentation' => 1,
);
addRequestVars($foo);
TaskNew();
exit();
}
/**
* Create a new milestone
*
* @ingroup pages
*/
function TaskNewMilestone()
{
global $PH;
$prj_id=getOnePassedId('prj','',true,__('No project selected?')); # aborts with error if not found
if(!$project= Project::getVisibleById($prj_id)) {
$PH->abortWarning("invalid project-id",ERROR_FATAL);
}
### build dummy form ###
$newtask= new Task(array(
'id' =>0,
'name' =>__("New Milestone"),
'project' =>$prj_id,
'category' =>TCATEGORY_MILESTONE,
'status' =>STATUS_OPEN,
)
);
$PH->show('taskEdit',array('tsk'=>$newtask->id),$newtask);
}
/**
* Create a task as Version
*
* @ingroup pages
*/
function TaskNewVersion()
{
global $PH;
$prj_id=getOnePassedId('prj','',true,__('No project selected?')); # aborts with error if not found
if(!$project= Project::getVisibleById($prj_id)) {
$PH->abortWarning("invalid project-id",ERROR_FATAL);
}
### build dummy form ###
$newtask= new Task(array(
'id' => 0,
'name' => __("New Version"),
'project' => $prj_id,
'status' => STATUS_APPROVED,
'completion' => 100,
'category' =>TCATEGORY_VERSION,
'is_released' => RELEASED_PUBLIC,
'time_released' => getGMTString(),
)
);
$PH->show('taskEdit',array('tsk'=>$newtask->id),$newtask);
}
/**
* create new folder
*
* @ingroup pages
*/
function TaskNewFolder()
{
global $PH;
$prj_id=getOnePassedId('prj','',true,__('No project selected?')); # aborts with error if not found
if(!$project= Project::getVisibleById($prj_id)) {
$PH->abortWarning("invalid project-id",ERROR_FATAL);
}
### for milestone ###
if( $milestone= Task::getVisibleById(get('for_milestone'))) {
$for_milestone= $milestone->id;
}
else {
$for_milestone= 0;
}
### get id of parent_task
$parent_task_id=0;
{
$task_ids= GetPassedIds('parent_task','folders_*'); # aborts with error if not found
if(count($task_ids) >= 1) {
$parent_task_id= $task_ids[0];
}
}
### build dummy form ###
$newtask= new Task(array(
'id' =>0,
'name' =>__("New folder"),
'project' =>$prj_id,
'is_folder' =>1, #@@@ depreciated!
'category' =>TCATEGORY_FOLDER,
'parent_task'=>$parent_task_id,
'for_milestone'=>$for_milestone,
)
);
$PH->show('taskEdit',array('tsk'=>$newtask->id),$newtask);
}
/**
* start taskEdit-form with a new task
* - figure out prio,label and estimated time from name
*
* @ingroup pages
*/
function TaskNew()
{
global $PH;
$parent_task = NULL;
$parent_task_id =0;
### try to figure out parent_task ###
if($task_ids=getPassedIds('parent_task','tasks_*|folders_*',false)) {
if(count($task_ids) != 1) {
$PH->abortWarning(__("Please select only one item as parent"),ERROR_NOTE);
}
if($task_ids[0] != 0) {
if(!$parent_task = Task::getVisibleById($task_ids[0])) {
$PH->abortWarning(__("Insufficient rights for parent item."),ERROR_NOTE);
}
$parent_task_id= $parent_task->id;
}
else {
$parent_task_id= 0;
}
}
else {
$parent_task_id= 0;
}
### figure out project ###
$prj_id= getOnePassedId('prj','projects_*',false); # NOT aborts with error if not found
if(!$prj_id) {
if(!$parent_task) {
$PH->abortWarning(__("could not find project"),ERROR_NOTE);
}
$prj_id= $parent_task->project;
}
if(!$project= Project::getVisibleById($prj_id)) {
$PH->abortWarning(__("could not find project"),ERROR_NOTE);
}
### make sure parent_task is valid ###
if($parent_task_id && !$parent_task = Task::getVisibleById($parent_task_id)) {
$PH->abortWarning(__("Parent task not found."), ERROR_NOTE);
}
$name= html_entity_decode(get('new_name')); # @@@ hack to get rid of slashed strings
$estimated='00:00:00';
### for milestone ###
$for_milestone_id= 0;
if( $milestone= Task::getVisibleById(get('for_milestone'))) {
$for_milestone_id= $milestone->id;
}
### if parent-task is milestone for some reason, avoid parenting ###
if($parent_task && ($parent_task->category == TCATEGORY_MILESTONE || $parent_task->category == TCATEGORY_VERSION)) {
$parent_task_id=0;
if(!$for_milestone_id) {
$for_milestone_id= $parent_task->id;
}
}
### category ###
$category= TCATEGORY_TASK;
if(!is_null($cat= get('task_category'))) {
global $g_tcategory_names;
if(!isset($g_tcategory_names[$cat])) {
$category= TCATEGORY_TASK;
}
else {
$category= $cat;
}
}
$folder_as_docu= get('task_show_folder_as_documentation',
($category == TCATEGORY_DOCU) ? 1 : 0);
### build dummy form ###
$newtask= new Task(array(
'id' =>0,
'name' =>$name,
'project' =>$prj_id,
'state' =>1,
'estimated' =>$estimated,
'category' =>$category,
'parent_task'=>$parent_task_id,
'for_milestone'=>$for_milestone_id,
'show_folder_as_documentation' =>intval($folder_as_docu)
));
### set a valid create-level ###
$newtask->pub_level= $project->getCurrentLevelCreate();
### insert without editing ###
if((get('noedit'))) {
$newtask->insert();
if(!$PH->showFromPage()) {
$PH->show('projView',array('prj'=>$prj));
}
}
### pass newobject to edit-page ###
else {
$PH->show('taskEdit',array('tsk'=>$newtask->id),$newtask);
}
}
/**
* Edit a task
*
* @ingroup pages
*/
function taskEdit($task=NULL)
{
global $PH;
### object or from database? ###
if(!$task) {
$ids= getPassedIds('tsk','tasks_*');
if(!$ids) {
$PH->abortWarning(__("Select some task(s) to edit"), ERROR_NOTE);
return;
}
else if(count($ids) > 1) {
$PH->show('taskEditMultiple');
exit();
}
else if(!$task= Task::getEditableById($ids[0])) {
$PH->abortWarning(__("You do not have enough rights to edit this task"), ERROR_RIGHTS);
}
}
### get parent project ####
if(!$project= Project::getVisibleById($task->project)) {
$PH->abortWarning("FATAL error! parent project not found");
}
### abort, if not enough rights ###
#$project->validateEditItem($task);
### set up page and write header ####
{
$page= new Page(array('use_jscalendar'=>true,'autofocus_field'=>'task_name'));
initPageForTask($page, $task, $project);
if($task->id) {
$page->title=$task->name;
$page->title_minor=$task->short;
}
else {
if($task->category == TCATEGORY_MILESTONE) {
$page->title=__("New milestone");
}
else if($task->category == TCATEGORY_VERSION) {
$page->title=__("New version");
}
else if($task->category == TCATEGORY_DOCU) {
$page->title=__("New topic");
}
else if($task->category == TCATEGORY_FOLDER) {
$page->title=__("New folder");
}
else {
$page->title=__("New task");
if($task->parent_task && $parent_task= Task::getVisibleById($task->parent_task)) {
$page->title_minor= sprintf(__('for %s','e.g. new task for something'), $parent_task->name);
}
}
}
echo(new PageHeader);
}
echo (new PageContentOpen);
### write form #####
{
require_once(confGet('DIR_STREBER') . 'render/render_form.inc.php');
global $auth;
global $REPRODUCIBILITY_VALUES;
global $g_prio_names;
global $g_status_names;
$block=new PageBlock(array(
#'title' =>__('Edit Task'),
'id' =>'functions',
));
$block->render_blockStart();
$form=new PageForm();
$form->button_cancel=true;
$form->add($task->fields['name']->getFormElement(&$task));
### task category ###
{
$list= array();
if($task->category == TCATEGORY_MILESTONE || $task->category == TCATEGORY_VERSION) {
$list= array(TCATEGORY_MILESTONE, TCATEGORY_VERSION);
### make sure it's valid
if($task->category != TCATEGORY_MILESTONE || $task->category != TCATEGORY_VERSION) {
if($task->is_released > RELEASED_UPCOMMING) {
$task->category= TCATEGORY_VERSION;
}
else {
$task->category= TCATEGORY_MILESTONE;
}
}
}
else {
$list=array();
if($project->settings & PROJECT_SETTING_ENABLE_TASKS) {
$list[]= TCATEGORY_TASK;
}
if($project->settings & PROJECT_SETTING_ENABLE_BUGS) {
$list[]= TCATEGORY_BUG;
}
$list[]= TCATEGORY_DOCU;
$list[]= TCATEGORY_FOLDER;
}
global $g_tcategory_names;
$cats= array();
foreach($list as $c) {
$cats[$c]= $g_tcategory_names[$c];
}
$form->add(new Form_Dropdown('task_category', __("Display as"),array_flip($cats),$task->category));
### warning if folder with subtasks ###
if($task->id && $task->category == TCATEGORY_FOLDER && ($num_subtasks= count($task->getSubtasks()))) {
$form->add(new Form_CustomHtml('<p><label></label>'. sprintf(__("This folder has %s subtasks. Changing category will ungroup them."), $num_subtasks) . '</p>'));
}
}
$form->add($tab_group= new Page_TabGroup());
### task attributes ###
{
$tab_group->add($tab= new Page_Tab('task', __("Task")));
### normaltasks and folders ##
if(!$task->isMilestoneOrVersion()) {
if($project->settings & PROJECT_SETTING_ENABLE_MILESTONES) {
$tab->add( new Form_DropdownGrouped('task_for_milestone',
__('For Milestone'),
$project->buildPlannedForMilestoneList(),
$task->for_milestone
));
}
### prio ###
if($task->category != TCATEGORY_MILESTONE && $task->category != TCATEGORY_VERSION) {
$tab->add(new Form_Dropdown('task_prio', __("Prio","Form label"), array_flip($g_prio_names), $task->prio));
}
}
### assigned to ###
{
### for existing tasks, get already assigned
if($task->id) {
$assigned_persons = $task->getAssignedPersons();
#$task_assignments = $task->getAssignments();
}
### for new tasks get the assignments from parent task ###
/**
* Some notes on assigning persons
*
* Passing this information is tricky because:
* - multiple persons could be assigned to a task
* - task-assignments for new tasks can't be stored to database until the task
* has finally been validated and stored itself. Therefore this information has
* to be passed in hiddenfields named "task_assign_to_#" whereas # is an integer counting
* up from 0.
* - additionally all persons have to be checked for visibility and if they are already
* assigned to this task.
*
* To automatically assign new tasks to persons there are two possibilites:
* 1. pass 'task_assign_to_#" - parameters
* 2. pass 'parent_task' - parameter which is been assigned to a person
*
* The first options beats the second.
*/
else {
### check new assigments ###
$count=0;
while($id_new= get('task_assign_to_'.$count)) {
$count++;
### check if already assigned ###
if($p= Person::getVisibleById($id_new)) {
$assigned_persons[]= $p;
}
}
if(!$count) {
$parents= $task->getFolder();
if($parents) {
$parents= array_reverse($parents);
foreach($parents as $p) {
if($ap= $p->getAssignedPersons()) {
$assigned_persons= $ap;
break;
}
}
}
}
}
$team=array(__('- select person -')=>0);
### create team-list ###
foreach($project->getPersons() as $p) {
$team[$p->name]= $p->id;
}
### create drop-down-lists ###
$count_new=0;
$count_all=0;
if(isset($assigned_persons)) {
foreach($assigned_persons as $ap) {
if(!$p= Person::getVisibleById($ap->id)) {
continue; # skip if invalid person
}
if($task->id) {
$tab->add(new Form_Dropdown('task_assigned_to_'.$ap->id, __("Assigned to"),$team, $ap->id));
}
else {
$tab->add(new Form_Dropdown('task_assign_to_'.$count_new, __("Assign to"),$team, $ap->id));
$count_new++;
}
$count_all++;
unset($team[$ap->name]);
}
}
### add empty drop-downlist for new assignments ###
$str_label = ($count_all == 0)
? __("Assign to","Form label")
: __("Also assign to","Form label");
$tab->add(new Form_Dropdown("task_assign_to_$count_new", $str_label,$team, 0));
}
### completion ###
if(!$task->is_released > RELEASED_UPCOMMING) {
#$form->add($task->fields['estimated' ]->getFormElement(&$task));
$ar= array(
__('undefined')=> -1,
'0%' => 0,
'10%' => 10,
'20%' => 20,
'30%' => 30,
'40%' => 40,
'50%' => 50,
'60%' => 60,
'70%' => 70,
'80%' => 80,
'90%' => 90,
'95%' => 95,
'98%' => 98,
'99%' => 99,
'100%' => 100,
);
$tab->add(new Form_Dropdown('task_completion',__("Completed"),$ar, $task->completion));
}
### status ###
{
$st=array();
foreach($g_status_names as $s=>$n) {
if($s >= STATUS_NEW) {
$st[$s]=$n;
}
}
if($task->isMilestoneOrVersion()) {
unset($st[STATUS_NEW]);
}
$field_status=new Form_Dropdown('task_status',"Status",array_flip($st), $task->status);
if($task->fields['status']->invalid) {
$field_status->invalid= true;
}
$tab->add($field_status);
}
if(!$task->isMilestoneOrVersion()) {
if($project->settings & PROJECT_SETTING_ENABLE_MILESTONES) {
### resolved version ###
$tab->add(new Form_DropdownGrouped('task_resolved_version', __('Resolved in'), $project->buildResolvedInList(), $task->resolved_version));
}
### resolved reason ###
global $g_resolve_reason_names;
$tab->add(new Form_Dropdown('task_resolve_reason', __('Resolve reason'),array_flip($g_resolve_reason_names), $task->resolve_reason));
}
}
### bug report ###
{
$tab_group->add($tab= new Page_Tab("bug",__("Bug Report")));
### use issue-report ###
global $g_severity_names;
global $g_reproducibility_names;
### create new one ###
if($task->issue_report <= 0) {
$issue= new Issue(array('id'=>0));
### get recent issue-reports ###
if($recent_ir=Issue::getCreatedRecently()) {
$default_version='';
$default_plattform='';
$default_production_build='';
$default_os='';
foreach($recent_ir as $ir){
if($ir->project == $project->id) {
if(!$issue->version && $ir->version) {
$issue->version= $ir->version;
}
if(! $issue->plattform && $ir->plattform) {
$issue->plattform= $ir->plattform;
}
if(! $issue->os && $ir->os) {
$issue->os= $ir->os;
}
if(! $issue->production_build && $ir->production_build) {
$issue->production_build= $ir->production_build;
}
}
}
}
}
else {
/**
* note: if task is visible ignore visibility of issue report
*/
$issue= Issue::getById($task->issue_report);
}
if($issue) {
$tab->add(new Form_Dropdown('issue_severity', __("Severity","Form label, attribute of issue-reports"), array_flip($g_severity_names), $issue->severity));
$tab->add(new Form_Dropdown('issue_reproducibility',__("Reproducibility","Form label, attribute of issue-reports"), array_flip($g_reproducibility_names), $issue->reproducibility));
foreach($issue->fields as $field) {
$tab->add($field->getFormElement(&$issue));
}
$tab->add(new Form_HiddenField('task_issue_report','',$task->issue_report));
}
else {
trigger_error("could not get Issue with id ($task->issue-report)", E_USER_NOTICE);
}
}
### timing ###
{
$tab_group->add($tab= new Page_Tab("timing",__("Timing")));
### estimated ###
if(!$task->isMilestoneOrVersion()){
#$tab->add($task->fields['estimated' ]->getFormElement(&$task));
$ar= array(
__('undefined')=> 0,
__('30 min') => 30*60,
__('1 h') => 60*60,
__('2 h') => 2*60*60,
__('4 h') => 4*60*60,
__('1 Day') => 1 * confGet('WORKHOURS_PER_DAY') * 60 * 60,
__('2 Days') => 2 * confGet('WORKHOURS_PER_DAY') * 60 * 60,
__('3 Days') => 3 * confGet('WORKHOURS_PER_DAY') * 60 * 60,
__('4 Days') => 4 * confGet('WORKHOURS_PER_DAY') * 60 * 60,
__('1 Week') => 1 * confGet('WORKDAYS_PER_WEEK') * confGet('WORKHOURS_PER_DAY') * 60 * 60,
#__('1,5 Weeks')=> 1.5 * confGet('WORKDAYS_PER_WEEK') * confGet('WORKHOURS_PER_DAY') * 60 * 60,
__('2 Weeks') => 2 * confGet('WORKDAYS_PER_WEEK') * confGet('WORKHOURS_PER_DAY') * 60 * 60,
__('3 Weeks') => 3 * confGet('WORKDAYS_PER_WEEK') * confGet('WORKHOURS_PER_DAY') * 60 * 60,
);
$tab->add(new Form_Dropdown('task_estimated',__("Estimated time"),$ar, $task->estimated));
$tab->add(new Form_Dropdown('task_estimated_max',__("Estimated worst case"),$ar, $task->estimated_max));
}
### planned time ###
if(!$task->isMilestoneOrVersion()) {
$tab->add($task->fields['planned_start' ]->getFormElement(&$task));
}
$tab->add($task->fields['planned_end' ]->getFormElement(&$task));
if($task->isMilestoneOrVersion()) {
global $g_released_names;
$tab->add(new Form_Dropdown('task_is_released', __("Release as version","Form label, attribute of issue-reports"), array_flip($g_released_names), $task->is_released));
$tab->add($task->fields['time_released']->getFormElement(&$task));
}
}
### description attributes ###
{
$tab_group->add($tab= new Page_Tab('description', __("Description")));
$e= $task->fields['description']->getFormElement(&$task);
$e->rows=20;
$tab->add($e);
}
### display attributes ###
{
$tab_group->add($tab= new Page_Tab('display',__("Display")));
### short ###
$tab->add($task->fields['short']->getFormElement(&$task));
### order id ###
$tab->add($task->fields['order_id']->getFormElement(&$task));
### Shows as news ###
$tab->add($task->fields['is_news']->getFormElement(&$task));
### Shows Folder as documentation ###
$tab->add($task->fields['show_folder_as_documentation']->getFormElement(&$task));
### public-level ###
if(($pub_levels=$task->getValidUserSetPublicLevels())
&& count($pub_levels)>1) {
$tab->add(new Form_Dropdown('task_pub_level', __("Publish to"),$pub_levels,$task->pub_level));
}
### label ###
if(!$task->isOfCategory(TCATEGORY_VERSION, TCATEGORY_MILESTONE, TCATEGORY_FOLDER)) {
$labels=array(__('undefined') => 0);
$counter= 1;
foreach(explode(",",$project->labels) as $l) {
$labels[$l]=$counter++;
}
$tab->add(new Form_Dropdown('task_label', __("Label"),$labels,$task->label));
}
}
## internal area ##
{
if((confGet('INTERNAL_COST_FEATURE')) && ($auth->cur_user->user_rights & RIGHT_VIEWALL) && ($auth->cur_user->user_rights & RIGHT_EDITALL)){
$tab_group->add($tab=new Page_Tab("internal",__("Internal")));
$tab->add($task->fields['calculation']->getFormElement(&$task));
}
}
/**
* to reduce spam, enforce captcha test for guests
*/
global $auth;
if($auth->cur_user->id == confGet('ANONYMOUS_USER')) {
$form->addCaptcha();
}
$form->add($task->fields['parent_task']->getFormElement(&$task));
#echo "<input type=hidden name='tsk' value='$task->id'>";
$form->add(new Form_HiddenField('tsk','',$task->id));
#echo "<input type=hidden name='task_project' value='$project->id'>";
$form->add(new Form_HiddenField('task_project','',$project->id));
### create another task ###
if($task->id == 0) {
$checked= get('create_another')
? 'checked'
: '';
$form->form_options[]="<input id='create_another' name='create_another' type=checkbox $checked><label for='create_another'>" . __("Create another task after submit") . "</label>"; ;
}
echo($form);
$PH->go_submit= 'taskEditSubmit';
if($return=get('return')) {
echo "<input type=hidden name='return' value='$return'>";
}
$block->render_blockEnd();
#@@@ passing project-id is an security-issue, because it might allow to add tasks to unverified projects.
# Double-checking project-rights in taskEditSubmit() required
}
echo (new PageContentClose);
echo (new PageHtmlEnd);
}
/**
* Submit changes to a task
*
* @ingroup pages
*/
function taskEditSubmit()
{
global $PH;
global $auth;
require_once(confGet('DIR_STREBER') . 'db/class_taskperson.inc.php');
/**
* keep a list of items linking to this task, task is new
* we have to change the linking id after(!) inserting the task
*/
$link_items=array();
### temporary object or from database? ###
$tsk_id=getOnePassedId('tsk','',true,'invalid id');
if($tsk_id == 0) {
$task= new Task(array(
'id'=>0,
'project'=>get('task_project'),
));
$was_category= 0; # undefined category for new tasks
$was_resolved_version= 0;
}
else {
if(!$task= Task::getVisiblebyId($tsk_id)) {
$PH->abortWarning("invalid task-id");
}
$was_category=$task->category;
$was_resolved_version= $task->resolved_version;
$task->validateEditRequestTime();
}
### cancel? ###
if(get('form_do_cancel')) {
if(!$PH->showFromPage()) {
$PH->show('taskView',array('tsk'=>$task->id));
}
exit();
}
### Validate integrety ###
if(!validateFormCrc()) {
$PH->abortWarning(__('Invalid checksum for hidden form elements'));
}
validateFormCaptcha(true);
$was_a_folder= ($task->category == TCATEGORY_FOLDER)
? true
: false;
$was_released_as= $task->is_released;
### get project ###
if(!$project= Project::getVisiblebyId($task->project)) {
$PH->abortWarning("task without project?");
}
/**
* adding comment (from quick edit) does only require view right...
*/
$added_comment= false;
{
### check for request feedback
if($request_feedback= get('request_feedback')) {
$team_members_by_nickname = array();
foreach($project->getProjectPersons() as $pp) {
$team_members_by_nickname[ $pp->getPerson()->nickname ] = $pp->getPerson();
}
$requested_people= array();
foreach( explode('\s*,\s*', $request_feedback) as $nickname) {
### now check if this nickname is a team member
if ($nickname = trim($nickname)) {
if ( isset( $team_members_by_nickname[$nickname] )) {
$person = $team_members_by_nickname[$nickname];
### update to itemperson table...
if($view = ItemPerson::getAll(array('person'=>$person->id, 'item'=>$task->id))){
$view[0]->feedback_requested_by = $auth->cur_user->id;
$view[0]->update();
}
else{
$new_view = new ItemPerson(array(
'item' =>$task->id,
'person' =>$person->id,
'feedback_requested_by'=> $auth->cur_user->id ));
$new_view->insert();
}
$requested_people[]= "<b>". asHtml($nickname) ."</b>";
}
else {
new FeedbackWarning(sprintf(__("Nickname not known in this project: %s"), "<b>". asHtml($nickname) ."</b>"));
}
}
}
if( $requested_people ) {
new FeedbackMessage(sprintf(__('Requested feedback from: %s.'), join($requested_people, ", ")));
}
}
### only insert the comment, when comment name or description are valid
if(get('comment_name') || get('comment_description')) {
require_once(confGet('DIR_STREBER') . 'pages/comment.inc.php');
$valid_comment= true;
### new object? ###
$comment= new Comment(array(
'name'=> get('comment_name'),
'description' =>get('comment_description'),
'project' => $task->project,
'task' => $task->id
));
if(confGet('REJECT_SPAM_CONTENT') && $auth->cur_user->id == confGet('ANONYMOUS_USER')) {
$propability= (isSpam($comment->description) + isSpam($comment->name)) * 0.5;
if($propability > confGet('REJECT_SPAM_CONTENT')) {
log_message(sprintf("rejected spam comment from %s with %s", getServerVar('REMOTE_ADDR'), $propability), LOG_MESSAGE_HACKING_ALERT);
$PH->abortWarning(__("Comment has been rejected, because it looks like spam.") );
}
}
### write to db ###
if($valid_comment) {
if(!$comment->insert()) {
new FeedbackWarning(__("Failed to add comment"));
}
else {
### change task update modification date ###
if(isset($task)) {
### Check if now longer new ###
if($task->status == STATUS_NEW) {
global $auth;
if($task->created < $auth->cur_user->last_login) {
$task->status = STATUS_OPEN;
}
}
$task->update(array('modified','status'));
}
$added_comment= true;
}
}
}
}
if($task->id != 0 && ! Task::getEditableById($task->id)) {
if($added_comment) {
### display taskView ####
if(!$PH->showFromPage()) {
$PH->show('home',array());
}
exit();
}
else {
$PH->abortWarning(__("Not enough rights to edit task"));
}
}
$task->validateEditRequestTime();
$status_old = $task->status;
# retrieve all possible values from post-data (with field->view_in_forms == true)
# NOTE:
# - this could be an security-issue.
# @@@ TODO: as some kind of form-edit-behaviour to field-definition
foreach($task->fields as $f) {
$name=$f->name;
$f->parseForm(&$task);
}
$task->fields['parent_task']->parseForm(&$task);
### category ###
$was_of_category = $task->category;
if(!is_null($c= get('task_category'))) {
global $g_tcategory_names;
if(isset($g_tcategory_names[$c])) {
$task->category= $c;
}
else {
trigger_error("ignoring unknown task category '$c'", E_USER_NOTICE);
}
}
/**
* @@@pixtur 2006-11-17: actually this has been depreciated. is_folder updated
* for backward compatibility only.
*/
$task->is_folder = ($task->category == TCATEGORY_FOLDER)
? 1
: 0;
### Check if now longer new ###
if($status_old == $task->status && $task->status == STATUS_NEW) {
global $auth;
if($task->created < $auth->cur_user->last_login) {
$task->status = STATUS_OPEN;
}
}
/**
* assigned to...
* - assigments are stored in form-fiels named 'task_assign_to_??' and 'task_assigned_to_??"...
* ... where ?? being the id of the last assigned person(s)
*
* - builds up multiple arrays of person-objects (reusing the same objects due to caching)
* - get already assigned persons into dict. of person_id => Person
* - get assignments into dict. of person_id => Person
* - get current project-team as dict of person_id => Person
* - checks for double-assigments
*
*/
{
$assigned_persons = array();
$task_assignments = array();
if($task->id) {
foreach($task->getAssignedPersons() as $p) {
$assigned_persons[$p->id] = $p;
}
foreach($task->getAssignments() as $ta) {
$task_assignments[$ta->person]= $ta;
}
}
$team= array();
foreach($project->getPersons() as $p) {
$team[$p->id]= $p;
}
$new_task_assignments= array(); # store assigments after(!) validation
$forwarded = 0;
$forward_comment = '';
$old_task_assignments = array();
if(isset($task_assignments)) {
foreach($task_assignments as $id=>$t_old) {
$id_new= get('task_assigned_to_'.$id);
$forward_state = get('task_forward_to_'.$id);
if($forward_state){
$forwarded = 1;
}
else{
$forwarded = 0;
}
$forward_comment = get('task_forward_comment_to_'.$id);
if($id_new === NULL) {
log_message("failure. Can't change no longer existing assigment (person-id=$id item-id=$t_old->id)", LOG_MESSAGE_DEBUG);
#$PH->abortWarning("failure. Can't change no longer existing assigment",ERROR_NOTE);
continue;
}
if($id == $id_new) {
if($tp = TaskPerson::getTaskPersons(array('person'=>$id, 'task'=>$task->id))){
$tp[0]->forward = $forwarded;
$tp[0]->forward_comment = $forward_comment;
$old_task_assignments[] = $tp[0];
}
#echo " [$id] {$team[$id]->name} still assigned<br>";
continue;
}
if($id_new == 0) {
if(!$t_old) {
continue;
}
#echo " [$id] {$team[$id]->name} unassigned<br>";
$t_old->delete();
continue;
}
#$t_new= $task_assignments[$id_new];
$p_new = @$team[$id_new];
if(!isset($p_new)) {
$PH->abortWarning("failure during form-value passing",ERROR_BUG);
}
#echo " [$id] assignment changed from {$team[$id]->name} to {$team[$id_new]->name}<br>";
$t_old->comment = sprintf(__("unassigned to %s","task-assignment comment"),$team[$id_new]->name);
$t_old->update();
$t_old->delete();
$new_assignment= new TaskPerson(array(
'person'=> $team[$id_new]->id,
'task' => $task->id,
'comment'=>sprintf(__("formerly assigned to %s","task-assigment comment"), $team[$id]->name),
'project'=>$project->id,
'forward'=>$forwarded,
'forward_comment'=>$forward_comment,
));
$new_task_assignments[]=$new_assignment;
$link_items[]=$new_assignment;
}
}
### check new assigments ###
$count=0;
while($id_new= get('task_assign_to_'.$count)) {
$forward_state = get('task_forward_to_'.$count);
if($forward_state){
$forwarded = 1;
}
else{
$forwarded = 0;
}
$forward_comment = get('task_forward_comment_to_'.$count);
$count++;
### check if already assigned ###
if(isset($task_assignments[$id_new])) {
if($tp = TaskPerson::getTaskPersons(array('person'=>$id_new,'task'=>$task->id))){
$tp[0]->forward = $forwarded;
$tp[0]->forward_comment = $forward_comment;
$old_task_assignments[] = $tp[0];
}
#new FeedbackMessage(sprintf(__("task was already assigned to %s"),$team[$id_new]->name));
}
else {
if(!isset($team[$id_new])) {
$PH->abortWarning("unknown person id $id_new",ERROR_DATASTRUCTURE);
}
$new_assignment= new TaskPerson(array(
'person'=> $team[$id_new]->id,
'task' => $task->id,
'comment'=>"",
'project'=>$project->id,
'forward'=>$forwarded,
'forward_comment'=>$forward_comment,
));
/**
* BUG?
* - inserting the new assigment before sucessfully validating the
* task will lead to double-entries in the database.
*/
$new_task_assignments[] = $new_assignment;
#$new_assignment->insert();
$link_items[]=$new_assignment;
}
}
}
if($task->isOfCategory(array(TCATEGORY_VERSION, TCATEGORY_MILESTONE))) {
if($is_released=get('task_is_released')) {
if(!is_null($is_released)) {
$task->is_released = $is_released;
}
}
}
### pub level ###
if($pub_level=get('task_pub_level')) {
if($task->id) {
if($pub_level > $task->getValidUserSetPublicLevels() ) {
$PH->abortWarning('invalid data',ERROR_RIGHTS);
}
}
#else {
# #@@@ check for person create rights
#}
$task->pub_level = $pub_level;
}
### check project ###
if($task->id == 0) {
if(!$task->project=get('task_project')) {
$PH->abortWarning("task requires project to be set");
}
}
### get parent_task ###
$is_ok= true;
$parent_task= NULL;
if($task->parent_task) {
$parent_task= Task::getVisibleById($task->parent_task);
}
### validate ###
if(!$task->name) {
new FeedbackWarning(__("Task requires name"));
$task->fields['name']->required=true;
$task->fields['name']->invalid=true;
$is_ok= false;
}
### task-name already exist ###
else if($task->id == 0){
$other_tasks = array();
if($parent_task) {
$other_tasks= Task::getAll(array(
'project' => $project->id,
'parent_task'=> $parent_task->id,
'status_min'=> STATUS_NEW,
'status_max'=> STATUS_CLOSED,
'visible_only' => false,
));
}
else {
$other_tasks= Task::getAll(array(
'project' => $project->id,
'parent_task'=> 0,
'status_min'=> STATUS_NEW,
'status_max'=> STATUS_CLOSED,
'visible_only' => false,
));
}
foreach($other_tasks as $ot) {
if(!strcasecmp($task->name, $ot->name)) {
$is_ok = false;
new FeedbackWarning(sprintf(__('Task called %s already exists'), $ot->getLink(false)));
break;
}
}
}
### automatically close resolved tasks ###
if($task->resolve_reason && $task->status < STATUS_COMPLETED) {
$task->status = STATUS_COMPLETED;
new FeedbackMessage(sprintf(__('Because task is resolved, its status has been changed to completed.')));
}
### Check if resolved tasks should be completed ###
if($task->resolved_version != 0 && $task->status < STATUS_COMPLETED) {
new FeedbackWarning(sprintf(__('Task has resolved version but is not completed?')));
$task->fields['resolved_version']->invalid= true;
$task->fields['status']->invalid= true;
$is_ok = false;
}
### Check if completion should be 100% ###
if ($task->status >= STATUS_COMPLETED) {
$task->completion = 100;
}
### repeat form if invalid data ###
if(!$is_ok) {
$PH->show('taskEdit',NULL,$task);
exit();
}
#--- write to database -----------------------------------------------------------------------
#--- be sure parent-task is folder ---
if($parent_task) {
if($parent_task->isMilestoneOrVersion()) {
if($parent_task->is_folder) {
$parent_task->is_folder= 0;
$parent_task->update(array('is_folder'),false);
}
$PH->abortWarning(__("Milestones may not have sub tasks"));
}
else if($parent_task->category != TCATEGORY_FOLDER) {
$parent_task->category= TCATEGORY_FOLDER;
$parent_task->is_folder= 1;
if($parent_task->update()) {
new FeedbackMessage(__("Turned parent task into a folder. Note, that folders are only listed in tree"));
}
else {
trigger_error(__("Failed, adding to parent-task"),E_USER_WARNING);
$PH->abortWarning(__("Failed, adding to parent-task"));
}
}
}
### ungroup child tasks? ###
if($was_a_folder && $task->category != TCATEGORY_FOLDER) {
$num_subtasks= $task->ungroupSubtasks(); # @@@ does this work???
/**
* note: ALSO invisible tasks should be updated, so do not check for visibility here.
*/
$parent= Task::getById($task->parent_task);
$parent_str= $parent
? $parent->name
: __('Project');
if($num_subtasks) {
new FeedbackMessage(sprintf(__("NOTICE: Ungrouped %s subtasks to <b>%s</b>"),$num_subtasks, $parent_str));
}
}
if($task->id && !get('task_issue_report')) {
$task_issue_report = $task->issue_report;
}
else if($task->issue_report != get('task_issue_report')) {
trigger_error("Requesting invalid issue report id for task!", E_USER_WARNING);
$task_issue_report= get('task_issue_report');
}
else {
$task_issue_report = 0;
}
### consider issue-report? ###
#$task_issue_report= get('task_issue_report');
if( $task->category == TCATEGORY_BUG || (isset($task_issue_report) && $task_issue_report) ) {
### new report as / temporary ###
if($task_issue_report == 0 || $task_issue_report == -1) {
$issue= new Issue(array(
'id'=>0,
'project' => $project->id,
'task' => $task->id,
));
### querry form-information ###
foreach($issue->fields as $f) {
$name=$f->name;
$f->parseForm(&$issue);
}
global $g_reproducibility_names;
if(!is_null($rep= get('issue_reproducibility'))) {
if(isset($g_reproducibility_names[$rep])) {
$issue->reproducibility= intval($rep);
}
else {
$issue->reproducibility= REPRODUCIBILITY_UNDEFINED;
}
}
global $g_severity_names;
if(!is_null($sev= get('issue_severity'))) {
if(isset($g_severity_names[$sev])) {
$issue->severity= intval($sev);
}
else {
$issue->severity= SEVERITY_UNDEFINED;
}
}
### write to db ###
if(!$issue->insert()) {
trigger_error("Failed to insert issue to db",E_USER_WARNING);
}
else {
$link_items[]= $issue;
$task->issue_report= $issue->id;
}
}
### get from database ###
else if($issue= Issue::getById($task_issue_report)) {
### querry form-information ###
foreach($issue->fields as $f) {
$name=$f->name;
$f->parseForm(&$issue);
}
global $g_reproducibility_names;
if(!is_null($rep= get('issue_reproducibility'))) {
if(isset($g_reproducibility_names[$rep])) {
$issue->reproducibility= intval($rep);
}
else {
$issue->reproducibility= REPRODUCIBILITY_UNDEFINED;
}
}
global $g_severity_names;
if(!is_null($sev= get('issue_severity'))) {
if(isset($g_severity_names[$sev])) {
$issue->severity= intval($sev);
}
else {
$issue->severity= SEVERITY_UNDEFINED;
}
}
### write to db ###
if(!$issue->update()) {
trigger_error("Failed to write issue to DB (id=$issue->id)", E_USER_WARNING);
}
if($task->issue_report != $issue->id) { # additional check, actually not necessary
trigger_error("issue-report as invalid id ($issue->id). Should be ($task->issue_report) Please report this bug.",E_USER_WARNING);
}
}
else {
trigger_error("Could not get issue with id $task->issue_report from database",E_USER_WARNING);
}
}
### write to db ###
if($task->id == 0) {
$task->insert();
### write task-assigments ###
foreach($new_task_assignments as $nta) {
$nta->insert();
}
### now we now the id of the new task, link the other items
foreach($link_items as $i) {
$i->task= $task->id;
$i->update();
}
new FeedbackMessage(sprintf(__("Created %s %s with ID %s","Created <type> <name> with ID <id>..."),
$task->getLabel(),
$task->getLink(false),
$task-> id)
);
}
else {
### write task-assigments ###
foreach($new_task_assignments as $nta) {
$nta->insert();
}
foreach($old_task_assignments as $ota){
$ota->update();
}
new FeedbackMessage(sprintf(__("Changed %s %s with ID %s","type,link,id"), $task->getLabel(), $task->getLink(false),$task->id));
$task->update();
$project->update(array(), true);
}
### add any recently resolved tasks if this is a just released version ###
if($task->category == TCATEGORY_VERSION && $was_category != TCATEGORY_VERSION) {
if($resolved_tasks= Task::getAll(array(
'project' => $task->project,
'status_min' => 0,
'status_max' => 10,
'resolved_version' => RESOLVED_IN_NEXT_VERSION,
))) {
foreach($resolved_tasks as $rt) {
$rt->resolved_version= $task->id;
$rt->update(array('resolved_version'));
}
new FeedbackMessage(sprintf(__('Marked %s tasks to be resolved in this version.'), count($resolved_tasks)));
}
}
### notify on change ###
$task->nowChangedByUser();
### create another task ###
if(get('create_another')) {
### build dummy form ###
$newtask= new Task(array(
'id' =>0,
'name' =>__('Name'),
'project' =>$task->project,
'state' =>1,
'prio' =>$task->prio,
'label' =>$task->label,
'parent_task'=>$task->parent_task,
'for_milestone'=>$task->for_milestone,
'category' =>$task->category,
));
$PH->show('taskEdit',array('tsk'=>$newtask->id),$newtask);
}
else {
### go to task, if new
if($tsk_id == 0) {
$PH->show('taskView',array('tsk' => $task->id));
exit();
}
### display taskView ####
else if(!$PH->showFromPage()) {
$PH->show('home',array());
}
}
}
/**
* to tasks to folder...
*
* @ingroup pages
*
* NOTE: this works either...
* - directly by passing a target folder in 'folder' or 'folders_*'
* - in two steps, whereas
* - the passed task-ids are keept as hidden fields,
* - a list with folders in been rendered
* - a flag 'from_selection' is set
* - after submit, the kept tasks are moved to 'folders_*'
*
*/
function TasksMoveToFolder()
{
global $PH;
$task_ids= getPassedIds('tsk','tasks_*');
if(!$task_ids) {
$PH->abortWarning(__("Select some tasks to move"));
exit();
}
/**
* by default render list of folders...
*/
$target_id=-1;
/**
* ...but, if folder was given, directly move tasks...
*/
$folder_ids= getPassedIds('folder','folders_*');
if(count($folder_ids) == 1) {
if($folder_task= Task::getVisibleById($folder_ids[0])) {
$target_id= $folder_task->id;
}
}
/**
* if no folders was selected, move tasks to project root
*/
else if(get('from_selection')) {
$target_id= 0;
}
if($target_id != -1) {
if($target_id != 0){
if(!$target_task= Task::getEditableById($target_id)) {
$PH->abortWarning(__("insufficient rights"));
}
### get path of target to check for cycles ###
$parent_tasks= $target_task->getFolder();
$parent_tasks[]= $target_task;
}
else {
$parent_tasks=array();
}
$count=0;
foreach($task_ids as $id) {
if($task= Task::getEditableById($id)) {
### check if tasks target_id is own child ###
$cycle_flag= false;
foreach($parent_tasks as $pt) {
if($pt->id == $task->id) {
$cycle_flag= true;
break;
}
}
if($cycle_flag) {
new FeedbackWarning(sprintf(__("Can not move task <b>%s</b> to own child."), $task->name));
}
else {
$task->parent_task= $target_id;
$task->update();
$task->nowChangedByUser();
}
}
else {
new FeedbackWarning(sprintf(__("Can not edit tasks %s"), $task->name));
}
}
### return to from-page? ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
exit();
}
/**
* build page folder lists...
*/
### get project ####
if(!$task= Task::getVisibleById($task_ids[0])) {
$PH->abortWarning("could not get task", ERROR_BUG);
}
if(!$project= Project::getVisibleById($task->project)) {
$PH->abortWarning("task without project?", ERROR_BUG);
}
### set up page and write header ####
{
$page= new Page(array('use_jscalendar'=>false));
$page->cur_tab='projects';
$page->type= __("Edit tasks");
$page->title="$project->name";
$page->title_minor=__("Select folder to move tasks into");
$page->crumbs= build_project_crumbs($project);
$page->options[]= new NaviOption(array(
'target_id' =>'tasksMoveToFolder',
));
echo(new PageHeader);
}
echo (new PageContentOpen);
### write form #####
{
### write tasks as hidden entry ###
foreach($task_ids as $id) {
if($task= Task::getEditableById($id)) {
echo "<input type=hidden name='tasks_{$id}_chk' value='1'>";
}
}
### write list of folders ###
{
$list= new ListBlock_tasks();
$list->query_options['show_folders']= true;
$list->query_options['folders_only']= true;
$list->query_options['project']= $project->id;
$list->groupings= NULL;
$list->block_functions= NULL;
$list->id= 'folders';
unset($list->columns['status']);
unset($list->columns['date_start']);
unset($list->columns['days_left']);
unset($list->columns['created_by']);
unset($list->columns['label']);
unset($list->columns['project']);
$list->functions= array();
$list->active_block_function = 'tree';
$list->print_automatic($project,NULL);
}
echo __("(or select nothing to move to project root)"). "<br> ";
echo "<input type=hidden name='from_selection' value='1'>"; # keep flag to ungroup tasks
echo "<input type=hidden name='project' value='$project->id'>";
$button_name=__("Move items");
echo "<input class=button2 type=submit value='$button_name'>";
$PH->go_submit='tasksMoveToFolder';
}
echo (new PageContentClose);
echo (new PageHtmlEnd());
}
/**
* tasksDelete
*
* @ingroup pages
*
* \NOTE sub-tasks of tasks are not deleted but ungrouped
*/
function TasksDelete()
{
global $PH;
$tsk=get('tsk');
$tasks_selected=get('tasks_*');
$ids=getPassedIds('tsk','tasks_*');
$tasks= array();
if(count($ids)==1) {
$tsk=$ids[0];
if(!$task= Task::getEditableById($tsk)) {
$PH->abortWarning(__('insufficient rights'),ERROR_RIGHTS);
$PH->show('home');
return;
}
$tasks[]= $task;
}
else if($ids) {
#--- get tasks ----
$num_tasks=count($tasks);
foreach($ids as $id) {
if(!$task= Task::getEditableById($id)) {
$PH->abortWarning("invalid task-id");
}
$tasks[]= $task;
}
}
if($tasks) {
$num_subtasks = 0;
$num_tasks= 0;
foreach($tasks as $task) {
$num_subtasks+= $task->ungroupSubtasks();
if(!$task->delete()) {
new FeedbackWarning(sprintf(__("Failed to delete task %s"), $task->name));
}
else {
$num_tasks++;
}
}
new FeedbackMessage(sprintf(__("Moved %s tasks to trash"),$num_tasks));
if($num_subtasks) {
new FeedbackMessage(sprintf(__(" ungrouped %s subtasks to above parents."),$num_subtasks));
}
### return to from-page? ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
else {
new FeedbackHint(__("No task(s) selected for deletion..."));
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
}
/**
* Restore deleted task
*
* @ingroup pages
*/
function TasksUndelete()
{
global $PH;
$tsk=get('tsk');
$tasks_selected=get('tasks_*');
$ids=getPassedIds('tsk','tasks_*');
if(count($ids)==1) {
$tsk=$ids[0];
$task= Task::getEditableById($tsk);
if(!$task) {
new FeedbackWarning(__("Could not find task"));
$PH->show('home');
return;
}
### check user-rights ###
if(!$project= Project::getVisibleById($task->project)) {
$PH->abortWarning("task without project?", ERROR_BUG);
}
### delete task ###
if($task->state!= -1) {
new FeedbackHint(sprintf(__("Task <b>%s</b> does not need to be restored"),$task->name));
}
else {
$task->state=1;
if($task->update()) {
new FeedbackMessage(sprintf(__("Task <b>%s</b> restored"),$task->name));
$task->nowChangedByUser();
}
else {
new FeedbackMessage(sprintf(__("Failed to restore Task <b>%s</b>"),$task->name));
}
}
### go to project view ###
### return to from-page? ###
if(!$PH->showFromPage()) {
$PH->show('projView',array('prj'=>$project->id));
}
}
else if($ids) {
#--- get tasks ----
$tasks=array();
$num_tasks=count($tasks);
$num_subtasks=0;
foreach($ids as $id) {
if(!$task = Task::getEditableById($id)) {
new FeedbackWarning("Could not find task");
$PH->show('home');
return;
}
### delete task ###
if($task->state!= -1) {
new FeedbackHint(sprintf(__("Task <b>%s</b> do not need to be restored"), $task->name));
}
else {
$task->state=1;
if($task->update()) {
new FeedbackMessage(sprintf(__("Task <b>%s</b> restored"),$task->name));
}
else {
new FeedbackWarning(sprintf(__("Failed to restore Task <b>%s</b>"),$task->name));
}
}
}
### return to from-page? ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
else {
new FeedbackHint(__("No task(s) selected for restoring..."));
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
}
/**
* Mark tasks as being completed
*
* @ingroup pages
*/
function TasksComplete()
{
global $PH;
$ids= getPassedIds('tsk','tasks_*');
if(!$ids) {
$PH->abortWarning(__("Select some task(s) to mark as completed"), ERROR_NOTE);
return;
}
$count=0;
$count_subtasks=0;
$num_errors=0;
foreach($ids as $id) {
if($task= Task::getEditableById($id)) {
$count++;
$task->status=5;
$task->date_closed= gmdate("Y-m-d", time());
$task->completion=100;
$task->update();
$task->nowChangedByUser();
### get all subtasks ###
if($subtasks= $task->getSubtasks()) {
foreach($subtasks as $st) {
if($subtask_editable= Task::getEditableById($st->id)) {
$count_subtasks++;
$subtask_editable->status= STATUS_COMPLETED;
$subtask_editable->date_closed= gmdate("Y-m-d", time());
$subtask_editable->completion=100;
$subtask_editable->update();
$subtask_editable->nowChangedByUser();
$subtask_editable->resolved_version= RESOLVED_IN_NEXT_VERSION;
}
else {
$num_errors++;
}
}
}
}
else {
$num_errors++;
}
}
$str_subtasks= $count_subtasks
? "(including $count_subtasks subtasks)"
: "";
new FeedbackMessage(sprintf(__("Marked %s tasks (%s subtasks) as completed."),$count,$str_subtasks)) ;
if($num_errors) {
new FeedbackWarning(sprintf(__("%s error(s) occured"), $num_errors));
}
### return to from-page ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
/**
* Create a task as being approved
*
* @ingroup pages
*/
function TasksApproved()
{
global $PH;
$ids= getPassedIds('tsk','tasks_*');
if(!$ids) {
$PH->abortWarning(__("Select some task(s) to mark as approved"), ERROR_NOTE);
return;
}
$count=0;
$num_errors=0;
foreach($ids as $id) {
if($task= Task::getEditableById($id)) {
$count++;
$task->status = STATUS_APPROVED;
$task->date_closed = gmdate("Y-m-d", time());
$task->completion = 100;
$task->update();
$task->nowChangedByUser();
}
else {
$num_errors++;
}
}
new FeedbackMessage(sprintf(__("Marked %s tasks as approved and hidden from project-view."),$count));
if($num_errors) {
new FeedbackWarning(sprintf(__("%s error(s) occured"), $num_errors));
}
### return to from-page ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
/**
* Create a task as closed
*
* @ingroup pages
*/
function TasksClosed()
{
global $PH;
$ids= getPassedIds('tsk','tasks_*');
if(!$ids) {
$PH->abortWarning(__("Select some task(s) to mark as closed"), ERROR_NOTE);
return;
}
$count=0;
$num_errors=0;
foreach($ids as $id) {
if($task= Task::getEditableById($id)) {
$count++;
$task->status = STATUS_CLOSED;
$task->date_closed = gmdate("Y-m-d", time());
$task->completion = 100;
$task->update();
$task->nowChangedByUser();
}
else {
$num_errors++;
}
}
new FeedbackMessage(sprintf(__("Marked %s tasks as closed."),$count));
if($num_errors) {
new FeedbackWarning(sprintf(__("Not enough rights to close %s tasks."), $num_errors));
}
### return to from-page ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
/**
* Reopen tasks
*
* @ingroup pages
*/
function TasksReopen()
{
global $PH;
$ids= getPassedIds('tsk','tasks_*');
if(!$ids) {
$PH->abortWarning(__("Select some task(s) to reopen"), ERROR_NOTE);
return;
}
$count =0;
$num_errors =0;
foreach($ids as $id) {
if($task= Task::getEditableById($id)) {
$count++;
$task->status=STATUS_OPEN;
$task->update();
$task->nowChangedByUser();
}
else {
$num_errors++;
}
}
new FeedbackMessage(sprintf(__("Reopened %s tasks."),$count));
if($num_errors) {
new FeedbackWarning(sprintf(__("%s error(s) occured"), $num_errors));
}
### return to from-page ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
/**
* Toggle task folders
*
* @ingroup pages
*/
function TaskToggleViewCollapsed()
{
global $PH;
global $auth;
$ids= getPassedIds('tsk','tasks_*');
if(!$ids) {
$PH->abortWarning(__("Select some task(s)"), ERROR_NOTE);
return;
}
$count = 0;
$num_errors = 0;
foreach($ids as $id) {
if($task= Task::getVisibleById($id)) {
if($task->view_collapsed) {
$task->view_collapsed= 0;
}
else {
$task->view_collapsed= 1;
}
if(!$task->update(array('view_collapsed'),false)) {
new FeedbackError(__("Could not update task"));
$num_errors++;
}
else {
$count++;
}
}
else {
$num_errors++;
}
}
if($num_errors) {
new FeedbackWarning(sprintf(__("%s error(s) occured"), $num_errors));
}
### return to from-page ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
/**
* add an issue-report to an existing task
*
* @ingroup pages
*/
function TaskAddIssueReport()
{
global $PH;
$id= getOnePassedId('tsk','tasks_*',true,__('No task selected to add issue-report?'));
if($task= Task::getEditableById($id)) {
if($task->issue_report) {
$PH->abortWarning(__("Task already has an issue-report"));
exit();
}
### check user-rights ###
if(!$project= Project::getVisibleById($task->project)) {
$PH->abortWarning(__("task without project?"), ERROR_BUG);
}
$task->issue_report= -1;
new FeedbackHint(__("Adding issue-report to task"));
$PH->show('taskEdit',array('tsk'=>$task->id),$task);
exit();
}
else {
new FeedbackWarning(__("Could not find task"));
}
### return to from-page ###
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
/**
* Edit description of a task
*
* @ingroup pages
*/
function taskEditDescription($task=NULL)
{
global $PH;
### object or from database? ###
if(!$task) {
$id= getOnePassedId('tsk','tasks_*');
if(!$task = Task::getEditableById($id)) {
$PH->abortWarning(__("Select a task to edit description"), ERROR_NOTE);
return;
}
}
### set up page and write header ####
{
$page= new Page(array('use_jscalendar'=>false, 'autofocus_field'=>'task_name'));
initPageForTask($page, $task);
$page->title_minor= __("Edit description");
echo(new PageHeader);
}
echo (new PageContentOpen);
### write form #####
{
require_once(confGet('DIR_STREBER') . 'render/render_form.inc.php');
$block=new PageBlock(array(
'id' =>'edit',
));
$block->render_blockStart();
$form=new PageForm();
$form->button_cancel=true;
$form->add(new Form_HiddenField('task_id','',$task->id));
$form->add($task->fields['name']->getFormElement(&$task));
$e= $task->fields['description']->getFormElement(&$task);
$e->rows=22;
$form->add($e);
echo ($form);
$block->render_blockEnd();
$PH->go_submit= 'taskEditDescriptionSubmit';
}
echo (new PageContentClose);
echo (new PageHtmlEnd);
}
/**
* Submit changes to the description of a task
*
* @ingroup pages
*/
function taskEditDescriptionSubmit()
{
global $PH;
### cancel? ###
if(get('form_do_cancel')) {
if(!$PH->showFromPage()) {
$PH->show('taskView',array('tsk'=>$task->id));
}
exit();
}
if(!$task = Task::getEditableById(intval(get('task_id')))) {
$PH->abortWarning("unknown task-id");
}
$name= get('task_name');
if(!is_null($name)) {
$task->name= $name;
}
$description= get('task_description');
if(!is_null($description)) {
$task->description= $description;
}
### validate ###
if(!$task->name) {
new FeedbackWarning(__("Task requires name"));
}
### repeat form if invalid data ###
if(!$task->name) {
$PH->show('taskEditDescription',NULL,$task);
exit();
}
### write to db ###
$task->update(array('name','description'));
### return to from-page? ###
if(!$PH->showFromPage()) {
$PH->show('taskView',array('tsk'=>$task->id));
}
}
/**
* View efforts for a task
*
* @ingroup pages
*/
function TaskViewEfforts()
{
global $PH;
require_once(confGet('DIR_STREBER') . 'lists/list_efforts.inc.php');
### get current project ###
$id=getOnePassedId('task','tasks_*');
if(!$task=Task::getVisibleById($id)) {
$PH->abortWarning("invalid task-id");
return;
}
### create from handle ###
$PH->defineFromHandle(array('task'=>$task->id));
if(!$project= Project::getVisibleById($task->project)) {
$PH->abortWarning("not enough rights");
}
### set up page ####
{
$page= new Page();
initPageForTask($page, $task, $project);
$page->title_minor= __("Task Efforts");
### page functions ###
$page->add_function(new PageFunction(array(
'target'=>'effortNew',
'params'=>array('task'=>$task->id),
'icon'=>'new',
'name'=>__('new Effort'),
)));
### render title ###
echo(new PageHeader);
}
echo (new PageContentOpen);
#--- list efforts --------------------------------------------------------------------------
{
$order_by=get('sort_'.$PH->cur_page->id."_efforts");
require_once(confGet('DIR_STREBER') . 'db/class_effort.inc.php');
$efforts= Effort::getAll(array(
'task' => $task->id,
'order_by' => $order_by,
));
$list= new ListBlock_efforts();
$list->render_list(&$efforts);
}
### 'add new task'-field ###
$PH->go_submit='effortNew';
echo '<input type="hidden" name="task" value="'.$id.'">';
echo (new PageContentClose);
echo (new PageHtmlEnd());
}
/**
* Edit multiple tasks
*
* @ingroup pages
*/
function TaskEditMultiple()
{
global $PH;
$task_ids= getPassedIds('tsk','tasks_*');
if(!$task_ids) {
$PH->abortWarning(__("Select some tasks to move"));
exit();
}
$count = 0;
$count_subtasks = 0;
$errors = 0;
$last_milestone_id=NULL;
$different_milestones=false;
$last_status=NULL;
$different_status=false;
$project= NULL;
$tasks= array();
$task_assignments = array();
$task_assignments_count = array();
$different_assignments = false;
$edit_fields=array(
'category',
'prio',
'status',
'for_milestone',
'resolved_version',
'resolve_reason',
'label',
'pub_level'
);
$different_fields=array(); # hash containing fieldnames which are different in tasks
$count=0;
foreach($task_ids as $id) {
if($task= Task::getEditableById($id)) {
$tasks[]= $task;
## get assigned persons ##
if($task_persons = $task->getAssignedPersons(false))
{
$counter = 0;
foreach($task_persons as $tp){
$task_assignments[$task->id][$counter++] = $tp->id;
}
$task_assignments_count[$task->id] = count($task_persons);
}
## if nobody is assigned
else{
$task_assignments[$task->id][0] = '__none__';
$task_assignments_count[$task->id] = 0;
}
### check project for first task
if(count($tasks) == 1) {
### make sure all are of same project ###
if(!$project = Project::getVisibleById($task->project)) {
$PH->abortWarning('could not get project');
}
}
else {
if($task->project != $tasks[0]->project) {
$PH->abortWarning(__("For editing all tasks must be of same project."));
}
foreach($edit_fields as $field_name) {
if($task->$field_name !== $tasks[0]->$field_name) {
$different_fields[$field_name]= true;
}
}
## check if tasks have different persons assigned ##
if($task_assignments_count[$tasks[0]->id] != $task_assignments_count[$task->id]){
$different_assignments = true;
}
else{
for($i = 0; $i < $task_assignments_count[$tasks[0]->id]; $i++){
if($task_assignments[$tasks[0]->id][$i] != $task_assignments[$task->id][$i]){
$different_assignments = true;
}
}
}
}
}
}
### set up page and write header ####
{
$page= new Page(array('use_jscalendar'=>true));
$page->cur_tab='projects';
$page->options[]= new naviOption(array(
'target_id' =>'taskEdit',
));
$page->type= __("Edit multiple tasks","Page title");
$page->title= sprintf(__("Edit %s tasks","Page title"), count($tasks));
echo(new PageHeader);
}
echo (new PageContentOpen);
### write form #####
{
require_once(confGet('DIR_STREBER') . 'render/render_form.inc.php');
global $g_status_names;
echo "<ol>";
foreach($tasks as $t) {
echo "<li>" . $t->getLink(false). "</li>";
}
echo "</ol>";
$form=new PageForm();
$form->button_cancel=true;
#$form->add($tasks[0]->fields['name']->getFormElement(&$tasks[0]));
#$form->add($tasks[0]->fields['short']->getFormElement(&$tasks[0]));
### category ###
{
$a= array();
global $g_tcategory_names;
foreach($g_tcategory_names as $s=>$n) {
$a[$s]=$n;
}
if(isset($different_fields['category'])) {
$a['__dont_change__']= ('-- ' . __('keep different'). ' --');
$form->add(new Form_Dropdown('task_category',__("Category"),array_flip($a), '__dont_change__'));
}
else {
$form->add(new Form_Dropdown('task_category',__("Category"),array_flip($a), $tasks[0]->category));
}
}
### status ###
{
$st=array();
foreach($g_status_names as $s => $n) {
if($s >= STATUS_NEW) {
$st[$s]=$n;
}
}
if(isset($different_fields['status'])) {
$st['__dont_change__']= ('-- ' . __('keep different'). ' --');
#$st[('-- ' . __('keep different'). ' --')]= '__dont_change__';
$form->add(new Form_Dropdown('task_status',__("Status"),array_flip($st), '__dont_change__'));
}
else {
$form->add(new Form_Dropdown('task_status',__("Status"),array_flip($st), $tasks[0]->status));
}
}
### public-level ###
if(($pub_levels=$task->getValidUserSetPublicLevels())
&& count($pub_levels)>1) {
if(isset($different_fields['pub_level'])) {
$pub_levels[('-- ' . __('keep different'). ' --')]= '__dont_change__';
$form->add(new Form_Dropdown('task_pub_level', __("Publish to"),$pub_levels, '__dont_change__'));
}
else {
$form->add(new Form_Dropdown('task_pub_level', __("Publish to"),$pub_levels,$tasks[0]->pub_level));
}
}
### labels ###
$labels=array(__('undefined') => 0);
$counter= 1;
foreach(explode(",",$project->labels) as $l) {
$labels[$l]=$counter++;
}
if(isset($different_fields['label'])) {
$labels[('-- ' . __('keep different'). ' --')]= '__dont_change__';
$form->add(new Form_Dropdown('task_label', __("Label"),$labels, '__dont_change__'));
}
else {
$form->add(new Form_Dropdown('task_label', __("Label"),$labels,$tasks[0]->label));
}
### prio ###
{
global $g_prio_names;
$pr= array();
foreach($g_prio_names as $key => $value) {
$pr[$key]= $value;
}
if(isset($different_fields['prio'])) {
$pr['__dont_change__']= ('-- ' . __('keep different'). ' --');
$form->add(new Form_Dropdown('task_prio',__("Prio"),array_flip($pr), '__dont_change__'));
}
else {
$form->add(new Form_Dropdown('task_prio',__("Prio"),array_flip($pr), $tasks[0]->prio));
}
}
### milestone ###
{
$grouped_milestone_options= $project->buildPlannedForMilestoneList();
if(isset($different_fields['for_milestone'])) {
$grouped_milestone_options[NO_OPTION_GROUP]['__dont_change__']= ('-- ' . __('keep different'). ' --');
$form->add(new Form_DropdownGrouped(
'task_for_milestone',
__('For Milestone'),
$grouped_milestone_options,
'__dont_change__'
));
}
else {
$form->add(new Form_DropdownGrouped(
'task_for_milestone',
__('For Milestone'),
$grouped_milestone_options,
$tasks[0]->for_milestone
));
}
}
### resolved_version ###
{
$grouped_resolve_options= $project->buildResolvedInList();
if(isset($different_fields['resolved_version'])) {
$grouped_resolve_options[NO_OPTION_GROUP]['__dont_change__']= ('-- ' . __('keep different'). ' --');
$form->add(new Form_DropdownGrouped(
'task_resolved_version',
__('resolved in Version'),
$grouped_resolve_options,
'__dont_change__'
));
}
else {
$form->add(new Form_DropdownGrouped(
'task_resolved_version',
__('resolved in Version'),
$project->buildResolvedInList(),
$tasks[0]->resolved_version
));
}
}
### resolve reason ###
{
global $g_resolve_reason_names;
$rr= array();
foreach($g_resolve_reason_names as $key => $value) {
$rr[$key]= $value;
}
if(isset($different_fields['resolve_reason'])) {
$rr['__dont_change__']= ('-- ' . __('keep different') . ' --');
$form->add(new Form_Dropdown('task_resolve_reason',__("Resolve Reason"),array_flip($rr), '__dont_change__'));
}
else {
$form->add(new Form_Dropdown('task_resolve_reason',__("Resolve Reason"),array_flip($rr), $tasks[0]->resolve_reason));
}
}
## assignement ##
{
$ass = array();
$ass_also = array();
## get project team ##
if($proj_persons = $project->getPersons()){
foreach($proj_persons as $pp){
$ass[$pp->id] = $pp->name;
$ass_also[$pp->id] = $pp->name;
}
}
## different persons assigend? ##
if($different_assignments){
$ass['__dont_change__'] = ('-- ' . __('keep different') . ' --');
$form->add(new Form_Dropdown('task_assignement_diff', __('Assigned to'), array_flip($ass), '__dont_change__'));
$ass_also['__select_person__'] = ('-- ' . __('select person') . ' --');
$form->add(new Form_Dropdown('task_assignement_also_diff', __('Also assigned to'), array_flip($ass_also), '__select_person__'));
}
else{
$ass['__none__'] = ('-- ' . __('none') . ' --');
foreach($task_assignments[$tasks[0]->id] as $key=>$value)
{
$form->add(new Form_Dropdown('task_assign_to_'.$task_assignments[$tasks[0]->id][$key], __('Assigned to'), array_flip($ass), $task_assignments[$tasks[0]->id][$key]));
}
$ass_also['__select_person__'] = ('-- ' . __('select person') . ' --');
$form->add(new Form_Dropdown('task_assign_to_0', __('Also assigned to'), array_flip($ass_also), '__select_person__'));
}
}
foreach($tasks as $t) {
$form->add(new Form_HiddenField("tasks_{$t->id}_chk",'',1));
}
$form->add(new Form_HiddenField('different_ass','',$different_assignments));
#$form->add(new Form_HiddenField('task_project','',$project->id));
echo($form);
$PH->go_submit= 'taskEditMultipleSubmit';
if($return=get('return')) {
echo "<input type=hidden name='return' value='$return'>";
}
}
echo (new PageContentClose);
echo (new PageHtmlEnd);
exit();
}
/**
* Submit changes to multiple tasks
*
* @ingroup pages
*/
function taskEditMultipleSubmit()
{
global $PH;
$ids= getPassedIds('tsk','tasks_*');
if(!$ids) {
$PH->abortWarning(__("Select some task(s) to mark as approved"), ERROR_NOTE);
return;
}
$count=0;
$errors=0;
$number = get('number');
### cancel? ###
if(get('form_do_cancel')) {
if(!$PH->showFromPage()) {
$PH->show('home');
}
exit();
}
foreach($ids as $id) {
if($task= Task::getEditableById($id)) {
$count++;
$change= false;;
$status_old= $task->status;
### status ###
if($count == 1){
if(!$project = Project::getVisibleById($task->project)) {
$PH->abortWarning('could not get project');
}
$team= array();
foreach($project->getPersons() as $p) {
$team[$p->id]= $p;
}
}
### assignment ###
{
$task_assigned_persons = array();
$task_assignments = array();
$task_persons_overwrite = array();
$task_persons_new = array();
$task_persons_delete = array();
## previous assigend persons ##
if($task_persons = $task->getAssignedPersons(false))
{
foreach($task_persons as $tp){
$task_assigned_persons[$tp->id] = $tp;
}
}
## previous assignements ##
if($task_assign = $task->getAssignments())
{
foreach($task_assign as $ta){
$task_assignments[$ta->person] = $ta;
}
}
## different assigned persons ##
## overwrite ?? ##
$ass1 = get('task_assignement_diff');
if($ass1 && $ass1 != '__dont_change__'){
$task_persons_overwrite[] = $ass1;
foreach($task_assignments as $key=>$value){
$task_persons_delete[] = $value;
}
$change = true;
}
## new ?? ##
$ass2 = get('task_assignement_also_diff');
if($ass2 && $ass2 != '__select_person__'){
$task_persons_new[] = $ass2;
$change = true;
}
$different = get('different_ass');
if(isset($different) && !$different){
if(isset($task_assignments) && count($task_assignments) != 0){
foreach($task_assignments as $tid=>$t_old){
$id_new = get('task_assign_to_'.$tid);
## no changes ##
if($tid == $id_new){
continue;
}
if($id_new == '__none__'){
if(!$t_old){
continue;
}
$task_persons_delete[] = $t_old;
continue;
}
$task_persons_delete[] = $t_old;
$task_persons_overwrite[] = $id_new;
}
}
else{
$id_new = get('task_assign_to___none__');
if($id_new && $id_new != '__none__'){
$task_persons_new[] = $id_new;
}
}
$id_new = get('task_assign_to_0');
if($id_new != '__select_person__'){
if(!isset($task_assignments[$id_new])){
$task_persons_new[] = $id_new;
}
}
$change = true;
}
}
### category ###
$v= get('task_category');
if(!is_null($v) && $v != '__dont_change__' && $v != $task->category) {
$task->category= $v;
$change= true;
}
### status ###
$status= get('task_status');
if($status && $status != '__dont_change__' && $status != $task->status) {
$task->status= $status;
$change= true;
}
### prio ###
$prio= get('task_prio');
if($prio && $prio != '__dont_change__' && $prio != $task->prio) {
$task->prio= $prio;
$change= true;
}
### pub level ###
$pub_level= get('task_pub_level');
if($pub_level && $pub_level != '__dont_change__' && $pub_level != $task->pub_level) {
if($pub_level > $task->getValidUserSetPublicLevel() ) {
$PH->abortWarning('invalid data',ERROR_RIGHTS);
}
$task->pub_level= $pub_level;
$change= true;
}
### label ###
$label= get('task_label');
if($label && $label != '__dont_change__' && $label != $task->label) {
$task->label= $label;
$change= true;
}
### for milestone ###
$fm= get('task_for_milestone');
if(!is_null($fm) && $fm != '__dont_change__' && $task->for_milestone != $fm) {
if($fm) {
if(($m= Task::getVisibleById($fm)) && $m->isMilestoneOrVersion()) {
$task->for_milestone= $fm;
$change= true;
}
else {
continue;
}
}
else {
$task->for_milestone= 0;
$change= true;
}
}
### resolve version ###
$rv= get('task_resolved_version');
if((!is_null($rv)) && ($rv != '__dont_change__') && ($task->resolved_version != $rv)) {
if($rv && $rv != -1) {
if($v= Task::getVisibleById($rv)) {
if($v->isMilestoneOrVersion()) {
$task->resolved_version= $rv;
$change= true;
}
}
else {
continue;
}
}
else {
if($rv == -1) {
$task->resolved_version= $rv;
$change= true;
}
else {
$task->resolved_version= 0;
$change= true;
}
}
}
### resolve reason ###
$rs= get('task_resolve_reason');
if($rs && $rs != '__dont_change__' && $rs != $rs->resolve_reason) {
$task->resolve_reason= $rs;
$change= true;
}
if($change) {
### Check if now longer new ###
if($status_old == $task->status && $task->status == STATUS_NEW) {
global $auth;
if($task->created < $auth->cur_user->last_login) {
$task->status = STATUS_OPEN;
}
}
## overwrite assigend persons ##
if(isset($task_persons_overwrite)){
if(isset($task_persons_delete)){
foreach($task_persons_delete as $tpd){
$tpd->delete();
}
}
foreach($task_persons_overwrite as $tpo)
{
$task_pers_over = new TaskPerson(array(
'person'=> $team[$tpo]->id,
'task' => $task->id,
'comment'=>'',
'project'=>$project->id,
));
$task_pers_over->insert();
}
}
## add new person ##
if(isset($task_persons_new)){
foreach($task_persons_new as $tpn){
if(!isset($task_assigned_persons[$tpn]))
{
$task_pers_new = new TaskPerson(array(
'person'=> $team[$tpn]->id,
'task' => $task->id,
'comment'=>'',
'project'=>$project->id,
));
$task_pers_new->insert();
}
}
}
##update##
$task->update();
$task->nowChangedByUser();
}
}
else {
$errors++;
}
}
### compose message ###
if($errors) {
new FeedbackWarning(sprintf(__('%s tasks could not be written'), $errors));
}
else if($count) {
new FeedbackMessage(sprintf(__('Updated %s tasks tasks'), $count));
}
### return to from-page? ###
if(!$PH->showFromPage()) {
$PH->show('taskView',array('tsk'=>$task->id));
}
}
/**
* Collapse all comments of a tasks
*
* @ingroup pages
*/
function taskCollapseAllComments()
{
global $PH;
/**
* because there are no checkboxes left anymore, we have to get the comment-ids
* directly from the task with the getComments-function
**/
### get task ###
$tsk=get('tsk');
### check sufficient user-rights ###
if($task=Task::getEditableById($tsk)) {
$ids= $task->getComments();
foreach($ids as $obj) {
if(!$comment=Comment::getEditableById($obj->id)) {
$PH->abortWarning('undefined comment','warning');
}
if(! $comment->view_collapsed) {
$comment->view_collapsed=1;
$comment->update();
}
}
}
else {
/**
* a better way should be not to display this function
* if user has not enough rights
**/
### abort, if not enough rights ###
$PH->abortWarning(__('insufficient rights'),ERROR_RIGHTS);
}
### display taskView ####
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
/**
* Expand all comments of a task
*
* @ingroup pages
*/
function taskExpandAllComments()
{
global $PH;
/**
* because there are no checkboxes left anymore, we have to get the comment-ids
* directly from the task with the getComments-function
**/
### get task ###
$tsk= get('tsk');
### check sufficient user-rights ###
if($task=Task::getEditableById($tsk)) {
$ids= $task->getComments();
foreach($ids as $obj) {
if(!$comment=Comment::getEditableById($obj->id)) {
$PH->abortWarning('undefined comment','warning');
}
### get all comments including all sub-comments
$list= $comment->getAll();
$list[]= $comment;
foreach($list as $c) {
if($c->view_collapsed) {
$c->view_collapsed=0;
$c->update();
}
}
}
}
else {
/**
* a better way should be not to display this function
* if user has not enough rights
**/
### abort, if not enough rights ###
$PH->abortWarning(__('insufficient rights'),ERROR_RIGHTS);
}
### display taskView ####
if(!$PH->showFromPage()) {
$PH->show('home');
}
}
/**
* create new note on person
*
* @ingroup pages
*/
function taskNoteOnPersonNew()
{
global $PH;
## get person ##
$pid = getOnePassedId('person');
if(!$person = Person::getById($pid)){
$PH->abortWarning(__("ERROR: could not get Person"), ERROR_NOTE);
return;
}
## build new object ##
$task_new = new Task(array(
'id' =>0, # temporary new
'name' =>'',
'state' =>1,
));
$PH->show('taskNoteOnPersonEdit',array('tsk'=>$task_new->id, 'person'=>$person->id), $task_new);
}
/**
* Edit note on person
*
* @ingroup pages
*/
function taskNoteOnPersonEdit($task=NULL, $person=NULL)
{
global $PH;
global $auth;
global $g_pub_level_names;
global $g_prio_names;
if(!$task){
$id = getOnePassedId('tsk');
if(!$task = Task::getEditableById($id)) {
$PH->abortWarning(__("Select a note to edit"), ERROR_NOTE);
return;
}
}
## get person ##
if(!$person){
$pid = getOnePassedId('person');
if(!$person = Person::getById($pid)) {
$PH->abortWarning(__("ERROR: could not get Person"), ERROR_NOTE);
return;
}
}
### set up page and write header ####
{
$page = new Page(array('use_jscalendar'=>false, 'autofocus_field'=>'task_name'));
$page->cur_tab = 'people';
if($person->id) {
$page->crumbs=build_person_crumbs($person);
}
$page->crumbs[]=new NaviCrumb(array(
'target_id' => 'taskNoteOnPersonEdit',
));
$page->type=__("Note");
if(!$task->id) {
$page->title = __('Create new note');
$page->title_minor=__('Edit');
## default title ##
$date = gmdate("Y-m-d", time());
$time = getGMTString();
$dt = $date . " " . renderTime($time);
$task->name = sprintf(__("New Note on %s, %s"),$person->name, $dt);
}
## eventually needed later when note is a subcategory of task
/*else {
$page->title=$task->name;
$page->title_minor=$task->short;
}*/
echo(new PageHeader);
}
echo (new PageContentOpen);
### write form #####
{
require_once(confGet('DIR_STREBER') . 'render/render_form.inc.php');
$form = new PageForm();
$form->button_cancel=true;
## name field ##
$form->add($task->fields['name']->getFormElement(&$task));
## description field ##
$e = $task->fields['description']->getFormElement(&$task);
$e->rows = 22;
$form->add($e);
### public-level drop down menu ###
$form->add(new Form_Dropdown('task_pub_level', __("Publish to","Form label"), array_flip($g_pub_level_names), $task->pub_level));
## priority drop down menu##
$form->add(new Form_Dropdown('task_prio', __("Prio","Form label"), array_flip($g_prio_names), $task->prio));
## project drop down menu ##
{
if($task->id == 0){
$proj_select = 0;
}
## eventually needed later when note is a subcategory of task
/*else {
if(!$project = $task->getProject()){
$PH->abortWarning(__("ERROR: could not get project"), ERROR_NOTE);
$proj_select = 0;
}
else{
$proj_select = $project->id;
}
}*/
$p_list = array();
#$p_list[0] = __('Assigned Projects');
$count = 1;
$p_projects = $person->getProjects();
$num = count($p_projects);
/*if($num == 0){
$p_list['-1'] = __('- no assigend projects');
}
else{*/
if($num > 0){
$p_list[0] = __('Assigned Projects');
foreach($p_projects as $pp){
$p_list[$pp->id] = "- " . $pp->name;
$count++;
}
}
#$p_list['-3'] = __('Company Projects');
$p_companies = $person->getCompanies();
$num = count($p_companies);
/*if($num == 0){
$p_list['-4'] = __('- no company projects');
}
elseif($num == 1){
$c_id = $p_companies[0]->id;
$c_projects = Project::getAll(array('company'=>$c_id));
foreach($c_projects as $cp){
$p_list[$cp->id] = "- " . $cp->name;
}
}
else*/if($num > 0){
$p_list['-1'] = __('Company Projects');
foreach($p_companies as $pcs){
$c_id = $pcs->id;
$c_projects = Project::getAll(array('company'=>$c_id));
$count2 = 0;
foreach($c_projects as $cp){
$p_list[$cp->id] = "- " . $cp->name;
}
}
}
#$p_list['-5'] = __('All other Projects');
if(!$projects = Project::getAll(array('order_by'=>'name ASC'))){
#$p_list['-6'] = __('- no other projects');
}
else{
$p_list['-2'] = __('All other Projects');
foreach($projects as $pj){
$p_list[$pj->id] = "- " . $pj->name;
}
}
$form->add(new Form_Dropdown('project', __('For Project','form label'),array_flip($p_list), $proj_select, "id='proj_list'"));
}
## new project ##
if($task->id == 0){
$form->add(new Form_checkbox('new_project',__('New project','form label'), false, "id='proj_new_checkbox'"));
$form->add(new Form_Input('new_project_name', __('Project name', 'form label'),false,NULL,false, "id='proj_new_input'","style='display:none'"));
}
## Assignements ##
{
$checked1 = "";
$checked2 = "";
if($task->id == 0){
$checked1 = "checked";
$checked2 = "checked";
$person_select = -1;
}
## eventually needed later when note is a subcategory of task
/*else {
if(!$pperson = $task->getAssignedPersons()){
$PH->abortWarning(__("ERROR: could not get assigned persons"), ERROR_NOTE);
}
else{
foreach($pperson as $pp){
if($pp->id == $person->id){
$checked1= "checked";
}
elseif($pp->id == $auth->cur_user->id){
$checked2= "checked";
}
else{
$person_select = $pp->id;
}
}
}
}*/
$form->add(new Form_customHTML('<p><label>' . __('Assign to') . '</lable></p>', 'assigne_note'));
if($person->id != $auth->cur_user->id){
$form->add(new Form_customHTML('<span class="checker"><input value="'.$person->id.'" name="task_assignement1" type="checkbox" ' . $checked1 .'><label for="task_assignement1">' . $person->name . '</label></span>', 'assigned_person1'));
$form->add(new Form_customHTML('<span class="checker"><input value="'.$auth->cur_user->id.'" name="task_assignement2" type="checkbox" ' . $checked2 .'><label for="task_assignement2">' . $auth->cur_user->name . '</label></span>', 'assigned_person2'));
}
else {
$form->add(new Form_customHTML('<span class="checker"><input value="'.$auth->cur_user->id.'" name="task_assignement2" type="checkbox" ' . $checked2 .'><label for="task_assignement2">' . $auth->cur_user->name . '</label></span>', 'assigned_person'));
}
$pers_list = array();
$pers_list[-1] = __('undefined');
if($persons = Person::getPersons(array('can_login'=>1))){
foreach($persons as $pers){
if($auth->cur_user->name <> $pers->name) {
$pers_list[$pers->id] = $pers->name;
}
}
}
$form->add(new Form_Dropdown('task_also_assign', __('Also assign to') ,array_flip($pers_list), $person_select));
}
## Book effort after submit ##
$form->form_options[] = "<span class=option><input id='book_effort' name='book_effort' class='checker' type=checkbox>" . __("Book effort after submit") . "</span>";
$form->add(new Form_HiddenField('tsk','',$task->id));
$form->add(new Form_HiddenField('person_id','',$person->id));
$form->add(new Form_HiddenField('creation_time','',$time));
echo ($form);
$PH->go_submit = 'taskNoteOnPersonEditSubmit';
}
echo (new PageContentClose);
echo (new PageHtmlEnd);
}
/**
* Submit changes to notes on a person
*
* @ingroup pages
*/
function taskNoteOnPersonEditSubmit()
{
global $PH;
global $auth;
global $g_user_profile_names;
### cancel? ###
if(get('form_do_cancel')) {
if(!$PH->showFromPage()) {
$PH->show('personView',array('person'=>getOnePassedId('person_id')));
}
exit();
}
### temporary object or from database? ###
$tsk_id = getOnePassedId('tsk','',true,'invalid id');
if($tsk_id == 0) {
$task = new Task(array(
'id'=>0,
));
}
## eventually needed later when note is a subcategory of task
/*else {
if(!$task= Task::getVisiblebyId($tsk_id)) {
$PH->abortWarning(__("ERROR: could not get task"), ERROR_NOTE);
return;
}
}*/
## other parameter ##
$person_id = getOnePassedId('person_id');
$prj_id = get('project');
$prj_new = get('new_project');
$prj_name = get('new_project_name');
$assignement1 = get('task_assignement1');
$assignement2 = get('task_assignement2');
$also_assignement = get('task_also_assign');
### pub level ###
if($pub_level = get('task_pub_level')) {
if($task->id) {
if($pub_level > $task->getValidUserSetPublicLevels() ) {
$PH->abortWarning('invalid data',ERROR_RIGHTS);
}
}
#else {
# #@@@ check for person create rights
#}
$task->pub_level = $pub_level;
}
## prio ##
if($prio = get('task_prio')){
$task->prio = $prio;
}
## status ##
if(!$task->id){
$task->status = STATUS_NEW;
}
# retrieve all possible values from post-data (with field->view_in_forms == true)
# NOTE:
# - this could be an security-issue.
# @@@ TODO: as some kind of form-edit-behaviour to field-definition
foreach($task->fields as $f) {
$name=$f->name;
$f->parseForm(&$task);
}
### validate ###
$is_ok = true;
## no project ##
if(($prj_id <= 0)) {
if(((!isset($prj_new)) || (!isset($prj_name)))){
new FeedbackWarning(__("Note requires project"));
## and no assignement ##
if((!isset($assignement1) && !isset($assignement2) && $also_assignement == -1)) {
new FeedbackWarning(__("Note requires assigned person(s)"));
}
$is_ok= false;
}
}
## if project but no assignement ##
if((!isset($assignement1) && !isset($assignement2) && $also_assignement == -1)) {
$assignement1 = $auth->cur_user->id;
}
if(!$is_ok) {
$PH->show('taskNoteOnPersonEdit',array('tsk'=>$task->id, 'person'=>$person_id), $task);
exit();
}
## new project
if(isset($prj_new) && isset($prj_name)){
$pperson = Person::getById($person_id);
if($companies = $pperson->getCompanies()) {
$company_id= $companies[0]->id;
}
else {
$company_id= 0;
}
$new_project = new Project(array(
'name'=>$prj_name,
'company'=>$company_id,
'status'=>STATUS_NEW,
'prio'=>PRIO_NORMAL,
'pub_level'=>PUB_LEVEL_OPEN
));
$new_project->insert();
$prj_id = $new_project->id;
## get project ##
if(!$project = Project::getById($prj_id)){
$PH->abortWarning(__("ERROR: could not get project"), ERROR_NOTE);
}
}
else {
## get project ##
if(!$project = Project::getById($prj_id)){
$PH->abortWarning(__("ERROR: could not get project"), ERROR_NOTE);
}
}
## set project of task ##
if(!$task->id){
$task->project = $project->id;
}
## assigne persons to task##
$new_task_assignments = array();
$count = 0;
if(!$task->id){
if(isset($assignement1)){
$person = Person::getById($assignement1);
$new_assignment1 = new TaskPerson(array(
'person'=> $assignement1,
'task' => $task->id,
'comment'=>sprintf(__("formerly assigned to %s","task-assigment comment"), $person->name),
'project'=>$project->id,
));
$new_task_assignments[$count] = $new_assignment1;
$count++;
}
if(isset($assignement2)){
$person = Person::getById($assignement2);
$new_assignment2 = new TaskPerson(array(
'person'=> $assignement2,
'task' => $task->id,
'comment'=>sprintf(__("formerly assigned to %s","task-assigment comment"), $person->name),
'project'=>$project->id,
));
$new_task_assignments[$count] = $new_assignment2;
$count++;
}
if($also_assignement != -1){
$person = Person::getById($also_assignement);
$new_assignment_also = new TaskPerson(array(
'person'=> $also_assignement,
'task' => $task->id,
'comment'=>sprintf(__("formerly assigned to %s","task-assigment comment"), $person->name),
'project'=>$project->id,
));
$new_task_assignments[$count] = $new_assignment_also;
$count++;
}
}
## eventually needed later when note is a subcategory of task
/*else {
# ToDo: check if persons are assigned
}*/
## assigne person to project ##
$team = array();
$new_project_assignments = array();
$count = 0;
if(!$task->id){
$projperson = $project->getPersons(false);
foreach($projperson as $projp){
$team[$projp->id] = $projp->name;
}
if(isset($assignement1)){
if(!isset($team[$assignement1])){
$person = Person::getById($assignement1);
$effort_style = ($person->settings & USER_SETTING_EFFORTS_AS_DURATION)
? 2
: 1;
$pp_new1 = new ProjectPerson(array(
'person' => $person->id,
'project' => $project->id,
'name' => $g_user_profile_names[$person->profile],
'adjust_effort_style' => $effort_style,
));
$new_project_assignments[$count] = $pp_new1;
$count++;
}
}
if(isset($assignement2)){
if(!isset($team[$assignement2])){
$effort_style = ($person->settings & USER_SETTING_EFFORTS_AS_DURATION)
? 2
: 1;
$person = Person::getById($assignement2);
$pp_new2 = new ProjectPerson(array(
'person' => $person->id,
'project' => $project->id,
'name' => $g_user_profile_names[$person->profile],
'adjust_effort_style' => $effort_style,
));
$new_project_assignments[$count] = $pp_new2;
$count++;
}
}
if($also_assignement != -1){
if(!isset($team[$also_assignement])){
$person = Person::getById($also_assignement);
$effort_style = ($person->settings & USER_SETTING_EFFORTS_AS_DURATION)
? 2
: 1;
$pp_new_also = new ProjectPerson(array(
'person' => $person->id,
'project' => $project->id,
'name' => $g_user_profile_names[$person->profile],
'adjust_effort_style' => $effort_style,
));
$new_project_assignments[$count] = $pp_new_also;
$count++;
}
}
}
## eventually needed later when note is a subcategory of task
/*else{
# ToDo: check if persons are assigned
}*/
## Insert ##
if($task->id == 0) {
$task->insert();
### write task-assigments ###
foreach($new_task_assignments as $nta) {
$nta->task = $task->id;
$nta->insert();
}
### write project-assigments ###
foreach($new_project_assignments as $npa) {
$npa->insert();
}
new FeedbackMessage(sprintf(__("Created task %s with ID %s"), $task->getLink(false),$task->id));
}
## eventually needed later when note is a subcategory of task
/*
else{
}
*/
### book effort ###
$book_effort = get('book_effort');
if($book_effort) {
$as_duration = 0;
if($pperson = $project->getProjectPersons()){
foreach($pperson as $pp){
if(($pp->project == $project->id) && ($pp->person == $auth->cur_user->id)){
if($pp->adjust_effort_style == 1){
$as_duration = 0;
}
else{
$as_duration = 1;
}
}
}
}
else{
$as_duration = 0;
}
if(get('creation_time')){
$start_time = get('creation_time');
}
else{
$start_time = '';
}
### build new object ###
$newEffort= new Effort(array(
'id' =>0,
'name' =>'',
'project' =>$project->id,
'task' =>$task->id,
'person' =>$auth->cur_user->id,
'as_duration' =>$as_duration,
'time_start' =>$start_time,
)
);
$PH->show('effortEdit',array('effort'=>$newEffort->id),$newEffort);
exit();
}
### display personList ####
if(!$PH->showFromPage()) {
$PH->show('personList',array());
}
}
/** @} */
?>