Example #1
0
 /**
  * go through all accounts and collect information
  *
  * returns array of count of... [$num_notification_sent, $num_warnings]
  */
 public static function sendNotifications()
 {
     global $PH;
     $people = Person::getPeople(array('visible_only' => false, 'can_login' => true));
     $num_notifications_sent = 0;
     $num_warnings = 0;
     foreach ($people as $p) {
         if ($p->settings & USER_SETTING_NOTIFICATIONS) {
             if ($p->office_email || $p->personal_email) {
                 $now = time();
                 $last = strToGMTime($p->notification_last);
                 $period = $p->notification_period * 60 * 60 * 24;
                 if (strToGMTime($p->notification_last) + $period < time() || $period == -1) {
                     $email = new EmailNotification($p);
                     if ($email->information_count) {
                         $result = $email->send();
                         if ($result === true) {
                             ### reset activation-flag ###
                             $p->settings &= USER_SETTING_SEND_ACTIVATION ^ RIGHT_ALL;
                             $p->notification_last = gmdate("Y-m-d H:i:s");
                             $p->update();
                             $num_notifications_sent++;
                         } else {
                             if ($result !== false) {
                                 $num_warnings++;
                                 new FeedbackWarning(sprintf(__('Failure sending mail: %s'), $result));
                             }
                         }
                     }
                 }
             }
         }
     }
     return array($num_notifications_sent, $num_warnings);
 }
Example #2
0
 static function RateItem($item)
 {
     $rate = 1;
     $age = time() - strToGMTime($item->modified);
     if ($age < 24 * 60 * 60 * 20) {
         $rate *= RATE_MODIFIED_20_DAYS_AGO;
     } else {
         if ($age < 62 * 60 * 60 * 20) {
             $rate *= RATE_MODIFIED_2_MONTHS_AGO;
         }
     }
     if ($item->state != 1) {
         $rate *= $rate_deleted;
     }
     if ($item->project && ($project = Project::getById($item->project))) {
         if ($project->status == STATUS_TEMPLATE) {
             $rate *= RATE_PROJECT_IS_TEMPLATE;
         } else {
             if ($project->status <= STATUS_OPEN) {
                 $rate *= RATE_PROJECT_IS_OPEN;
             } else {
                 if ($project->status > STATUS_COMPLETED) {
                     $rate *= RATE_PROJECT_IS_CLOSED;
                 }
             }
         }
     }
     return $rate;
 }
/**
* export selected efforts as a CSV ready for copy and paste into a spread-sheet  @ingroup pages
**
*/
function effortShowAsCSV()
{
    global $PH;
    global $g_effort_status_names;
    $effort_ids = getPassedIds('effort', 'efforts_*');
    if (!$effort_ids) {
        $PH->abortWarning(__("Select some efforts(s) to show"));
        exit;
    }
    $efforts = array();
    $different_fields = array();
    $edit_fields = array('status', 'pub_level', 'task');
    foreach ($effort_ids as $id) {
        if ($effort = Effort::getEditableById($id)) {
            $efforts[] = $effort;
            ### check project for first task
            if (count($efforts) == 1) {
                ### make sure all are of same project ###
                if (!($project = Project::getVisibleById($effort->project))) {
                    $PH->abortWarning('could not get project');
                }
            } else {
                if ($effort->project != $efforts[0]->project) {
                    $PH->abortWarning(__("For editing all efforts must be of same project."));
                }
                foreach ($edit_fields as $field_name) {
                    if ($effort->{$field_name} != $efforts[0]->{$field_name}) {
                        $different_fields[$field_name] = true;
                    }
                }
            }
        }
    }
    $page = new Page(array('use_jscalendar' => true));
    $page->cur_tab = 'projects';
    $page->options[] = new naviOption(array('target_id' => 'effortEdit'));
    $page->type = __("Edit multiple efforts", "Page title");
    $page->title = sprintf(__("%s efforts for copy and pasting into a spread-sheet", "Page title"), count($efforts));
    echo new PageHeader();
    echo new PageContentOpen();
    $block = new PageBlock(array('id' => 'functions', 'reduced_header' => true));
    $block->render_blockStart();
    $format = "[Date][Weekday][Task][Comment][Duration]";
    preg_match_all("/\\[(.*?)\\]/", $format, $matches);
    $overallDuration = 0;
    echo "<textarea style='width:96%; height:300px;'>";
    echo join("\t", $matches[1]) . "\n";
    foreach ($efforts as $e) {
        preg_match_all("/\\[(.*?)\\]/", $format, $matches);
        $separator = "";
        foreach ($matches[1] as $matchedFormat) {
            echo $separator;
            switch ($matchedFormat) {
                case "Date":
                    echo gmstrftime("%Y-%m-%d", strToGMTime($e->time_start));
                    break;
                case "Weekday":
                    echo gmstrftime("%a", strToGMTime($e->time_start));
                    break;
                case "Task":
                    if ($t = Task::getVisibleById($e->task)) {
                        echo $t->name;
                    }
                    break;
                case "Comment":
                    echo $e->name;
                    break;
                case "Duration":
                    $durationInMinutes = round((strToGMTime($e->time_end) - strToGMTime($e->time_start)) / 60, 0);
                    $roundUpTo15 = ceil($durationInMinutes / 15) * 15 / 60;
                    $overallDuration += $roundUpTo15;
                    echo number_format($roundUpTo15, 2, $dec_point = ',', '');
                    break;
            }
            $separator = "\t";
        }
        echo "\n";
    }
    echo "</textarea>";
    echo "<br>";
    echo __("Overall Duration:") . $overallDuration . "h";
    $block->render_blockEnd();
    echo new PageContentClose();
    echo new PageHtmlEnd();
    exit;
}
 function render_tr(&$item, $style = "")
 {
     if ($ip = ItemPerson::getAll(array('item' => $item->id, 'notify_if_unchanged_min' => NOTIFY_1DAY))) {
         $period = '';
         switch ($ip[0]->notify_if_unchanged) {
             case NOTIFY_1DAY:
                 $period = 24 * 60 * 60;
                 break;
             case NOTIFY_2DAYS:
                 $period = 2 * 24 * 60 * 60;
                 break;
             case NOTIFY_3DAYS:
                 $period = 3 * 24 * 60 * 60;
                 break;
             case NOTIFY_4DAYS:
                 $period = 4 * 24 * 60 * 60;
                 break;
             case NOTIFY_5DAYS:
                 $period = 5 * 24 * 60 * 60;
                 break;
             case NOTIFY_1WEEK:
                 $period = 7 * 24 * 60 * 60;
                 break;
             case NOTIFY_2WEEKS:
                 $period = 2 * 7 * 24 * 60 * 60;
                 break;
             case NOTIFY_3WEEKS:
                 $period = 3 * 7 * 24 * 60 * 60;
                 break;
             case NOTIFY_1MONTH:
                 $period = 4 * 7 * 24 * 60 * 60;
                 break;
             case NOTIFY_2MONTH:
                 $period = 2 * 4 * 7 * 24 * 60 * 60;
                 break;
         }
         $notify_date = $ip[0]->notify_date;
         if ($notify_date != '0000-00-00 00:00:00') {
             $send_date = strToGMTime($notify_date) + $period;
             $current_date = time();
             if ($send_date > $current_date) {
                 $days = round(($send_date - $current_date) / 60 / 60 / 24);
                 print "<td>" . sprintf(__('in %s day(s)'), $days) . "</td>";
             } else {
                 $days = round(($current_date - $send_date) / 60 / 60 / 24);
                 print "<td>" . sprintf(__('since %s day(s)'), $days) . "</td>";
             }
         } else {
             print "<td>&nbsp;</td>";
         }
     } else {
         print "<td>&nbsp;</td>";
     }
 }
Example #5
0
 /**
  * records history events in rss/rss_$project->id.xml
  *
  * must be called from a project-related page!
  *
  *
  * @param project - current project object used in: proj.inc.php <- function call
  */
 static function updateRSS($project)
 {
     global $PH;
     global $auth;
     if (!$project) {
         return NULL;
     }
     /**
      * only show changes by others
      */
     if (Auth::isAnonymousUser()) {
         $not_modified_by = NULL;
     } else {
         $not_modified_by = $auth->cur_user->id;
     }
     ### get all the changes (array of history items) ##
     $changes = ChangeLine::getChangeLines(array('project' => $project->id, 'unviewed_only' => false, 'limit_rowcount' => 20, 'type' => array(ITEM_TASK, ITEM_FILE), 'limit_offset' => 0));
     /*
     $changes= DbProjectItem::getAll(array(
         'project'           => $project->id,        # query only this project history
         'alive_only'        => false,               # get deleted entries
         'visible_only'      => false,               # ignore user viewing rights
         'limit_rowcount'    => 20,                  # show only last 20 entries in rss feed
         #'show_assignments'  => false,              # ignore simple assignment events
     ));
     */
     $url = confGet('SELF_PROTOCOL') . '://' . confGet('SELF_URL');
     # url part of the link to the task
     $from_domain = confGet('SELF_DOMAIN');
     # domain url
     if (confGet('USE_MOD_REWRITE')) {
         $url = str_replace('index.php', '', $url);
     }
     ### define general rss file settings ###
     $rss = new UniversalFeedCreator();
     $rss->title = "StreberPM: " . $project->name;
     $rss->description = "Latest Project News";
     $rss->link = "{$url}?go=projView&prj={$project->id}";
     $rss->syndicationURL = $url;
     # go through all retrieved changes and create rss feed
     foreach ($changes as $ch) {
         $item = $ch->item;
         $name_author = __('???');
         if ($person = Person::getVisibleById($item->modified_by)) {
             $name_author = $person->name;
         }
         $str_updated = '';
         if ($new = $ch->item->isChangedForUser()) {
             if ($new == 1) {
                 $str_updated = __('New');
             } else {
                 $str_updated = __('Updated');
             }
         }
         $feeditem = new FeedItem();
         $feeditem->title = $item->name . " (" . $ch->txt_what . ' ' . __("by") . ' ' . $name_author . ")";
         $feeditem->link = $url . "?go=itemView&item={$item->id}";
         $feeditem->date = gmdate("r", strToGMTime($item->modified));
         $feeditem->source = $url;
         $feeditem->author = $name_author;
         switch ($ch->type) {
             case ChangeLine::COMMENTED:
                 $feeditem->description = $ch->html_details;
                 break;
             case ChangeLine::NEW_TASK:
                 $feeditem->description = str_replace("\n", "<br>", $item->description);
                 break;
             default:
                 $feeditem->description = $ch->type . " " . str_replace("\n", "<br>", $item->description);
                 break;
         }
         $rss->addItem($feeditem);
     }
     /**
      * all history items processed ...
      * save the rss 2.0 feed to rss/rss_$project->id.xml ...
      * false stands for not showing the resulting feed file -> create in background
      */
     $rss->saveFeed("RSS2.0", "_rss/proj_{$project->id}.xml", false);
 }
Example #6
0
 function validateEditRequestTime($abort_on_failure = true)
 {
     global $PH;
     global $auth;
     if (!($edit_request_time = get('edit_request_time'))) {
         if ($abort_on_failure) {
             $PH->abortWarning("undefined edit request time", ERROR_BUG);
             exit;
         } else {
             return NULL;
         }
     }
     $last_modified = strToGMTime($this->modified);
     if ($edit_request_time < $last_modified) {
         if ($this->modified_by != $auth->cur_user->id) {
             if ($abort_on_failure) {
                 require_once confGet('DIR_STREBER') . 'db/class_person.inc.php';
                 if ($person = Person::getVisibleById($this->modified_by)) {
                     $link_person = $person->getLink();
                 } else {
                     $link_person = __('Unknown');
                 }
                 $time_ago = floor((time() - $last_modified) / 60) + 1;
                 $PH->abortWarning(sprintf(__("Item has been modified during your editing by %s (%s minutes ago). Your changes can not be submitted."), $link_person, $time_ago), ERROR_NOTE);
             } else {
                 return NULL;
             }
         }
     }
     return true;
 }
Example #7
0
 function render_tr(&$obj, $style = "")
 {
     if (!isset($obj) || !$obj instanceof Effort) {
         trigger_error("ListBlock->render_tr() called without valid object", E_USER_WARNING);
         return;
     }
     $value = round((strToGMTime($obj->time_end) - strToGMTime($obj->time_start)) / 60 / 60, 1) . "h";
     print "<td>{$value}</td>";
 }
function newEffortFromTimeTracking()
{
    global $PH;
    global $auth;
    require_once confGet('DIR_STREBER') . 'db/class_effort.inc.php';
    $time_end = intval(get('effort_end_seconds'));
    if ($time_end == 0) {
        $time_end = null;
    }
    $new_effort = new Effort(array('id' => 0, 'time_start' => getGMTString(get('effort_start_seconds')), 'time_end' => getGMTString($time_end), 'name' => get('description'), 'billing' => get('billing'), 'productivity' => get('productivity')));
    ### get project ###
    $new_effort->project = get('effort_project_id');
    if (!($project = Project::getVisibleById($new_effort->project))) {
        $PH->abortWarning(__("Could not get project of effort"));
    }
    if (!$project->isPersonVisibleTeamMember($auth->cur_user)) {
        $PH->abortWarning("ERROR: Insufficient rights");
    }
    ### link to task ###
    $task_id = get('effort_task_id');
    if (!(is_null($task_id) || $task_id == 0)) {
        if ($task_id == 0) {
            $new_effort->task = 0;
        } else {
            if ($task = Task::getVisibleById($task_id)) {
                $new_effort->task = $task->id;
            }
        }
    } else {
        if (get('task_name') != "") {
            ### create new task
            $newtask = new Task(array('id' => 0, 'name' => get('task_name'), 'project' => $project->id));
            $newtask->insert();
            $new_effort->task = $newtask->id;
        }
    }
    ### get person ###
    $new_effort->person = $auth->cur_user->id;
    ### go back to from if validation fails ###
    $failure = false;
    if (strToGMTime($new_effort->time_end) - strToGMTime($new_effort->time_start) < 0) {
        $failure = true;
        new FeedbackWarning(__("Cannot start before end."));
    }
    ### write to db ###
    $new_effort->insert();
    ### display taskView ####
    if (!$PH->showFromPage()) {
        $PH->show('projView', array('prj' => $effort->project));
    }
}
Example #9
0
 /**
  * get Open Efforts sum
  * sums up open and new efforts (e.I. everything that's not closed, balanced or not billable)
  */
 function getOpenEffortsSum()
 {
     $sum = 0.0;
     require_once confGet('DIR_STREBER') . 'db/class_effort.inc.php';
     $efforts = Effort::getAll(array('project' => $this->id, 'effort_status_max' => EFFORT_STATUS_OPEN));
     foreach ($efforts as $e) {
         $sum += 1.0 * strToGMTime($e->time_end) - 1.0 * strToGMTime($e->time_start);
     }
     return $sum;
 }
 private function addUntouchedMonitoredItems()
 {
     $unchanged_headline_html = '';
     $unchanged_headline_txt = '';
     $unchanged_body_html = '';
     $unchanged_body_plaintext = '';
     $monitored_items_unchanged = ItemPerson::getAll(array('is_bookmark' => 1, 'notify_if_unchanged_min' => NOTIFY_1DAY, 'person' => $this->recipient->id));
     if (!$monitored_items_unchanged) {
         return;
     }
     foreach ($monitored_items_unchanged as $miu) {
         ## reminder period ##
         $period = '';
         switch ($miu->notify_if_unchanged) {
             case NOTIFY_1DAY:
                 $period = 24 * 60 * 60;
                 break;
             case NOTIFY_2DAYS:
                 $period = 2 * 24 * 60 * 60;
                 break;
             case NOTIFY_3DAYS:
                 $period = 3 * 24 * 60 * 60;
                 break;
             case NOTIFY_4DAYS:
                 $period = 4 * 24 * 60 * 60;
                 break;
             case NOTIFY_5DAYS:
                 $period = 5 * 24 * 60 * 60;
                 break;
             case NOTIFY_1WEEK:
                 $period = 7 * 24 * 60 * 60;
                 break;
             case NOTIFY_2WEEKS:
                 $period = 2 * 7 * 24 * 60 * 60;
                 break;
             case NOTIFY_3WEEKS:
                 $period = 3 * 7 * 24 * 60 * 60;
                 break;
             case NOTIFY_1MONTH:
                 $period = 4 * 7 * 24 * 60 * 60;
                 break;
             case NOTIFY_2MONTH:
                 $period = 2 * 4 * 7 * 24 * 60 * 60;
                 break;
         }
         $date = $miu->notify_date;
         if ($pi = DbProjectItem::getVisibleById($miu->item)) {
             $mod_date = $pi->modified;
             if ($date != '0000-00-00 00:00:00') {
                 $date = strToGMTime($date) + $period;
                 $date = date('Y-m-d H:i:s', $date);
                 if ($date >= $mod_date && strToGMTime($date) <= time()) {
                     $diff = strToGMTime($date) - strToGMTime($mod_date);
                     if ($diff >= $period) {
                         ### diff in days ###
                         $information_count++;
                         $days = round((time() - strToGMTime($miu->notify_date)) / 60 / 60 / 24);
                         $object = DbProjectItem::getObjectById($pi->id);
                         $unchanged_body_html .= '<li>' . sprintf(__("%s (not touched since %s day(s))"), asHtml($object->name), $days) . '</li>';
                         $unchanged_body_plaintext .= '- ' . sprintf(__("%s (not touched since %s day(s))"), $object->name, $days) . '\\n\\r';
                     }
                 }
             }
         }
     }
     if ($unchanged_body_html) {
         $this->information_count++;
         $this->body_html .= "<h3>" . __('Unchanged monitored items:', 'notification') . "</h3>" . "<ul>" . $unchanged_body_html . "</ul>";
         $this->body_plaintext .= "\n\r" . __('Unchanged monitored items:', 'notification') . "\n\r" . $unchanged_body_plaintext;
     }
 }
Example #11
0
/**
* converts a time string like 2005-05-02 23:23:32 from the client's timezone to database GMT-String
*/
function clientTimeStrToGMTString($str)
{
    global $auth;
    $time_offset = 0;
    if (isset($auth->cur_user)) {
        $time_offset = $auth->cur_user->time_offset;
    }
    return getGMTString(strToGMTime($str) - $time_offset - confGet('SERVER_TIME_OFFSET'));
}
Example #12
0
/**
* renders a time as distance ago... (expects GMT times)
*/
function renderTimeAgo($t)
{
    $duration = time() - strToGMTime($t);
    if (strToGMTime($t) == 0) {
        return __("never");
    }
    if ($duration < 60 * 5) {
        return __('just now');
    }
    if ($duration < 60 * 60) {
        return sprintf(__('%smin ago'), ceil($duration / 60));
    }
    if ($duration < 60 * 60 * 2) {
        return __('1 hour ago');
    }
    if ($duration < 60 * 60 * 24) {
        return sprintf(__('%sh ago'), ceil($duration / 60 / 60));
    }
    if ($duration < 60 * 60 * 24 * 62) {
        return sprintf(__('%s days ago'), ceil($duration / 60 / 60 / 24));
    }
    if ($duration < 60 * 60 * 24 * 365 * 2) {
        return sprintf(__('%s months ago'), ceil($duration / 60 / 60 / 24 / 30));
    }
    if ($duration < 60 * 60 * 24 * 365 * 20) {
        return sprintf(__('%s years ago'), ceil($duration / 60 / 60 / 24 / 365));
    }
}
Example #13
0
 function render_tr(&$obj, $style = "")
 {
     measure_start('col_timedue');
     $class = "";
     $title = "planned end undefined.";
     $value = "";
     if ($obj->planned_end && $obj->planned_end != '0000-00-00' && $obj->planned_end != '0000-00-00 00:00:00') {
         if ($obj->status >= STATUS_COMPLETED) {
             if ($obj->status == STATUS_COMPLETED) {
                 $value = __("Review");
                 $title = __("Task status set to completed and needs approval.");
             } else {
                 $title = sprintf(__("Item was approved on: %s:", "date a task was approved"), renderDate($obj->date_closed));
                 $value = __("done");
             }
         } else {
             $daysLeft = floor((strToGMTime($obj->planned_end) - time()) / 24 / 60 / 60);
             switch ($daysLeft) {
                 case 0:
                     $value = __("Today");
                     $title = __("This task is planned to be completed today.");
                     break;
                 case 1:
                     $value = __("Tomorrow");
                     $title = __("This task is planned to be completed tomorrow.");
                     break;
                 case 7:
                 case 8:
                 case 9:
                 case 10:
                 case 11:
                 case 12:
                 case 13:
                 case 14:
                     $value = __("Next week");
                     $title = sprintf(__("due: %s"), renderDate($obj->planned_end));
                     break;
                 default:
                     $value = abs($daysLeft) . " <span class='entity'>" . __("days");
                     if ($daysLeft < 0) {
                         $class = "overDue";
                         $title = __("this task is overdue!");
                         $value .= __("late", "time status of a task");
                     } else {
                         $value .= __("remain", "time status of a task");
                         if ($obj->planned_start && $obj->planned_start != '0000-00-00' && $obj->planned_start != '0000-00-00 00:00:00') {
                             if (floor((strToGMTime($obj->planned_start) - time()) / 24 / 60 / 60) + 1 >= 1) {
                                 $value = __("Pending");
                                 $title = sprintf(__("planned for %s", "a certain date"), renderTimestamp($obj->planned_start));
                             } else {
                                 $title = sprintf(__("start: %s"), renderDate($obj->planned_start)) . " / " . sprintf(__("due: %s"), renderDate($obj->planned_end));
                             }
                         } else {
                             $title = sprintf(__("due: %s"), renderDate($obj->planned_end));
                         }
                     }
                     break;
             }
         }
         $value .= "</span>";
         print "<td class='timeDue {$class}' title='{$title}'>{$value}</td>";
         measure_stop('col_timedue');
     } else {
         print "<td></td>";
     }
 }
 function render_tr(&$task, $style = "")
 {
     global $PH;
     if (!isset($task) || !is_object($task)) {
         trigger_error("ListBlock->render_tr() called without valid object", E_USER_WARNING);
         return;
     }
     ### days left ###
     $due_str = $task->planned_end;
     $html_due = '';
     if ($due_str == "0000-00-00" || $due_str == "0000-00-00 00:00:00") {
         $html_due = '';
     } else {
         $due_days = floor((strToGMTime($task->planned_end) - time()) / 24 / 60 / 60) + 1;
         if ($due_days == 0) {
             $html_due = __("Due Today");
         } else {
             if ($due_days < 0) {
                 $class = 'overDue';
                 $html_due = '<span class=overdue>' . sprintf(__("%s days late"), -$due_days) . '</span>';
             } else {
                 $html_due = sprintf(__("%s days left"), $due_days);
             }
         }
     }
     $buffer = renderDateHtml($task->planned_end);
     if ($html_due && $task->status < STATUS_CLOSED) {
         $buffer .= '<br><span class=sub>(' . $html_due . ')</span>';
     }
     if ($this->parent_block->sum_estimated_max) {
         $buffer .= '<br><span class=sub>' . sprintf(__('%s required'), renderEstimatedDuration(($this->parent_block->sum_estimated_max + $this->parent_block->sum_estimated_min) / 2 - ($this->parent_block->sum_completion_max + $this->parent_block->sum_completion_min) / 2)) . '</span>';
     }
     echo '<td class=nowrap>' . $buffer . '</td>';
 }
Example #15
0
/**
* Submit changes to an effort  @ingroup pages
*/
function effortEditSubmit()
{
    global $PH;
    global $auth;
    ### Validate form crc
    if (!validateFormCrc()) {
        $PH->abortWarning(__('Invalid checksum for hidden form elements'));
    }
    ### get effort ####
    $id = getOnePassedId('effort');
    if ($id == 0) {
        $effort = new Effort(array('id' => 0));
    } else {
        $effort = Effort::getEditableById($id);
        if (!$effort) {
            $PH->abortWarning(__("Could not get effort"));
            return;
        }
        $effort->validateEditRequestTime();
    }
    ### cancel ###
    if (get('form_do_cancel')) {
        if (!$PH->showFromPage()) {
            $PH->show('projView', array('prj' => $effort->project));
        }
        exit;
    }
    ### get project ###
    $effort->project = get('effort_project');
    if (!($project = Project::getVisibleById($effort->project))) {
        $PH->abortWarning(__("Could not get project of effort"));
    }
    if (!$project->isPersonVisibleTeamMember($auth->cur_user)) {
        $PH->abortWarning("ERROR: Insufficient rights");
    }
    ### get person ###
    if ($effort->person = get('effort_person')) {
        if (!($person = Person::getVisibleById($effort->person))) {
            $PH->abortWarning(__("Could not get person of effort"));
        }
    }
    # retrieve all possible values from post-data
    # NOTE:
    # - this could be an security-issue.
    # - TODO: as some kind of form-edit-behaviour to field-definition
    foreach ($effort->fields as $f) {
        $name = $f->name;
        $f->parseForm($effort);
    }
    ### times as duration ###
    if ($as_duration = get('effort_as_duration')) {
        $effort->as_duration = $as_duration;
        ### make sure day of time_end stays the same if date changes... ###
        if (($time_start = $effort->time_start) && ($time_end = $effort->time_end)) {
            $effort->time_end = gmdate("Y-m-d", strToClientTime($time_end)) . " " . gmdate("H:i:s", strToClientTime($time_end));
            $effort->time_start = gmdate("Y-m-d", strToClientTime($time_end)) . " " . gmdate("00:00:00", strToClientTime($time_end));
        } else {
            trigger_error("Getting time_start and time_end failed", E_USER_WARNING);
        }
    }
    ### pub level ###
    if ($pub_level = get('effort_pub_level')) {
        ### not a new effort ###
        if ($effort->id) {
            if ($pub_level > $effort->getValidUserSetPublicLevels()) {
                $PH->abortWarning('invalid data', ERROR_RIGHTS);
            }
        }
        #else {
        #  #@@@ check for person create rights
        #}
        $effort->pub_level = $pub_level;
    }
    ## effort status ##
    if ($effort_status = get('effort_status')) {
        $effort->status = $effort_status;
    }
    if ($effort_billing = get('effort_billing')) {
        $effort->billing = intval($effort_billing);
    }
    if ($effort_productivity = get('effort_productivity')) {
        $effort->productivity = intval($effort_productivity);
    }
    ### link to task ###
    $task_id = get('effort_task');
    if (!is_null($task_id)) {
        if ($task_id == 0) {
            $effort->task = 0;
        } else {
            if ($task = Task::getVisibleById($task_id)) {
                $effort->task = $task->id;
            }
        }
    }
    ### go back to from if validation fails ###
    $failure = false;
    if (!$effort->name) {
        $failure = true;
        new FeedbackWarning(__("Name required"));
    }
    if (strToGMTime($effort->time_end) - strToGMTime($effort->time_start) < 0) {
        $failure = true;
        new FeedbackWarning(__("Cannot start before end."));
    }
    ### validation of the Datetime fields###
    if (!$as_duration) {
        if (strToGMTime($effort->time_start) == 0) {
            $failure = true;
            $name = $effort->fields['time_start']->name;
            $field_id = $effort->_type . '_' . $name;
            $value_time = get($field_id . '_time');
            new FeedbackWarning(sprintf(__("<b>%s</b> is not a valid value for start time."), $value_time));
            $effort->time_start = getGMTString();
        }
        if (strToGMTime($effort->time_end) == 0) {
            $failure = true;
            $name = $effort->fields['time_end']->name;
            $field_id = $effort->_type . '_' . $name;
            $value_time = get($field_id . '_time');
            new FeedbackWarning(sprintf(__("<b>%s</b> is not a valid value for end time."), $value_time));
            $effort->time_end = getGMTString();
        }
    } else {
        ##As duration
        if (strToGMTime($effort->time_end) == 0) {
            $failure = true;
            $name = $effort->fields['time_end']->name;
            $field_id = $effort->_type . '_' . $name;
            $value_time = get($field_id . '_time');
            new FeedbackWarning(sprintf(__("<b>%s</b> is not a valid value for hours."), $value_time));
            $effort->time_end = gmdate("Y-m-d", time()) . " 00:00:00";
        }
    }
    if ($failure) {
        $PH->show('effortEdit', NULL, $effort);
        exit;
    }
    ### write to db ###
    if ($effort->id == 0) {
        $effort->insert();
    } else {
        $effort->update();
    }
    ### display taskView ####
    if (!$PH->showFromPage()) {
        $PH->show('projView', array('prj' => $effort->project));
    }
}