/** * Prepare project data for a given month * * @param integer $month * @param integer $year * @param mixed $additional_conditions * @param boolean $include_assignments_table * @return array */ function getMonthData($month, $year, $additional_conditions, $include_assignments_table = false) { $first_day = DateTimeValue::beginningOfMonth($month, $year); $last_day = DateTimeValue::endOfMonth($month, $year); // Than we define empty result... $result = array(); for ($i = 1; $i <= $last_day->getDay(); $i++) { $result["{$year}-{$month}-{$i}"] = array(); } // for $objects_table = TABLE_PREFIX . 'project_objects'; $assignments_table = TABLE_PREFIX . 'assignments'; $conditions = db_prepare_string("{$objects_table}.due_on BETWEEN ? AND ?", array($first_day, $last_day)); if ($additional_conditions) { $conditions .= " AND {$additional_conditions}"; } // if // If we don't have user ID-s filter we can exclude assignments table $tables = $include_assignments_table ? "{$objects_table}, {$assignments_table}" : $objects_table; $objects = ProjectObjects::findBySQL("SELECT DISTINCT {$objects_table}.* FROM {$tables} WHERE {$conditions} ORDER BY type, due_on"); if (is_foreachable($objects)) { foreach ($objects as $object) { $due_on = $object->getDueOn(); $result[$due_on->getYear() . '-' . $due_on->getMonth() . '-' . $due_on->getDay()][] = $object; } // foreach } // if return $result; }
/** * Render calendar * * Params: * * - data - Calendar data * - first_week_day - Value for first day in week from settings * @param array $params * @return string */ function smarty_function_calendar($params, &$smarty) { $first_week_day = 0; if (isset($params['first_week_day'])) { $first_week_day = (int) array_var($params, 'first_week_day'); unset($params['first_week_day']); } // if $data = array(); if (isset($params['data'])) { $data = array_var($params, 'data'); unset($params['first_week_day']); } // if $days = array(0 => lang('Sunday'), 1 => lang('Monday'), 2 => lang('Tuesday '), 3 => lang('Wednesday'), 4 => lang('Thursday'), 5 => lang('Friday'), 6 => lang('Saturday')); $data_keys = array_keys($data); $date = $data_keys[0]; $date = explode('-', $date); $year = $date[0]; // year to render $month = $date[1]; // month to render $begining_of_month = DateTimeValue::beginningOfMonth($month, $year); $end_of_month = DateTimeValue::endOfMonth($month, $year); $first_month_day = date('w', $begining_of_month->getTimestamp()); $calendar = "<div id=\"calendar\">\n<table>\n"; // header $calendar .= "\t<thead>\n"; $from = $first_week_day; $start_point = null; for ($i = 0; $i < 7; $i++) { $day = $from > 6 ? $days[$from - 7] : $days[$from]; $calendar .= "\t\t<th>{$day}</th>\n"; $from++; if ($day == $days[$first_month_day]) { $start_point = $i; } // if } $calendar .= "\t</thead>\n"; // data $calendar .= "\t<tr>\n"; $curr_day = 1; for ($i = 1; $i < 36; $i++) { if ($i - 1 >= $start_point) { if ($curr_day <= $end_of_month->getDay()) { $calendar .= "\t\t<td><span>{$curr_day}</span>"; $items = $data[$year . '-' . $month . '-' . $curr_day]['items']; $counts = $data[$year . '-' . $month . '-' . $curr_day]['counts']; // milestones foreach ($items as $milestone) { if (instance_of($milestone, 'Milestone')) { $calendar .= "<p>" . $milestone->getName() . "</p>"; } } // foreach if ($counts) { if ($counts['Ticket']) { $calendar .= "<p>(" . $counts['Ticket'] . ')' . lang('Tickets') . "</p>"; } // if if ($counts['Task']) { $calendar .= "<p>(" . $counts['Task'] . ')' . lang('Tasks') . "</p>"; } // if } // if $calendar .= "</td>\n"; $curr_day++; } else { $calendar .= "\t\t<td></td>\n"; } // if } else { $calendar .= "\t\t<td></td>\n"; } $calendar .= $i % 7 == 0 && $i < 35 ? "\t</tr>\n\t<tr>\n" : null; } $calendar .= "\t</tr>\n"; $calendar .= "</table>\n</div>\n"; return $calendar; }
/** * Exports time records * * @param void * @return null */ function export() { $object_visibility = array_var($_GET, 'visibility', VISIBILITY_NORMAL); $exportable_modules = explode(',', array_var($_GET, 'modules', null)); if (!is_foreachable($exportable_modules)) { $exportable_modules = null; } // if require_once PROJECT_EXPORTER_MODULE_PATH . '/models/ProjectExporterOutputBuilder.class.php'; $output_builder = new ProjectExporterOutputBuilder($this->active_project, $this->smarty, $this->active_module, $exportable_modules); if (!$output_builder->createOutputFolder()) { $this->serveData($output_builder->execution_log, 'execution_log', null, FORMAT_JSON); } // if $output_builder->createAttachmentsFolder(); $timerecords = TimeRecords::findByProject($this->active_project, STATE_VISIBLE, $object_visibility); $distinct_months = array(); foreach ($timerecords as $timerecord) { $date = $timerecord->getRecordDate(); $exists = false; for ($x = 0; $x < count($distinct_months); $x++) { if ($distinct_months[$x]['month'] == $date->getMonth() && $distinct_months[$x]['year'] == $date->getYear()) { $exists = true; } // if } // for if (!$exists) { $distinct_months[] = array("year" => $date->getYear(), "month" => $date->getMonth(), "month_string" => $date->date_data['month'], "beginning_of_month" => DateTimeValue::beginningOfMonth($date->getMonth(), $date->getYear()), "end_of_month" => DateTimeValue::endOfMonth($date->getMonth(), $date->getYear())); } // if } // foreach $people = ProjectUsers::findUsersByProject($this->active_project); $companies = Companies::findByProject($this->active_project); $total_times = array(); foreach ($people as $person) { $person->temp_total_time = TimeRecords::getTotalUserTimeOnProject($this->active_project, $person); } // foreach $output_builder->setFileTemplate($this->active_module, $this->controller_name, 'index'); $output_builder->smarty->assign(array("distinct_months" => $distinct_months, "people" => $people, "companies" => $companies, "total_times" => $total_times, "timerecords" => $timerecords)); $output_builder->outputToFile('index'); // export monthly report if (is_foreachable($distinct_months)) { $output_builder->setFileTemplate($this->active_module, $this->controller_name, 'monthly'); foreach ($distinct_months as $distinct_month) { $output_builder->smarty->assign(array('current_month' => $distinct_month, 'start_date' => DateTimeValue::beginningOfMonth($distinct_month[month], $distinct_month['year']), 'end_date' => DateTimeValue::endOfMonth($distinct_month['month'], $distinct_month['year']))); $output_builder->outputToFile('monthly_' . $distinct_month['month'] . '_' . $distinct_month['year']); } // foreach } // if // export report for persons if (is_foreachable($people)) { $output_builder->setFileTemplate($this->active_module, $this->controller_name, 'person'); foreach ($people as $person) { $output_builder->smarty->assign(array('current_person' => $person)); $output_builder->outputToFile('user_' . $person->getId()); } // foreach } // if $this->serveData($output_builder->execution_log, 'execution_log', null, FORMAT_JSON); }
/** * Prepare conditions based on filter settings * * @param User $user * @return string */ function prepareConditions($user) { $project_objects_table = TABLE_PREFIX . 'project_objects'; $assignments_table = TABLE_PREFIX . 'assignments'; $completable_types = get_completable_project_object_types(); $conditions = array(); // Selected projects filter if ($this->getProjectFilter() == PROJECT_FILTER_SELECTED) { $project_ids = $this->getProjectFilterData(); if ($project_ids) { $conditions[] = db_prepare_string("({$project_objects_table}.project_id IN (?))", array($project_ids)); $types_filter = ProjectUsers::getVisibleTypesFilter($user, null, $completable_types); if ($types_filter) { $conditions[] = $types_filter; } else { return false; // No access to any of the projects? } // if } // if } // if // All projects if (count($conditions) == 0) { $types_filter = ProjectUsers::getVisibleTypesFilter($user, array(PROJECT_STATUS_ACTIVE), $completable_types); if ($types_filter) { $conditions[] = $types_filter; } else { return false; // No access to any of the projects? } // if } // if // User filter switch ($this->getUserFilter()) { // Not assigned to anyone case USER_FILTER_NOT_ASSIGNED: $user_id = $user->getId(); $conditions[] = "({$assignments_table}.user_id IS NULL)"; break; // Logged user // Logged user case USER_FILTER_LOGGED_USER: $user_id = $user->getId(); $conditions[] = "({$assignments_table}.user_id = {$user_id})"; break; // Logged user is responsible // Logged user is responsible case USER_FILTER_LOGGED_USER_RESPONSIBLE: $user_id = $user->getId(); $conditions[] = "({$assignments_table}.user_id = {$user_id}) AND ({$assignments_table}.is_owner = 1)"; break; // All members of a specific company // All members of a specific company case USER_FILTER_COMPANY: $visible_user_ids = $user->visibleUserIds(); if (!is_foreachable($visible_user_ids)) { return false; } // if $company_id = $this->getUserFilterData(); if ($company_id) { $company = Companies::findById($company_id); if (instance_of($company, 'Company')) { $user_ids = Users::findUserIdsByCompany($company); if (is_foreachable($user_ids)) { foreach ($user_ids as $k => $v) { if (!in_array($v, $visible_user_ids)) { unset($user_ids[$k]); } // if } // if if (count($user_ids) > 0) { $imploded = implode(', ', $user_ids); $conditions[] = "({$assignments_table}.user_id IN ({$imploded}))"; } else { return false; } // if } // if } // if } // if break; // Selected users // Selected users case USER_FILTER_SELECTED: $visible_user_ids = $user->visibleUserIds(); if (!is_foreachable($visible_user_ids)) { return false; } // if $user_ids = $this->getUserFilterData(); if (is_foreachable($user_ids)) { foreach ($user_ids as $k => $v) { if (!in_array($v, $visible_user_ids)) { unset($user_ids[$k]); } // if } // foreach if (count($user_ids) > 0) { $imploded = implode(', ', $user_ids); $conditions[] = "({$assignments_table}.user_id IN ({$imploded}))"; } else { return false; } // if } // if break; } // switch $today = new DateValue(time() + get_user_gmt_offset($user)); // Calculate user timezone when determining today switch ($this->getDateFilter()) { // List late assignments case DATE_FILTER_LATE: $today_str = db_escape($today->toMySQL()); $conditions[] = "({$project_objects_table}.due_on < {$today_str})"; break; // List today assignments // List today assignments case DATE_FILTER_TODAY: $today_str = db_escape($today->toMySQL()); $conditions[] = "({$project_objects_table}.due_on = {$today_str})"; break; // List tomorrow assignments // List tomorrow assignments case DATE_FILTER_TOMORROW: $tomorrow = $today->advance(86400, false); $tomorrow_str = db_escape($tomorrow->toMySQL()); $conditions[] = "({$project_objects_table}.due_on = {$tomorrow_str})"; break; // List this week assignments // List this week assignments case DATE_FILTER_THIS_WEEK: $first_day_sunday = UserConfigOptions::getValue('time_first_week_day', $user) == 0; $week_start = $today->beginningOfWeek($first_day_sunday); $week_end = $today->endOfWeek($first_day_sunday); $week_start_str = db_escape($week_start->toMySQL()); $week_end_str = db_escape($week_end->toMySQL()); $conditions[] = "({$project_objects_table}.due_on >= {$week_start_str} AND {$project_objects_table}.due_on <= {$week_end_str})"; break; // List next week assignments // List next week assignments case DATE_FILTER_NEXT_WEEK: $first_day_sunday = UserConfigOptions::getValue('time_first_week_day', $user) == 0; $next_week = $today->advance(604800, false); $week_start = $next_week->beginningOfWeek($first_day_sunday); $week_end = $next_week->endOfWeek($first_day_sunday); $week_start_str = db_escape($week_start->toMySQL()); $week_end_str = db_escape($week_end->toMySQL()); $conditions[] = "({$project_objects_table}.due_on >= {$week_start_str} AND {$project_objects_table}.due_on <= {$week_end_str})"; break; // List this month assignments // List this month assignments case DATE_FILTER_THIS_MONTH: $month_start = DateTimeValue::beginningOfMonth($today->getMonth(), $today->getYear()); $month_end = DateTimeValue::endOfMonth($today->getMonth(), $today->getYear()); $month_start_str = db_escape($month_start->toMySQL()); $month_end_str = db_escape($month_end->toMySQL()); $conditions[] = "({$project_objects_table}.due_on >= {$month_start_str} AND {$project_objects_table}.due_on <= {$month_end_str})"; break; // List next month assignments // List next month assignments case DATE_FILTER_NEXT_MONTH: $month = $today->getMonth() + 1; $year = $today->getYear(); if ($month == 13) { $month = 1; $year += 1; } // if $month_start = DateTimeValue::beginningOfMonth($month, $year); $month_end = DateTimeValue::endOfMonth($month, $year); $month_start_str = db_escape($month_start->toMySQL()); $month_end_str = db_escape($month_end->toMySQL()); $conditions[] = "({$project_objects_table}.due_on >= {$month_start_str} AND {$project_objects_table}.due_on <= {$month_end_str})"; break; // Specific date // Specific date case DATE_FILTER_SELECTED_DATE: $date_from = $this->getDateFrom(); if (instance_of($date_from, 'DateTimeValue')) { $date_from_str = db_escape($date_from->toMySql()); $conditions[] = "({$project_objects_table}.due_on = {$date_from_str})"; } // if break; // Specific range // Specific range case DATE_FILTER_SELECTED_RANGE: $date_from = $this->getDateFrom(); $date_to = $this->getDateTo(); if (instance_of($date_from, 'DateValue') && instance_of($date_to, 'DateValue')) { $date_from_str = db_escape($date_from->toMySQL()); $date_to_str = db_escape($date_to->toMySQL()); $conditions[] = "({$project_objects_table}.due_on >= {$date_from_str} AND {$project_objects_table}.due_on <= {$date_to_str})"; } // if break; } // switch // Status filter switch ($this->getStatusFilter()) { case STATUS_FILTER_ACTIVE: $conditions[] = "({$project_objects_table}.completed_on IS NULL)"; break; case STATUS_FILTER_COMPLETED: $conditions[] = "({$project_objects_table}.completed_on IS NOT NULL)"; break; } // if // Additional filters $state = STATE_VISIBLE; $visibility = $user->getVisibility(); $conditions[] = "({$project_objects_table}.state >= {$state} AND {$project_objects_table}.visibility >= {$visibility})"; return implode(' AND ', $conditions); }
/** * Render calendar * * @param void * @return string */ function render() { $first_day = DateTimeValue::beginningOfMonth($this->month, $this->year); $last_day = DateTimeValue::endOfMonth($this->month, $this->year); // --------------------------------------------------- // Header // --------------------------------------------------- $result = "\n<table class=\"calendar\">\n<thead>\n<tr>\n"; $first_day_num = 0; $current_day = $this->first_weekday; for ($i = 0; $i < 7; $i++) { $real_day = $current_day > 6 ? $current_day - 7 : $current_day; // get real day num (we have a small offset with start day setting) $class = $real_day == 0 || $real_day == 6 ? 'weekend' : 'weekday'; // class for row $current_day++; if ($real_day == $first_day->getWeekday()) { $first_day_num = $real_day; // we got where we need to start... } // if $result .= "<th class=\"{$class}\">" . $this->renderDayHeader($real_day) . "</th>\n"; } // for $result .= "</tr>\n</thead>\n"; // --------------------------------------------------- // Body // --------------------------------------------------- if ($this->first_weekday > $first_day_num) { $left_span = 7 - ($this->first_weekday - $first_day_num); } else { $left_span = $first_day_num - $this->first_weekday; } // if $weekday = $left_span; $result .= "<tbody>\n<tr>\n"; if ($left_span) { $result .= "<td class=\"previousMonth\" colspan=\"{$left_span}\"></td>\n"; } // if for ($i = 1; $i <= $last_day->getDay(); $i++) { $day = new DateValue($this->year . '-' . $this->month . '-' . $i); if ($weekday == 0) { $result .= "<tr>\n"; } // if $result .= $this->renderDay($day, $weekday); if ($weekday == 6) { $result .= "</tr>\n"; } // if $weekday = $weekday == 6 ? 0 : $weekday + 1; } // for // Close row if we ended in the middle of it if ($weekday > 0) { $right_span = 7 - $weekday; $result .= "<td class=\"nextMonth\" colspan=\"{$right_span}\"></td>\n</tr>"; } // if // --------------------------------------------------- // Close and done // --------------------------------------------------- return $result . "</tbody>\n</table>"; }
/** * Prepare conditions based on report settings * * @param User $user * @param Project $project * @return string */ function prepareConditions($user, $project = null) { $project_objects_table = TABLE_PREFIX . 'project_objects'; $conditions = array(); // Project and type if (instance_of($project, 'Project')) { $conditions[] = db_prepare_string('project_id = ? AND type = ?', array($project->getId(), 'timerecord')); } else { $conditions[] = db_prepare_string('type = ?', array('timerecord')); } // if // User filter switch ($this->getUserFilter()) { // Anyone - This filter used to filter only time tracked from all // visible users, but that did not include deleted accounts. Fixed now // //case USER_FILTER_ANYBODY: // $visible_user_ids = $user->visibleUserIds(); // if(is_foreachable($visible_user_ids)) { // $conditions[] = "($project_objects_table.integer_field_1 IN (" . db_escape($visible_user_ids) . '))'; // } else { // return false; // not visible users // } // if // break; // Logged user case USER_FILTER_LOGGED_USER: $user_id = $user->getId(); $conditions[] = "({$project_objects_table}.integer_field_1 = {$user_id})"; break; // All members of a specific company // All members of a specific company case USER_FILTER_COMPANY: $visible_user_ids = $user->visibleUserIds(); if (!is_foreachable($visible_user_ids)) { return false; } // if $company_id = $this->getUserFilterData(); if ($company_id) { $company = Companies::findById($company_id); if (instance_of($company, 'Company')) { $user_ids = Users::findUserIdsByCompany($company); if (is_foreachable($user_ids)) { foreach ($user_ids as $k => $v) { if (!in_array($v, $visible_user_ids)) { unset($user_ids[$k]); } // if } // if if (count($user_ids) > 0) { $imploded = implode(', ', $user_ids); $conditions[] = "({$project_objects_table}.integer_field_1 IN ({$imploded}))"; } else { return false; } // if } // if } // if } // if break; // Selected users // Selected users case USER_FILTER_SELECTED: $visible_user_ids = $user->visibleUserIds(); if (!is_foreachable($visible_user_ids)) { return false; } // if $user_ids = $this->getUserFilterData(); if (is_foreachable($user_ids)) { foreach ($user_ids as $k => $v) { if (!in_array($v, $visible_user_ids)) { unset($user_ids[$k]); } // if } // foreach if (count($user_ids) > 0) { $imploded = implode(', ', $user_ids); $conditions[] = "({$project_objects_table}.integer_field_1 IN ({$imploded}))"; } else { return false; } // if } // if break; } // switch $today = new DateValue(time() + get_user_gmt_offset($user)); // Calculate user timezone when determining today switch ($this->getDateFilter()) { // List time records posted for today case DATE_FILTER_TODAY: $today_str = db_escape($today->toMySQL()); $conditions[] = "({$project_objects_table}.date_field_1 = {$today_str})"; break; // List next week records // List next week records case DATE_FILTER_LAST_WEEK: $first_day_sunday = UserConfigOptions::getValue('time_first_week_day', $user) == 0; $last_week = $today->advance(-604800, false); $week_start = $last_week->beginningOfWeek($first_day_sunday); $week_end = $last_week->endOfWeek($first_day_sunday); $week_start_str = db_escape($week_start->toMySQL()); $week_end_str = db_escape($week_end->toMySQL()); $conditions[] = "({$project_objects_table}.date_field_1 >= {$week_start_str} AND {$project_objects_table}.date_field_1 <= {$week_end_str})"; break; // List this week records // List this week records case DATE_FILTER_THIS_WEEK: $first_day_sunday = UserConfigOptions::getValue('time_first_week_day', $user) == 0; $week_start = $today->beginningOfWeek($first_day_sunday); $week_end = $today->endOfWeek($first_day_sunday); $week_start_str = db_escape($week_start->toMySQL()); $week_end_str = db_escape($week_end->toMySQL()); $conditions[] = "({$project_objects_table}.date_field_1 >= {$week_start_str} AND {$project_objects_table}.date_field_1 <= {$week_end_str})"; break; // List this month time records // List this month time records case DATE_FILTER_LAST_MONTH: $month = $today->getMonth() - 1; $year = $today->getYear(); if ($month == 0) { $month = 12; $year -= 1; } // if $month_start = DateTimeValue::beginningOfMonth($month, $year); $month_end = DateTimeValue::endOfMonth($month, $year); $month_start_str = db_escape($month_start->toMySQL()); $month_end_str = db_escape($month_end->toMySQL()); $conditions[] = "({$project_objects_table}.date_field_1 >= {$month_start_str} AND {$project_objects_table}.date_field_1 <= {$month_end_str})"; break; // Last month // Last month case DATE_FILTER_THIS_MONTH: $month_start = DateTimeValue::beginningOfMonth($today->getMonth(), $today->getYear()); $month_end = DateTimeValue::endOfMonth($today->getMonth(), $today->getYear()); $month_start_str = db_escape($month_start->toMySQL()); $month_end_str = db_escape($month_end->toMySQL()); $conditions[] = "({$project_objects_table}.date_field_1 >= {$month_start_str} AND {$project_objects_table}.date_field_1 <= {$month_end_str})"; break; // Specific date // Specific date case DATE_FILTER_SELECTED_DATE: $date_from = $this->getDateFrom(); if (instance_of($date_from, 'DateValue')) { $date_from_str = db_escape($date_from->toMySql()); $conditions[] = "({$project_objects_table}.date_field_1 = {$date_from_str})"; } // if break; // Specific range // Specific range case DATE_FILTER_SELECTED_RANGE: $date_from = $this->getDateFrom(); $date_to = $this->getDateTo(); if (instance_of($date_from, 'DateValue') && instance_of($date_to, 'DateValue')) { $date_from_str = db_escape($date_from->toMySQL()); $date_to_str = db_escape($date_to->toMySQL()); $conditions[] = "({$project_objects_table}.date_field_1 >= {$date_from_str} AND {$project_objects_table}.date_field_1 <= {$date_to_str})"; } // if break; } // switch // Billable filter switch ($this->getBillableFilter()) { case BILLABLE_FILTER_BILLABLE: $conditions[] = "({$project_objects_table}.integer_field_2 = '" . BILLABLE_STATUS_BILLABLE . "')"; break; case BILLABLE_FILTER_NOT_BILLABLE: $conditions[] = "({$project_objects_table}.integer_field_2 = '" . BILLABLE_STATUS_NOT_BILLABLE . "' OR {$project_objects_table}.integer_field_2 IS NULL)"; break; case BILLABLE_FILTER_BILLABLE_BILLED: $conditions[] = "({$project_objects_table}.integer_field_2 >= '" . BILLABLE_STATUS_BILLED . "')"; break; case BILLABLE_FILTER_PENDING_PAYMENT: $conditions[] = "({$project_objects_table}.integer_field_2 = '" . BILLABLE_STATUS_PENDING_PAYMENT . "')"; break; case BILLABLE_FILTER_BILLABLE_NOT_BILLED: $conditions[] = "({$project_objects_table}.integer_field_2 IN ('" . BILLABLE_STATUS_BILLABLE . "', '" . BILLABLE_STATUS_PENDING_PAYMENT . "'))"; break; } // switch // Additional filters $state = STATE_VISIBLE; $visibility = $user->getVisibility(); $conditions[] = "({$project_objects_table}.state >= {$state} AND {$project_objects_table}.visibility >= {$visibility})"; return implode(' AND ', $conditions); }