Index: language/en_us/objects.php =================================================================== --- language/en_us/objects.php (revision 96) +++ language/en_us/objects.php (working copy) @@ -20,6 +20,8 @@ 'comments' => 'Comments', 'milestone' => 'Milestone', 'milestones' => 'Milestones', + 'time' => 'Time', + 'times' => 'Times', 'task' => 'Task', 'tasks' => 'Tasks', 'task list' => 'Task list', @@ -70,10 +72,13 @@ 'private message' => 'Private message', 'private milestone' => 'Private milestone', + 'private time' => 'Private time', 'private task list' => 'Private task lists', 'private comment' => 'Private comment', 'private file' => 'Private file', + + 'billable time' => 'Billable time', ); // array -?> \ No newline at end of file +?> Index: language/en_us/errors.php =================================================================== --- language/en_us/errors.php (revision 96) +++ language/en_us/errors.php (working copy) @@ -61,7 +61,12 @@ // Add milestone form 'milestone name required' => 'Milestone name value is required', 'milestone due date required' => 'Milestone due date value is required', - + + // Add time form + 'time name required' => 'Time name value is required', + 'time date required' => 'Time date value is required', + 'time hours required' => 'Time hours value is required', + // Add task list 'task list name required' => 'Task list name value is required', 'task list name unique' => 'Task list name must be unique in project', @@ -105,4 +110,4 @@ ); // array -?> \ No newline at end of file +?> Index: language/en_us/general.php =================================================================== --- language/en_us/general.php (revision 96) +++ language/en_us/general.php (working copy) @@ -23,11 +23,13 @@ 'submit' => 'Submit', 'reset' => 'Reset', 'name' => 'Name', + 'hours' => 'Hours', 'title' => 'Title', 'description' => 'Description', 'text' => 'Text', 'additional text' => 'Additional text', 'due date' => 'Due date', + 'done date' => 'Date', 'assign to' => 'Assign to', 'late' => 'Late', 'upcoming' => 'Upcoming', @@ -77,7 +79,6 @@ 'state' => 'State', 'zipcode' => 'Zipcode', 'country' => 'Country', - 'n/a' => 'n/a', 'contact' => 'Contact', 'pagination page' => 'Page:', 'pagination first' => 'First page', @@ -119,4 +120,4 @@ 'month 12' => 'December', ); // array -?> \ No newline at end of file +?> Index: language/en_us/actions.php =================================================================== --- language/en_us/actions.php (revision 96) +++ language/en_us/actions.php (working copy) @@ -63,7 +63,12 @@ 'add milestone' => 'Add milestone', 'edit milestone' => 'Edit milestone', 'delete milestone' => 'Delete milestone', - + + // Time + 'add time' => 'Add time', + 'edit time' => 'Edit time', + 'delete time' => 'Delete time', + // People 'update people' => 'Update', 'remove user from project' => 'Remove from project', @@ -103,4 +108,4 @@ ); // array -?> \ No newline at end of file +?> Index: language/en_us/project_interface.php =================================================================== --- language/en_us/project_interface.php (revision 96) +++ language/en_us/project_interface.php (working copy) @@ -67,6 +67,7 @@ 'all permissions' => 'All', 'can manage messages' => 'Manage messages', + 'can manage time' => 'Manage time', 'can manage tasks' => 'Manage tasks', 'can manage milestones' => 'Manage milestones', 'can upload files' => 'Upload files', @@ -138,10 +139,11 @@ // Private 'private message desc' => 'Private messages are visible only to owner company members. Members of client companies will not be able to see them.', 'private milestone desc' => 'Private milestones are visible only to owner company members. Members of client companies will not be able to see them.', + 'private time desc' => 'Private times are visible only to owner company members. Members of client companies will not be able to see them.', 'private task list desc' => 'Private task lists are visible only to owner company members. Members of client companies will not be able to see them.', 'private comment desc' => 'Private comments are visible only to owner company members. Members of client companies will not be able to see them.', 'private file desc' => 'Private files are visible only to the members of the owner company. Members of client companies will not be able to see them', ); // array -?> \ No newline at end of file +?> Index: language/en_us/messages.php =================================================================== --- language/en_us/messages.php (revision 96) +++ language/en_us/messages.php (working copy) @@ -19,10 +19,12 @@ 'no activities in project' => 'There are no activities logged for this project', 'comment dnx' => 'Requested comment does not exist', 'milestone dnx' => 'Requested milestone does not exist', + 'time dnx' => 'Requested time record does not exist', 'task list dnx' => 'Requested task list does not exist', 'task dnx' => 'Requested task does not exist', 'no milestones in project' => 'There are no milestones in this project', 'no active milestones in project' => 'There are no active milestones in this project', + 'no time records in project' => 'There are no time records in this project', 'empty milestone' => 'This milestone is empty. You can add a message or a task list to it at any time', 'no logs for project' => 'There are no log entries related to this project', 'no recent activities' => 'There are no recent activities logged in the database', @@ -78,7 +80,11 @@ 'success add milestone' => 'Milestone \'%s\' has been created successfully', 'success edit milestone' => 'Milestone \'%s\' has been updated successfully', 'success deleted milestone' => 'Milestone \'%s\' has been deleted successfully', - + + 'success add time' => 'Time \'%s\' has been created successfully', + 'success edit time' => 'Time \'%s\' has been updated successfully', + 'success deleted time' => 'Time \'%s\' has been deleted successfully', + 'success add message' => 'Message %s has been added successfully', 'success edit message' => 'Message %s has been updated successfully', 'success deleted message' => 'Message \'%s\' and all of its comments has been deleted successfully', @@ -160,6 +166,7 @@ 'error update message options' => 'Failed to update message options', 'error delete comment' => 'Failed to delete selected comment', 'error delete milestone' => 'Failed to delete selected milestone', + 'error delete time' => 'Failed to delete selected time', 'error complete task' => 'Failed to complete selected task', 'error open task' => 'Failed to reopen selected task', 'error upload file' => 'Failed to upload file', @@ -204,6 +211,7 @@ // Confirmation 'confirm delete message' => 'Are you sure that you want to delete this message?', 'confirm delete milestone' => 'Are you sure that you want to delete this milestone?', + 'confirm delete time' => 'Are you sure that you want to delete this time?', 'confirm delete task list' => 'Are you sure that you want to delete this task lists and all of its tasks?', 'confirm delete task' => 'Are you sure that you want to delete this task?', 'confirm delete comment' => 'Are you sure that you want to delete this comment?', @@ -245,6 +253,10 @@ 'log delete projectmilestones' => '\'%s\' deleted', 'log close projectmilestones' => '\'%s\' finished', 'log open projectmilestones' => '\'%s\' reopened', + + 'log add projecttimes' => '\'%s\' added', + 'log edit projecttimes' => '\'%s\' updated', + 'log delete projecttimes' => '\'%s\' deleted', 'log add projecttasklists' => '\'%s\' added', 'log edit projecttasklists' => '\'%s\' updated', @@ -275,4 +287,4 @@ ); // array -?> \ No newline at end of file +?> Index: application/helpers/project_website.php =================================================================== --- application/helpers/project_website.php (revision 96) +++ application/helpers/project_website.php (working copy) @@ -22,6 +22,7 @@ define('PROJECT_TAB_MESSAGES', 'messages'); define('PROJECT_TAB_TASKS', 'tasks'); define('PROJECT_TAB_MILESTONES', 'milestones'); + define('PROJECT_TAB_TIME', 'time'); define('PROJECT_TAB_FILES', 'files'); define('PROJECT_TAB_TAGS', 'tags'); define('PROJECT_TAB_FORMS', 'forms'); @@ -55,6 +56,11 @@ get_url('milestone') )); add_tabbed_navigation_item(new TabbedNavigationItem( + PROJECT_TAB_TIME, + lang('time'), + get_url('time') + )); + add_tabbed_navigation_item(new TabbedNavigationItem( PROJECT_TAB_FILES, lang('files'), get_url('files') @@ -79,4 +85,4 @@ tabbed_navigation_set_selected($selected); } // dashboard_tabbed_navigation -?> \ No newline at end of file +?> Index: application/models/projects/Project.class.php =================================================================== --- application/models/projects/Project.class.php (revision 96) +++ application/models/projects/Project.class.php (working copy) @@ -1,1411 +1,1449 @@ -all_messages)) { - $this->all_messages = ProjectMessages::getProjectMessages($this, true); - } // if - return $this->all_messages; - } // getAllMessages - - /** - * Return only the messages that current user can see (if not member of owner company private - * messages will be excluded) - * - * @param null - * @return null - */ - function getMessages() { - if(logged_user()->isMemberOfOwnerCompany()) { - return $this->getAllMessages(); // members of owner company can view all messages - } // if - - if(is_null($this->messages)) { - $this->messages = ProjectMessages::getProjectMessages($this, false); - } // if - return $this->messages; - } // getMessages - - /** - * Return all important messages - * - * @param void - * @return array - */ - function getAllImportantMessages() { - if(is_null($this->all_important_messages)) { - $this->all_important_messages = ProjectMessages::getImportantProjectMessages($this, true); - } // if - return $this->all_important_messages; - } // getAllImportantMessages - - /** - * Return array of important messages - * - * @param void - * @return array - */ - function getImportantMessages() { - if(logged_user()->isMemberOfOwnerCompany()) { - return $this->getAllImportantMessages(); - } // if - - if(is_null($this->important_messages)) { - $this->important_messages = ProjectMessages::getImportantProjectMessages($this, false); - } // if - return $this->important_messages; - } // getImportantMessages - - // --------------------------------------------------- - // Milestones - // --------------------------------------------------- - - /** - * Return all milestones, don't filter them by is_private stamp based on users permissions - * - * @param void - * @return array - */ - function getAllMilestones() { - if(is_null($this->all_milestones)) { - $this->all_milestones = ProjectMilestones::findAll(array( - 'conditions' => array('`project_id` = ?', $this->getId()), - 'order' => 'due_date' - )); // findAll - } // if - return $this->all_milestones; - } // getAllMilestones - - /** - * Return all project milestones - * - * @access public - * @param void - * @return array - */ - function getMilestones() { - if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllMilestones(); // member of owner company - if(is_null($this->milestones)) { - $this->milestones = ProjectMilestones::findAll(array( - 'conditions' => array('`project_id` = ? AND `is_private` = ?', $this->getId(), 0), - 'order' => 'due_date' - )); // findAll - } // if - return $this->milestones; - } // getMilestones - - /** - * Return all opet milestones without is_private check - * - * @param void - * @return array - */ - function getAllOpenMilestones() { - if(is_null($this->all_open_milestones)) { - $this->all_open_milestones = ProjectMilestones::findAll(array( - 'conditions' => array('`project_id` = ? AND `completed_on` = ?', $this->getId(), EMPTY_DATETIME), - 'order' => 'due_date' - )); // findAll - } // if - return $this->all_open_milestones; - } // getAllOpenMilestones - - /** - * Return open milestones - * - * @access public - * @param void - * @return array - */ - function getOpenMilestones() { - if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllOpenMilestones(); - if(is_null($this->open_milestones)) { - $this->open_milestones = ProjectMilestones::findAll(array( - 'conditions' => array('`project_id` = ? AND `completed_on` = ? AND `is_private` = ?', $this->getId(), EMPTY_DATETIME, 0), - 'order' => 'due_date' - )); // findAll - } // if - return $this->open_milestones; - } // getOpenMilestones - - /** - * This function will return all completed milestones - * - * @param void - * @return array - */ - function getAllCompletedMilestones() { - if(is_null($this->all_completed_milestones)) { - $this->all_completed_milestones = ProjectMilestones::findAll(array( - 'conditions' => array('`project_id` = ? AND `completed_on` > ?', $this->getId(), EMPTY_DATETIME), - 'order' => 'due_date' - )); // findAll - } // if - return $this->all_completed_milestones; - } // getAllCompletedMilestones - - /** - * Return completed milestones - * - * @access public - * @param void - * @return array - */ - function getCompletedMilestones() { - if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllCompletedMilestones(); - if(is_null($this->completed_milestones)) { - $this->completed_milestones = ProjectMilestones::findAll(array( - 'conditions' => array('`project_id` = ? AND `completed_on` > ? AND `is_private` = ?', $this->getId(), EMPTY_DATETIME, 0), - 'order' => 'due_date' - )); // findAll - } // if - return $this->completed_milestones; - } // getCompletedMilestones - - /** - * Return array of late open milestones - * - * @param void - * @return array - */ - function getLateMilestones() { - if($this->late_milestones === false) $this->splitOpenMilestones(); - return $this->late_milestones; - } // getLateMilestones - - /** - * Return array of today open milestones - * - * @param void - * @return array - */ - function getTodayMilestones() { - if($this->today_milestones === false) $this->splitOpenMilestones(); - return $this->today_milestones; - } // getTodayMilestones - - /** - * Return array of upcoming open milestones - * - * @param void - * @return array - */ - function getUpcomingMilestones() { - if($this->upcoming_milestones === false) $this->splitOpenMilestones(); - return $this->upcoming_milestones; - } // getUpcomingMilestones - - /** - * This function will walk through open milestones array and splid them into late, today and upcomming - * - * @param void - * @return array - */ - private function splitOpenMilestones() { - $open_milestones = $this->getOpenMilestones(); - - // Reset from false - $this->late_milestones = null; - $this->today_milestones = null; - $this->upcoming_milestones = null; - - if(is_array($open_milestones)) { - foreach($open_milestones as $open_milestone) { - if($open_milestone->isLate()) { - if(!is_array($this->late_milestones)) $this->late_milestones = array(); - $this->late_milestones[] = $open_milestone; - } elseif($open_milestone->isToday()) { - if(!is_array($this->today_milestones)) $this->today_milestones = array(); - $this->today_milestones[] = $open_milestone; - } else { - if(!is_array($this->upcoming_milestones)) $this->upcoming_milestones = array(); - $this->upcoming_milestones[] = $open_milestone; - } // if - } // foreach - } // if - } // splitOpenMilestones - - // --------------------------------------------------- - // Task lists - // --------------------------------------------------- - - /** - * Return all task lists - * - * @param void - * @return array - */ - function getAllTaskLists() { - if(is_null($this->all_task_lists)) { - $this->all_task_lists = ProjectTaskLists::findAll(array( - 'conditions' => array('`project_id` = ?', $this->getId()), - 'order' => '`order`' - )); // findAll - } // if - return $this->all_task_lists; - } // getAllTaskLists - - /** - * Return all taks lists - * - * @access public - * @param void - * @return array - */ - function getTaskLists() { - if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllTaskLists(); - if(is_null($this->task_lists)) { - $this->task_lists = ProjectTaskLists::findAll(array( - 'conditions' => array('`project_id` = ? AND `is_private` = ?', $this->getId(), 0), - 'order' => '`order`' - )); // findAll - } // if - return $this->task_lists; - } // getTaskLists - - /** - * Return all open task lists from this project - * - * @param void - * @return array - */ - function getAllOpenTaskLists() { - if(is_null($this->all_open_task_lists)) { - $this->all_open_task_lists = ProjectTaskLists::findAll(array( - 'conditions' => array('`project_id` = ? AND `completed_on` = ?', $this->getId(), EMPTY_DATETIME), - 'order' => '`order`' - )); // findAll - } // if - return $this->all_open_task_lists; - } // getAllOpenTaskLists - - /** - * Return open task lists - * - * @access public - * @param void - * @return array - */ - function getOpenTaskLists() { - if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllOpenTaskLists(); - if(is_null($this->open_task_lists)) { - $this->open_task_lists = ProjectTaskLists::findAll(array( - 'conditions' => array('`project_id` = ? AND `completed_on` = ? AND `is_private` = ?', $this->getId(), EMPTY_DATETIME, 0), - 'order' => '`order`' - )); // findAll - } // if - return $this->open_task_lists; - } // getOpenTaskLists - - /** - * Return all completed task lists - * - * @param void - * @return array - */ - function getAllCompletedTaskLists() { - if(is_null($this->all_completed_task_lists)) { - $this->all_completed_task_lists = ProjectTaskLists::findAll(array( - 'conditions' => array('`project_id` = ? AND `completed_on` > ?', $this->getId(), EMPTY_DATETIME), - 'order' => '`order`' - )); // findAll - } // if - return $this->all_completed_task_lists; - } // getAllCompletedTaskLists - - /** - * Return completed task lists - * - * @access public - * @param void - * @return array - */ - function getCompletedTaskLists() { - if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllCompletedTaskLists(); - if(is_null($this->completed_task_lists)) { - $this->completed_task_lists = ProjectTaskLists::findAll(array( - 'conditions' => array('`project_id` = ? AND `completed_on` > ? AND `is_private` = ?', $this->getId(), EMPTY_DATETIME, 0), - 'order' => '`order`' - )); // findAll - } // if - return $this->completed_task_lists; - } // getCompletedTaskLists - - // --------------------------------------------------- - // Tags - // --------------------------------------------------- - - /** - * This function will return unique tags used on objects of this project. Result is cached! - * - * @access public - * @param void - * @return array - */ - function getTagNames() { - $exclude_private = !logged_user()->isMemberOfOwnerCompany(); - if(is_null($this->tag_names)) { - $this->tag_names = Tags::getProjectTagNames($this, $exclude_private); - } // if - return $this->tag_names; - } // getTagNames - - /** - * This function return associative array of project objects tagged with specific tag. Array has following elements: - * - * - messages - * - milestones - * - tast lists - * - files - * - * @access public - * @param string $tag - * @return array - */ - function getObjectsByTag($tag) { - $exclude_private = !logged_user()->isMemberOfOwnerCompany(); - return array( - 'messages' => Tags::getProjectObjects($this, $tag, 'ProjectMessages', $exclude_private), - 'milestones' => Tags::getProjectObjects($this, $tag, 'ProjectMilestones', $exclude_private), - 'task_lists' => Tags::getProjectObjects($this, $tag, 'ProjectTaskLists', $exclude_private), - 'files' => Tags::getProjectObjects($this, $tag, 'ProjectFiles', $exclude_private), - ); // array - } // getObjectsByTag - - /** - * Return number of project objects tagged with $tag - * - * @param string $tag - * @return integer - */ - function countObjectsByTag($tag) { - $exclude_private = !logged_user()->isMemberOfOwnerCompany(); - return Tags::countProjectObjectsByTag($tag, $this, $exclude_private); - } // countObjectsByTag - - // --------------------------------------------------- - // Project log - // --------------------------------------------------- - - /** - * Return full project log - * - * @param integer $limit - * @param integer $offset - * @return array - */ - function getFullProjectLog($limit = null, $offset = null) { - return ApplicationLogs::getProjectLogs($this, true, true, $limit, $offset); - } // getFullProjectLog - - /** - * Return all project log entries that this user can see - * - * @param integer $limit Number of logs that will be returned - * @param integer $offset Return from this record - * @return array - */ - function getProjectLog($limit = null, $offset = null) { - $include_private = logged_user()->isMemberOfOwnerCompany(); - $include_silent = logged_user()->isAdministrator(); - - return ApplicationLogs::getProjectLogs($this, $include_private, $include_silent, $limit, $offset); - } // getProjectLog - - /** - * Return number of logs for this project - * - * @access public - * @param void - * @return null - */ - function countProjectLogs() { - return ApplicationLogs::count(array('`project_id` = ?', $this->getId())); - } // countProjectLogs - - // --------------------------------------------------- - // Project forms - // --------------------------------------------------- - - /** - * Return all project forms - * - * @param void - * @return array - */ - function getAllForms() { - if(is_null($this->all_forms)) { - $this->all_forms = ProjectForms::findAll(array( - 'conditions' => array('`project_id` = ?', $this->getId()), - 'order' => '`order`' - )); // findAll - } // if - return $this->all_forms; - } // getAllForms - - /** - * Return only visible project forms - * - * @param void - * @return null - */ - function getVisibleForms($only_enabled = false) { - $conditions = '`project_id` = ' . DB::escape($this->getId()); - if($only_enabled) { - $conditions .= ' AND `is_enabled` = ' . DB::escape(true); - } // if - - return ProjectForms::findAll(array( - 'conditions' => $conditions, - 'order' => '`order`' - )); // findAll - } // getVisibleForms - - /** - * Return owner company object - * - * @access public - * @param void - * @return Company - */ - function getCompany() { - return owner_company(); - } // getCompany - - /** - * Get all companies involved in this project - * - * @access public - * @param boolean $include_owner_company Include owner in result - * @return array - */ - function getCompanies($include_owner_company = true) { - $result = array(); - if($include_owner_company) $result[] = $this->getCompany(); - - $companies = ProjectCompanies::getCompaniesByProject($this); - if(is_array($companies)) { - $result = array_merge($result, $companies); - } // if - - return $result; - } // getCompanies - - /** - * Remove all companies from project - * - * @access public - * @param void - * @return boolean - */ - function clearCompanies() { - return ProjectCompanies::clearByProject($this); - } // clearCompanies - - /** - * Return all users involved in this project - * - * @access public - * @param void - * @return array - */ - function getUsers($group_by_company = true) { - $users = ProjectUsers::getUsersByProject($this); - if(!is_array($users) || !count($users)) { - return null; - } // if - - if($group_by_company) { - - $grouped = array(); - foreach($users as $user) { - if(!isset($grouped[$user->getCompanyId()]) || !is_array($grouped[$user->getCompanyId()])) { - $grouped[$user->getCompanyId()] = array(); - } // if - $grouped[$user->getCompanyId()][] = $user; - } // foreach - return $grouped; - - } else { - return $users; - } // if - } // getUsers - - /** - * Remove all users from project - * - * @access public - * @param void - * @return boolean - */ - function clearUsers() { - return ProjectUsers::clearByProject($this); - } // clearUsers - - /** - * Return user who created this milestone - * - * @access public - * @param void - * @return User - */ - function getCreatedBy() { - return Users::findById($this->getCreatedById()); - } // getCreatedBy - - /** - * Return user who completed this project - * - * @access public - * @param void - * @return User - */ - function getCompletedBy() { - return Users::findById($this->getCompletedById()); - } // getCompletedBy - - /** - * Return display name of user who completed this project - * - * @access public - * @param void - * @return string - */ - function getCompletedByDisplayName() { - $completed_by = $this->getCompletedBy(); - return $completed_by instanceof User ? $completed_by->getDisplayName() : lang('n/a'); - } // getCompletedByDisplayName - - // --------------------------------------------------- - // User tasks - // --------------------------------------------------- - - /** - * Return array of milestones that are assigned to specific user or his company - * - * @param User $user - * @return array - */ - function getUsersMilestones(User $user) { - $conditions = DB::prepareString('`project_id` = ? AND ((`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?) OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?) OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?)) AND `completed_on` = ?', array($this->getId(), $user->getId(), $user->getCompanyId(), 0, $user->getCompanyId(), 0, 0, EMPTY_DATETIME)); - if(!$user->isMemberOfOwnerCompany()) { - $conditions .= DB::prepareString(' AND `is_private` = ?', array(0)); - } // if - return ProjectMilestones::findAll(array( - 'conditions' => $conditions, - 'order' => '`due_date`' - )); - } // getUsersMilestones - - /** - * Return array of task that are assigned to specific user or his company - * - * @param User $user - * @return array - */ - function getUsersTasks(User $user) { - $task_lists = $this->getTaskLists(); - if(!is_array($task_lists)) { - return false; - } // if - - $task_list_ids = array(); - foreach($task_lists as $task_list) { - if(!$user->isMemberOfOwnerCompany() && $task_list->isPrivate()) { - continue; - } // if - $task_list_ids[] = $task_list->getId(); - } // if - - return ProjectTasks::findAll(array( - 'conditions' => array('`task_list_id` IN (?) AND ((`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?) OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?) OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?)) AND `completed_on` = ?', $task_list_ids, $user->getId(), $user->getCompanyId(), 0, $user->getCompanyId(), 0, 0, EMPTY_DATETIME), - 'order' => '`created_on`' - )); // findAll - } // getUsersTasks - - // --------------------------------------------------- - // Files - // --------------------------------------------------- - - function getFolders() { - if(is_null($this->folders)) { - $this->folders = ProjectFolders::getProjectFolders($this); - } // if - return $this->folders; - } // getFolders - - /** - * Return all important files - * - * @param void - * @return array - */ - function getAllImportantFiles() { - if(is_null($this->all_important_files)) { - $this->all_important_files = ProjectFiles::getImportantProjectFiles($this, true); - } // if - return $this->all_important_files; - } // getAllImportantFiles - - /** - * Return important files - * - * @param void - * @return array - */ - function getImportantFiles() { - if(logged_user()->isMemberOfOwnerCompany()) { - return $this->getAllImportantFiles(); - } // if - - if(is_null($this->important_files)) { - $this->important_files = ProjectFiles::getImportantProjectFiles($this, false); - } // if - return $this->important_files; - } // getImportantFiles - - /** - * Return all orphaned files - * - * @param void - * @return array - */ - function getAllOrphanedFiles() { - if(is_null($this->all_orphaned_files)) { - $this->all_orphaned_files = ProjectFiles::getOrphanedFilesByProject($this, true); - } // - return $this->all_orphaned_files; - } // getAllOrphanedFiles - - /** - * Return orphaned files - * - * @param void - * @return array - */ - function getOrphanedFiles() { - if(is_null($this->orphaned_files)) { - $this->orphaned_files = ProjectFiles::getOrphanedFilesByProject($this, logged_user()->isMemberOfOwnerCompany()); - } // if - return $this->orphaned_files; - } // getOrphanedFiles - - // --------------------------------------------------- - // Status - // --------------------------------------------------- - - /** - * Check if this project is active - * - * @access public - * @param void - * @return boolean - */ - function isActive() { - return !$this->isCompleted(); - } // isActive - - /** - * Check if this project is completed - * - * @access public - * @param void - * @return boolean - */ - function isCompleted() { - return (boolean) $this->getCompletedOn(); - } // isCompleted - - // --------------------------------------------------- - // Permissions - // --------------------------------------------------- - - /** - * Check if user can add project - * - * @access public - * @param void - * @return null - */ - function canAdd(User $user) { - return $user->isAccountOwner() || $user->isAdministrator(owner_company()); - } // canAdd - - /** - * Returns true if user can update speicific project - * - * @access public - * @param User $user - * @return boolean - */ - function canEdit(User $user) { - return $user->isAccountOwner() || $user->isAdministrator(owner_company()); - } // canEdit - - /** - * Returns true if user can delete specific project - * - * @access public - * @param User $user - * @return boolean - */ - function canDelete(User $user) { - return $user->isAccountOwner() || $user->isAdministrator(owner_company()); - } // canDelete - - /** - * Returns true if user can change status of this project - * - * @access public - * @param User $user - * @return boolean - */ - function canChangeStatus(User $user) { - return $this->canEdit($user); - } // canChangeStatus - - /** - * Returns true if user can access permissions page and can update permissions - * - * @access public - * @param User $user - * @return boolean - */ - function canChangePermissions(User $user) { - return $user->isAccountOwner() || $user->isAdministrator(owner_company()); - } // canChangePermissions - - /** - * Check if specific user can remove company from project - * - * @access public - * @param User $user - * @param Company $remove_company Remove this company - * @return boolean - */ - function canRemoveCompanyFromProject(User $user, Company $remove_company) { - if($remove_company->isOwner()) return false; - return $user->isAccountOwner() || $user->isAdministrator(); - } // canRemoveCompanyFromProject - - /** - * Check if this user can remove other user from project - * - * @access public - * @param User $user - * @param User $remove_user User that need to be removed - * @return boolean - */ - function canRemoveUserFromProject(User $user, User $remove_user) { - if($remove_user->isAccountOwner()) return false; - return $user->isAccountOwner() || $user->isAdministrator(); - } // canRemoveUserFromProject - - // --------------------------------------------------- - // URLS - // --------------------------------------------------- - - /** - * Link to project overview page - * - * @access public - * @param void - * @return stirng - */ - function getOverviewUrl() { - return get_url('project', 'overview', array('active_project' => $this->getId())); - } // getOverviewUrl - - /** - * Return project messages index page URL - * - * @param void - * @return string - */ - function getMessagesUrl() { - return get_url('message', 'index', array('active_project' => $this->getId())); - } // getMessagesUrl - - /** - * Return project tasks index page URL - * - * @param void - * @return string - */ - function getTasksUrl() { - return get_url('task', 'index', array('active_project' => $this->getId())); - } // getTasksUrl - - /** - * Return project milestones index page URL - * - * @param void - * @return string - */ - function getMilestonesUrl() { - return get_url('milestone', 'index', array('active_project' => $this->getId())); - } // getMilestonesUrl - - /** - * Return project forms index page URL - * - * @param void - * @return string - */ - function getFormsUrl() { - return get_url('form', 'index', array('active_project' => $this->getId())); - } // getFormsUrl - - /** - * Return project people index page URL - * - * @param void - * @return string - */ - function getPeopleUrl() { - return get_url('project', 'people', array('active_project' => $this->getId())); - } // getPeopleUrl - - /** - * Return project permissions page URL - * - * @param void - * @return string - */ - function getPermissionsUrl() { - return get_url('project', 'permissions', array('active_project' => $this->getId())); - } // getPermissionsUrl - - /** - * Return search URL - * - * @param string $search_for - * @param integer $page - * @return string - */ - function getSearchUrl($search_for = null, $page = null) { - if(trim($search_for) <> '') { - $params = array( - 'active_project' => $this->getId(), - 'search_for' => $search_for, - 'page' => (integer) $page > 0 ? (integer) $page : 1 - ); // array - return get_url('project', 'search', $params); - } else { - return ROOT_URL . '/index.php'; - } // if - } // getSearchUrl - - /** - * Return edit project URL - * - * @access public - * @param void - * @return string - */ - function getEditUrl() { - return get_url('project', 'edit', array( - 'id' => $this->getId(), - 'active_project' => $this->getId(), - )); - } // getEditUrl - - /** - * Return delete project URL - * - * @access public - * @param void - * @return string - */ - function getDeleteUrl() { - return get_url('project', 'delete', array( - 'id' => $this->getId(), - 'active_project' => $this->getId(), - )); - } // getDeleteUrl - - /** - * Return complete project url - * - * @access public - * @param void - * @return string - */ - function getCompleteUrl() { - return get_url('project', 'complete', $this->getId()); - } // getCompleteUrl - - /** - * Return open project URL - * - * @access public - * @param void - * @return string - */ - function getOpenUrl() { - return get_url('project', 'open', $this->getId()); - } // getOpenUrl - - /** - * Return remove user from project URL - * - * @access public - * @param User $user - * @return string - */ - function getRemoveUserUrl(User $user) { - return get_url('project', 'remove_user', array('user_id' => $user->getId(), 'project_id' => $this->getId())); - } // getRemoveUserUrl - - /** - * Return remove company from project URL - * - * @access public - * @param Company $company - * @return string - */ - function getRemoveCompanyUrl(Company $company) { - return get_url('project', 'remove_company', array('company_id' => $company->getId(), 'project_id' => $this->getId())); - } // getRemoveCompanyUrl - - /** - * Return tag URL - * - * @access public - * @param string $tag_name - * @return string - */ - function getTagUrl($tag_name) { - return get_url('tag', 'project_tag', array('tag' => $tag_name, 'active_project' => $this->getId())); - } // getTagUrl - - // --------------------------------------------------- - // System functions - // --------------------------------------------------- - - /** - * Validate object before save - * - * @access public - * @param array $errors - * @return null - */ - function validate(&$errors) { - if(!$this->validatePresenceOf('name')) { - $errors[] = lang('project name required'); - } // if - if(!$this->validateUniquenessOf('name')) { - $errors[] = lang('project name unique'); - } // if - } // validate - - /** - * Delete project - * - * @param void - * @return boolean - */ - function delete() { - $this->clearMessages(); - $this->clearTaskLists(); - $this->clearMilestones(); - $this->clearFiles(); - $this->clearFolders(); - $this->clearForms(); - $this->clearPermissions(); - $this->clearLogs(); - return parent::delete(); - } // delete - - /** - * Clear all project messages - * - * @param void - * @return null - */ - private function clearMessages() { - $messages = $this->getAllMessages(); - if(is_array($messages)) { - foreach($messages as $message) { - $message->delete(); - } // foreach - } // if - } // clearMessages - - /** - * Clear all task lists - * - * @param void - * @return null - */ - private function clearTaskLists() { - $task_lists = $this->getAllTaskLists(); - if(is_array($task_lists)) { - foreach($task_lists as $task_list) { - $task_list->delete(); - } // foreach - } // if - } // clearTaskLists - - /** - * Clear all milestones - * - * @param void - * @return null - */ - private function clearMilestones() { - $milestones = $this->getAllMilestones(); - if(is_array($milestones)) { - foreach($milestones as $milestone) { - $milestone->delete(); - } // foreach - } // if - } // clearMilestones - - /** - * Clear forms - * - * @param void - * @return null - */ - private function clearForms() { - $forms = $this->getAllForms(); - if(is_array($forms)) { - foreach($forms as $form) { - $form->delete(); - } // foreach - } // if - } // clearForms - - /** - * Clear all files and folders - * - * @param void - * @return null - */ - private function clearFiles() { - $files = ProjectFiles::getAllFilesByProject($this); - if(is_array($files)) { - foreach($files as $file) { - $file->delete(); - } // foreach - } // if - } // clearFiles - - /** - * Clear all folders - * - * @param void - * @return null - */ - private function clearFolders() { - $folders = $this->getFolders(); - if(is_array($folders)) { - foreach($folders as $folder) { - $folder->delete(); - } // foreach - } // if - } // clearFolders - - /** - * Clear project level permissions - * - * @param void - * @return null - */ - function clearPermissions() { - ProjectCompanies::clearByProject($this); - ProjectUsers::clearByProject($this); - } // clearPermissions - - /** - * Clear application logs for this project - * - * @param void - * @return null - */ - function clearLogs() { - ApplicationLogs::clearByProject($this); - } // clearLogs - - // --------------------------------------------------- - // ApplicationDataObject implementation - // --------------------------------------------------- - - /** - * Return object type name - * - * @param void - * @return string - */ - function getObjectTypeName() { - return lang('project'); - } // getObjectTypeName - - /** - * Return object URl - * - * @access public - * @param void - * @return string - */ - function getObjectUrl() { - return $this->getOverviewUrl(); - } // getObjectUrl - - } // Project - +all_messages)) { + $this->all_messages = ProjectMessages::getProjectMessages($this, true); + } // if + return $this->all_messages; + } // getAllMessages + + /** + * Return only the messages that current user can see (if not member of owner company private + * messages will be excluded) + * + * @param null + * @return null + */ + function getMessages() { + if(logged_user()->isMemberOfOwnerCompany()) { + return $this->getAllMessages(); // members of owner company can view all messages + } // if + + if(is_null($this->messages)) { + $this->messages = ProjectMessages::getProjectMessages($this, false); + } // if + return $this->messages; + } // getMessages + + /** + * Return all important messages + * + * @param void + * @return array + */ + function getAllImportantMessages() { + if(is_null($this->all_important_messages)) { + $this->all_important_messages = ProjectMessages::getImportantProjectMessages($this, true); + } // if + return $this->all_important_messages; + } // getAllImportantMessages + + /** + * Return array of important messages + * + * @param void + * @return array + */ + function getImportantMessages() { + if(logged_user()->isMemberOfOwnerCompany()) { + return $this->getAllImportantMessages(); + } // if + + if(is_null($this->important_messages)) { + $this->important_messages = ProjectMessages::getImportantProjectMessages($this, false); + } // if + return $this->important_messages; + } // getImportantMessages + + // --------------------------------------------------- + // Milestones + // --------------------------------------------------- + + /** + * Return all milestones, don't filter them by is_private stamp based on users permissions + * + * @param void + * @return array + */ + function getAllMilestones() { + if(is_null($this->all_milestones)) { + $this->all_milestones = ProjectMilestones::findAll(array( + 'conditions' => array('`project_id` = ?', $this->getId()), + 'order' => 'due_date' + )); // findAll + } // if + return $this->all_milestones; + } // getAllMilestones + + /** + * Return all project milestones + * + * @access public + * @param void + * @return array + */ + function getMilestones() { + if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllMilestones(); // member of owner company + if(is_null($this->milestones)) { + $this->milestones = ProjectMilestones::findAll(array( + 'conditions' => array('`project_id` = ? AND `is_private` = ?', $this->getId(), 0), + 'order' => 'due_date' + )); // findAll + } // if + return $this->milestones; + } // getMilestones + + /** + * Return all opet milestones without is_private check + * + * @param void + * @return array + */ + function getAllOpenMilestones() { + if(is_null($this->all_open_milestones)) { + $this->all_open_milestones = ProjectMilestones::findAll(array( + 'conditions' => array('`project_id` = ? AND `completed_on` = ?', $this->getId(), EMPTY_DATETIME), + 'order' => 'due_date' + )); // findAll + } // if + return $this->all_open_milestones; + } // getAllOpenMilestones + + /** + * Return open milestones + * + * @access public + * @param void + * @return array + */ + function getOpenMilestones() { + if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllOpenMilestones(); + if(is_null($this->open_milestones)) { + $this->open_milestones = ProjectMilestones::findAll(array( + 'conditions' => array('`project_id` = ? AND `completed_on` = ? AND `is_private` = ?', $this->getId(), EMPTY_DATETIME, 0), + 'order' => 'due_date' + )); // findAll + } // if + return $this->open_milestones; + } // getOpenMilestones + + /** + * This function will return all completed milestones + * + * @param void + * @return array + */ + function getAllCompletedMilestones() { + if(is_null($this->all_completed_milestones)) { + $this->all_completed_milestones = ProjectMilestones::findAll(array( + 'conditions' => array('`project_id` = ? AND `completed_on` > ?', $this->getId(), EMPTY_DATETIME), + 'order' => 'due_date' + )); // findAll + } // if + return $this->all_completed_milestones; + } // getAllCompletedMilestones + + /** + * Return completed milestones + * + * @access public + * @param void + * @return array + */ + function getCompletedMilestones() { + if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllCompletedMilestones(); + if(is_null($this->completed_milestones)) { + $this->completed_milestones = ProjectMilestones::findAll(array( + 'conditions' => array('`project_id` = ? AND `completed_on` > ? AND `is_private` = ?', $this->getId(), EMPTY_DATETIME, 0), + 'order' => 'due_date' + )); // findAll + } // if + return $this->completed_milestones; + } // getCompletedMilestones + + /** + * Return array of late open milestones + * + * @param void + * @return array + */ + function getLateMilestones() { + if($this->late_milestones === false) $this->splitOpenMilestones(); + return $this->late_milestones; + } // getLateMilestones + + /** + * Return array of today open milestones + * + * @param void + * @return array + */ + function getTodayMilestones() { + if($this->today_milestones === false) $this->splitOpenMilestones(); + return $this->today_milestones; + } // getTodayMilestones + + /** + * Return array of upcoming open milestones + * + * @param void + * @return array + */ + function getUpcomingMilestones() { + if($this->upcoming_milestones === false) $this->splitOpenMilestones(); + return $this->upcoming_milestones; + } // getUpcomingMilestones + + /** + * This function will walk through open milestones array and splid them into late, today and upcomming + * + * @param void + * @return array + */ + private function splitOpenMilestones() { + $open_milestones = $this->getOpenMilestones(); + + // Reset from false + $this->late_milestones = null; + $this->today_milestones = null; + $this->upcoming_milestones = null; + + if(is_array($open_milestones)) { + foreach($open_milestones as $open_milestone) { + if($open_milestone->isLate()) { + if(!is_array($this->late_milestones)) $this->late_milestones = array(); + $this->late_milestones[] = $open_milestone; + } elseif($open_milestone->isToday()) { + if(!is_array($this->today_milestones)) $this->today_milestones = array(); + $this->today_milestones[] = $open_milestone; + } else { + if(!is_array($this->upcoming_milestones)) $this->upcoming_milestones = array(); + $this->upcoming_milestones[] = $open_milestone; + } // if + } // foreach + } // if + } // splitOpenMilestones + + // --------------------------------------------------- + // Time + // --------------------------------------------------- + + /** + * Return all times, don't filter them by is_private stamp based on users permissions + * + * @param void + * @return array + */ + function getAllTimes() { + if(is_null($this->all_times)) { + $this->all_times = ProjectTimes::findAll(array( + 'conditions' => array('`project_id` = ?', $this->getId()), + 'order' => 'done_date desc' + )); // findAll + } // if + return $this->all_times; + } // getAllTimes + + /** + * Return all project time + * + * @access public + * @param void + * @return array + */ + function getTimes() { + if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllTimes(); // member of owner company + if(is_null($this->times)) { + $this->times = ProjectTimes::findAll(array( + 'conditions' => array('`project_id` = ? AND `is_private` = ?', $this->getId(), 0), + 'order' => 'done_date desc' + )); // findAll + } // if + return $this->times; + } // getTimes + + // --------------------------------------------------- + // Task lists + // --------------------------------------------------- + + /** + * Return all task lists + * + * @param void + * @return array + */ + function getAllTaskLists() { + if(is_null($this->all_task_lists)) { + $this->all_task_lists = ProjectTaskLists::findAll(array( + 'conditions' => array('`project_id` = ?', $this->getId()), + 'order' => '`order`' + )); // findAll + } // if + return $this->all_task_lists; + } // getAllTaskLists + + /** + * Return all taks lists + * + * @access public + * @param void + * @return array + */ + function getTaskLists() { + if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllTaskLists(); + if(is_null($this->task_lists)) { + $this->task_lists = ProjectTaskLists::findAll(array( + 'conditions' => array('`project_id` = ? AND `is_private` = ?', $this->getId(), 0), + 'order' => '`order`' + )); // findAll + } // if + return $this->task_lists; + } // getTaskLists + + /** + * Return all open task lists from this project + * + * @param void + * @return array + */ + function getAllOpenTaskLists() { + if(is_null($this->all_open_task_lists)) { + $this->all_open_task_lists = ProjectTaskLists::findAll(array( + 'conditions' => array('`project_id` = ? AND `completed_on` = ?', $this->getId(), EMPTY_DATETIME), + 'order' => '`order`' + )); // findAll + } // if + return $this->all_open_task_lists; + } // getAllOpenTaskLists + + /** + * Return open task lists + * + * @access public + * @param void + * @return array + */ + function getOpenTaskLists() { + if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllOpenTaskLists(); + if(is_null($this->open_task_lists)) { + $this->open_task_lists = ProjectTaskLists::findAll(array( + 'conditions' => array('`project_id` = ? AND `completed_on` = ? AND `is_private` = ?', $this->getId(), EMPTY_DATETIME, 0), + 'order' => '`order`' + )); // findAll + } // if + return $this->open_task_lists; + } // getOpenTaskLists + + /** + * Return all completed task lists + * + * @param void + * @return array + */ + function getAllCompletedTaskLists() { + if(is_null($this->all_completed_task_lists)) { + $this->all_completed_task_lists = ProjectTaskLists::findAll(array( + 'conditions' => array('`project_id` = ? AND `completed_on` > ?', $this->getId(), EMPTY_DATETIME), + 'order' => '`order`' + )); // findAll + } // if + return $this->all_completed_task_lists; + } // getAllCompletedTaskLists + + /** + * Return completed task lists + * + * @access public + * @param void + * @return array + */ + function getCompletedTaskLists() { + if(logged_user()->isMemberOfOwnerCompany()) return $this->getAllCompletedTaskLists(); + if(is_null($this->completed_task_lists)) { + $this->completed_task_lists = ProjectTaskLists::findAll(array( + 'conditions' => array('`project_id` = ? AND `completed_on` > ? AND `is_private` = ?', $this->getId(), EMPTY_DATETIME, 0), + 'order' => '`order`' + )); // findAll + } // if + return $this->completed_task_lists; + } // getCompletedTaskLists + + // --------------------------------------------------- + // Tags + // --------------------------------------------------- + + /** + * This function will return unique tags used on objects of this project. Result is cached! + * + * @access public + * @param void + * @return array + */ + function getTagNames() { + $exclude_private = !logged_user()->isMemberOfOwnerCompany(); + if(is_null($this->tag_names)) { + $this->tag_names = Tags::getProjectTagNames($this, $exclude_private); + } // if + return $this->tag_names; + } // getTagNames + + /** + * This function return associative array of project objects tagged with specific tag. Array has following elements: + * + * - messages + * - milestones + * - tast lists + * - files + * + * @access public + * @param string $tag + * @return array + */ + function getObjectsByTag($tag) { + $exclude_private = !logged_user()->isMemberOfOwnerCompany(); + return array( + 'messages' => Tags::getProjectObjects($this, $tag, 'ProjectMessages', $exclude_private), + 'milestones' => Tags::getProjectObjects($this, $tag, 'ProjectMilestones', $exclude_private), + 'task_lists' => Tags::getProjectObjects($this, $tag, 'ProjectTaskLists', $exclude_private), + 'files' => Tags::getProjectObjects($this, $tag, 'ProjectFiles', $exclude_private), + ); // array + } // getObjectsByTag + + /** + * Return number of project objects tagged with $tag + * + * @param string $tag + * @return integer + */ + function countObjectsByTag($tag) { + $exclude_private = !logged_user()->isMemberOfOwnerCompany(); + return Tags::countProjectObjectsByTag($tag, $this, $exclude_private); + } // countObjectsByTag + + // --------------------------------------------------- + // Project log + // --------------------------------------------------- + + /** + * Return full project log + * + * @param integer $limit + * @param integer $offset + * @return array + */ + function getFullProjectLog($limit = null, $offset = null) { + return ApplicationLogs::getProjectLogs($this, true, true, $limit, $offset); + } // getFullProjectLog + + /** + * Return all project log entries that this user can see + * + * @param integer $limit Number of logs that will be returned + * @param integer $offset Return from this record + * @return array + */ + function getProjectLog($limit = null, $offset = null) { + $include_private = logged_user()->isMemberOfOwnerCompany(); + $include_silent = logged_user()->isAdministrator(); + + return ApplicationLogs::getProjectLogs($this, $include_private, $include_silent, $limit, $offset); + } // getProjectLog + + /** + * Return number of logs for this project + * + * @access public + * @param void + * @return null + */ + function countProjectLogs() { + return ApplicationLogs::count(array('`project_id` = ?', $this->getId())); + } // countProjectLogs + + // --------------------------------------------------- + // Project forms + // --------------------------------------------------- + + /** + * Return all project forms + * + * @param void + * @return array + */ + function getAllForms() { + if(is_null($this->all_forms)) { + $this->all_forms = ProjectForms::findAll(array( + 'conditions' => array('`project_id` = ?', $this->getId()), + 'order' => '`order`' + )); // findAll + } // if + return $this->all_forms; + } // getAllForms + + /** + * Return only visible project forms + * + * @param void + * @return null + */ + function getVisibleForms($only_enabled = false) { + $conditions = '`project_id` = ' . DB::escape($this->getId()); + if($only_enabled) { + $conditions .= ' AND `is_enabled` = ' . DB::escape(true); + } // if + + return ProjectForms::findAll(array( + 'conditions' => $conditions, + 'order' => '`order`' + )); // findAll + } // getVisibleForms + + /** + * Return owner company object + * + * @access public + * @param void + * @return Company + */ + function getCompany() { + return owner_company(); + } // getCompany + + /** + * Get all companies involved in this project + * + * @access public + * @param boolean $include_owner_company Include owner in result + * @return array + */ + function getCompanies($include_owner_company = true) { + $result = array(); + if($include_owner_company) $result[] = $this->getCompany(); + + $companies = ProjectCompanies::getCompaniesByProject($this); + if(is_array($companies)) { + $result = array_merge($result, $companies); + } // if + + return $result; + } // getCompanies + + /** + * Remove all companies from project + * + * @access public + * @param void + * @return boolean + */ + function clearCompanies() { + return ProjectCompanies::clearByProject($this); + } // clearCompanies + + /** + * Return all users involved in this project + * + * @access public + * @param void + * @return array + */ + function getUsers($group_by_company = true) { + $users = ProjectUsers::getUsersByProject($this); + if(!is_array($users) || !count($users)) { + return null; + } // if + + if($group_by_company) { + + $grouped = array(); + foreach($users as $user) { + if(!isset($grouped[$user->getCompanyId()]) || !is_array($grouped[$user->getCompanyId()])) { + $grouped[$user->getCompanyId()] = array(); + } // if + $grouped[$user->getCompanyId()][] = $user; + } // foreach + return $grouped; + + } else { + return $users; + } // if + } // getUsers + + /** + * Remove all users from project + * + * @access public + * @param void + * @return boolean + */ + function clearUsers() { + return ProjectUsers::clearByProject($this); + } // clearUsers + + /** + * Return user who created this milestone + * + * @access public + * @param void + * @return User + */ + function getCreatedBy() { + return Users::findById($this->getCreatedById()); + } // getCreatedBy + + /** + * Return user who completed this project + * + * @access public + * @param void + * @return User + */ + function getCompletedBy() { + return Users::findById($this->getCompletedById()); + } // getCompletedBy + + /** + * Return display name of user who completed this project + * + * @access public + * @param void + * @return string + */ + function getCompletedByDisplayName() { + $completed_by = $this->getCompletedBy(); + return $completed_by instanceof User ? $completed_by->getDisplayName() : lang('n/a'); + } // getCompletedByDisplayName + + // --------------------------------------------------- + // User tasks + // --------------------------------------------------- + + /** + * Return array of milestones that are assigned to specific user or his company + * + * @param User $user + * @return array + */ + function getUsersMilestones(User $user) { + $conditions = DB::prepareString('`project_id` = ? AND ((`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?) OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?) OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?)) AND `completed_on` = ?', array($this->getId(), $user->getId(), $user->getCompanyId(), 0, $user->getCompanyId(), 0, 0, EMPTY_DATETIME)); + if(!$user->isMemberOfOwnerCompany()) { + $conditions .= DB::prepareString(' AND `is_private` = ?', array(0)); + } // if + return ProjectMilestones::findAll(array( + 'conditions' => $conditions, + 'order' => '`due_date`' + )); + } // getUsersMilestones + + /** + * Return array of task that are assigned to specific user or his company + * + * @param User $user + * @return array + */ + function getUsersTasks(User $user) { + $task_lists = $this->getTaskLists(); + if(!is_array($task_lists)) { + return false; + } // if + + $task_list_ids = array(); + foreach($task_lists as $task_list) { + if(!$user->isMemberOfOwnerCompany() && $task_list->isPrivate()) { + continue; + } // if + $task_list_ids[] = $task_list->getId(); + } // if + + return ProjectTasks::findAll(array( + 'conditions' => array('`task_list_id` IN (?) AND ((`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?) OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?) OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?)) AND `completed_on` = ?', $task_list_ids, $user->getId(), $user->getCompanyId(), 0, $user->getCompanyId(), 0, 0, EMPTY_DATETIME), + 'order' => '`created_on`' + )); // findAll + } // getUsersTasks + + // --------------------------------------------------- + // Files + // --------------------------------------------------- + + function getFolders() { + if(is_null($this->folders)) { + $this->folders = ProjectFolders::getProjectFolders($this); + } // if + return $this->folders; + } // getFolders + + /** + * Return all important files + * + * @param void + * @return array + */ + function getAllImportantFiles() { + if(is_null($this->all_important_files)) { + $this->all_important_files = ProjectFiles::getImportantProjectFiles($this, true); + } // if + return $this->all_important_files; + } // getAllImportantFiles + + /** + * Return important files + * + * @param void + * @return array + */ + function getImportantFiles() { + if(logged_user()->isMemberOfOwnerCompany()) { + return $this->getAllImportantFiles(); + } // if + + if(is_null($this->important_files)) { + $this->important_files = ProjectFiles::getImportantProjectFiles($this, false); + } // if + return $this->important_files; + } // getImportantFiles + + /** + * Return all orphaned files + * + * @param void + * @return array + */ + function getAllOrphanedFiles() { + if(is_null($this->all_orphaned_files)) { + $this->all_orphaned_files = ProjectFiles::getOrphanedFilesByProject($this, true); + } // + return $this->all_orphaned_files; + } // getAllOrphanedFiles + + /** + * Return orphaned files + * + * @param void + * @return array + */ + function getOrphanedFiles() { + if(is_null($this->orphaned_files)) { + $this->orphaned_files = ProjectFiles::getOrphanedFilesByProject($this, logged_user()->isMemberOfOwnerCompany()); + } // if + return $this->orphaned_files; + } // getOrphanedFiles + + // --------------------------------------------------- + // Status + // --------------------------------------------------- + + /** + * Check if this project is active + * + * @access public + * @param void + * @return boolean + */ + function isActive() { + return !$this->isCompleted(); + } // isActive + + /** + * Check if this project is completed + * + * @access public + * @param void + * @return boolean + */ + function isCompleted() { + return (boolean) $this->getCompletedOn(); + } // isCompleted + + // --------------------------------------------------- + // Permissions + // --------------------------------------------------- + + /** + * Check if user can add project + * + * @access public + * @param void + * @return null + */ + function canAdd(User $user) { + return $user->isAccountOwner() || $user->isAdministrator(owner_company()); + } // canAdd + + /** + * Returns true if user can update speicific project + * + * @access public + * @param User $user + * @return boolean + */ + function canEdit(User $user) { + return $user->isAccountOwner() || $user->isAdministrator(owner_company()); + } // canEdit + + /** + * Returns true if user can delete specific project + * + * @access public + * @param User $user + * @return boolean + */ + function canDelete(User $user) { + return $user->isAccountOwner() || $user->isAdministrator(owner_company()); + } // canDelete + + /** + * Returns true if user can change status of this project + * + * @access public + * @param User $user + * @return boolean + */ + function canChangeStatus(User $user) { + return $this->canEdit($user); + } // canChangeStatus + + /** + * Returns true if user can access permissions page and can update permissions + * + * @access public + * @param User $user + * @return boolean + */ + function canChangePermissions(User $user) { + return $user->isAccountOwner() || $user->isAdministrator(owner_company()); + } // canChangePermissions + + /** + * Check if specific user can remove company from project + * + * @access public + * @param User $user + * @param Company $remove_company Remove this company + * @return boolean + */ + function canRemoveCompanyFromProject(User $user, Company $remove_company) { + if($remove_company->isOwner()) return false; + return $user->isAccountOwner() || $user->isAdministrator(); + } // canRemoveCompanyFromProject + + /** + * Check if this user can remove other user from project + * + * @access public + * @param User $user + * @param User $remove_user User that need to be removed + * @return boolean + */ + function canRemoveUserFromProject(User $user, User $remove_user) { + if($remove_user->isAccountOwner()) return false; + return $user->isAccountOwner() || $user->isAdministrator(); + } // canRemoveUserFromProject + + // --------------------------------------------------- + // URLS + // --------------------------------------------------- + + /** + * Link to project overview page + * + * @access public + * @param void + * @return stirng + */ + function getOverviewUrl() { + return get_url('project', 'overview', array('active_project' => $this->getId())); + } // getOverviewUrl + + /** + * Return project messages index page URL + * + * @param void + * @return string + */ + function getMessagesUrl() { + return get_url('message', 'index', array('active_project' => $this->getId())); + } // getMessagesUrl + + /** + * Return project tasks index page URL + * + * @param void + * @return string + */ + function getTasksUrl() { + return get_url('task', 'index', array('active_project' => $this->getId())); + } // getTasksUrl + + /** + * Return project milestones index page URL + * + * @param void + * @return string + */ + function getMilestonesUrl() { + return get_url('milestone', 'index', array('active_project' => $this->getId())); + } // getMilestonesUrl + + /** + * Return project forms index page URL + * + * @param void + * @return string + */ + function getFormsUrl() { + return get_url('form', 'index', array('active_project' => $this->getId())); + } // getFormsUrl + + /** + * Return project people index page URL + * + * @param void + * @return string + */ + function getPeopleUrl() { + return get_url('project', 'people', array('active_project' => $this->getId())); + } // getPeopleUrl + + /** + * Return project permissions page URL + * + * @param void + * @return string + */ + function getPermissionsUrl() { + return get_url('project', 'permissions', array('active_project' => $this->getId())); + } // getPermissionsUrl + + /** + * Return search URL + * + * @param string $search_for + * @param integer $page + * @return string + */ + function getSearchUrl($search_for = null, $page = null) { + if(trim($search_for) <> '') { + $params = array( + 'active_project' => $this->getId(), + 'search_for' => $search_for, + 'page' => (integer) $page > 0 ? (integer) $page : 1 + ); // array + return get_url('project', 'search', $params); + } else { + return ROOT_URL . '/index.php'; + } // if + } // getSearchUrl + + /** + * Return edit project URL + * + * @access public + * @param void + * @return string + */ + function getEditUrl() { + return get_url('project', 'edit', array( + 'id' => $this->getId(), + 'active_project' => $this->getId(), + )); + } // getEditUrl + + /** + * Return delete project URL + * + * @access public + * @param void + * @return string + */ + function getDeleteUrl() { + return get_url('project', 'delete', array( + 'id' => $this->getId(), + 'active_project' => $this->getId(), + )); + } // getDeleteUrl + + /** + * Return complete project url + * + * @access public + * @param void + * @return string + */ + function getCompleteUrl() { + return get_url('project', 'complete', $this->getId()); + } // getCompleteUrl + + /** + * Return open project URL + * + * @access public + * @param void + * @return string + */ + function getOpenUrl() { + return get_url('project', 'open', $this->getId()); + } // getOpenUrl + + /** + * Return remove user from project URL + * + * @access public + * @param User $user + * @return string + */ + function getRemoveUserUrl(User $user) { + return get_url('project', 'remove_user', array('user_id' => $user->getId(), 'project_id' => $this->getId())); + } // getRemoveUserUrl + + /** + * Return remove company from project URL + * + * @access public + * @param Company $company + * @return string + */ + function getRemoveCompanyUrl(Company $company) { + return get_url('project', 'remove_company', array('company_id' => $company->getId(), 'project_id' => $this->getId())); + } // getRemoveCompanyUrl + + /** + * Return tag URL + * + * @access public + * @param string $tag_name + * @return string + */ + function getTagUrl($tag_name) { + return get_url('tag', 'project_tag', array('tag' => $tag_name, 'active_project' => $this->getId())); + } // getTagUrl + + // --------------------------------------------------- + // System functions + // --------------------------------------------------- + + /** + * Validate object before save + * + * @access public + * @param array $errors + * @return null + */ + function validate(&$errors) { + if(!$this->validatePresenceOf('name')) { + $errors[] = lang('project name required'); + } // if + if(!$this->validateUniquenessOf('name')) { + $errors[] = lang('project name unique'); + } // if + } // validate + + /** + * Delete project + * + * @param void + * @return boolean + */ + function delete() { + $this->clearMessages(); + $this->clearTaskLists(); + $this->clearMilestones(); + $this->clearFiles(); + $this->clearFolders(); + $this->clearForms(); + $this->clearPermissions(); + $this->clearLogs(); + return parent::delete(); + } // delete + + /** + * Clear all project messages + * + * @param void + * @return null + */ + private function clearMessages() { + $messages = $this->getAllMessages(); + if(is_array($messages)) { + foreach($messages as $message) { + $message->delete(); + } // foreach + } // if + } // clearMessages + + /** + * Clear all task lists + * + * @param void + * @return null + */ + private function clearTaskLists() { + $task_lists = $this->getAllTaskLists(); + if(is_array($task_lists)) { + foreach($task_lists as $task_list) { + $task_list->delete(); + } // foreach + } // if + } // clearTaskLists + + /** + * Clear all milestones + * + * @param void + * @return null + */ + private function clearMilestones() { + $milestones = $this->getAllMilestones(); + if(is_array($milestones)) { + foreach($milestones as $milestone) { + $milestone->delete(); + } // foreach + } // if + } // clearMilestones + + /** + * Clear forms + * + * @param void + * @return null + */ + private function clearForms() { + $forms = $this->getAllForms(); + if(is_array($forms)) { + foreach($forms as $form) { + $form->delete(); + } // foreach + } // if + } // clearForms + + /** + * Clear all files and folders + * + * @param void + * @return null + */ + private function clearFiles() { + $files = ProjectFiles::getAllFilesByProject($this); + if(is_array($files)) { + foreach($files as $file) { + $file->delete(); + } // foreach + } // if + } // clearFiles + + /** + * Clear all folders + * + * @param void + * @return null + */ + private function clearFolders() { + $folders = $this->getFolders(); + if(is_array($folders)) { + foreach($folders as $folder) { + $folder->delete(); + } // foreach + } // if + } // clearFolders + + /** + * Clear project level permissions + * + * @param void + * @return null + */ + function clearPermissions() { + ProjectCompanies::clearByProject($this); + ProjectUsers::clearByProject($this); + } // clearPermissions + + /** + * Clear application logs for this project + * + * @param void + * @return null + */ + function clearLogs() { + ApplicationLogs::clearByProject($this); + } // clearLogs + + // --------------------------------------------------- + // ApplicationDataObject implementation + // --------------------------------------------------- + + /** + * Return object type name + * + * @param void + * @return string + */ + function getObjectTypeName() { + return lang('project'); + } // getObjectTypeName + + /** + * Return object URl + * + * @access public + * @param void + * @return string + */ + function getObjectUrl() { + return $this->getOverviewUrl(); + } // getObjectUrl + + } // Project + ?> \ No newline at end of file Index: application/models/project_times/ProjectTime.class.php =================================================================== --- application/models/project_times/ProjectTime.class.php (revision 0) +++ application/models/project_times/ProjectTime.class.php (revision 0) @@ -0,0 +1,313 @@ +getProjectId()); + } // getProject + + /** + * Return assigned to object. It can be User, Company or nobady (NULL) + * + * @access public + * @param void + * @return ApplicationDataObject + */ + function getAssignedTo() { + if($this->getAssignedToUserId() > 0) { + return $this->getAssignedToUser(); + } elseif($this->getAssignedToCompanyId() > 0) { + return $this->getAssignedToCompany(); + } else { + return null; + } // if + } // getAssignedTo + + /** + * Return responsible company + * + * @access public + * @param void + * @return Company + */ + protected function getAssignedToCompany() { + return Companies::findById($this->getAssignedToCompanyId()); + } // getAssignedToCompany + + /** + * Return responsible user + * + * @access public + * @param void + * @return User + */ + protected function getAssignedToUser() { + return Users::findById($this->getAssignedToUserId()); + } // getAssignedToUser + + /** + * Returns true if this time log is made today + * + * @access public + * @param void + * @return boolean + */ + function isToday() { + $now = DateTimeValueLib::now(); + $created_on = $this->getDoneDate(); + + // getCreatedOn and similar functions can return NULL + if(!($created_on instanceof DateTimeValue)) return false; + + return $now->getDay() == $created_on->getDay() && + $now->getMonth() == $created_on->getMonth() && + $now->getYear() == $created_on->getYear(); + } // isToday + + /** + * Returnst true if this application log was made yesterday + * + * @param void + * @return boolean + */ + function isYesterday() { + $created_on = $this->getDoneDate(); + if(!($created_on instanceof DateTimeValue)) return false; + + $day_after = $created_on->advance(24 * 60 * 60, false); + $now = DateTimeValueLib::now(); + + return $now->getDay() == $day_after->getDay() && + $now->getMonth() == $day_after->getMonth() && + $now->getYear() == $day_after->getYear(); + } // isYesterday + + + // --------------------------------------------------- + // Permissions + // --------------------------------------------------- + + /** + * Returns true if specific user has CAN_MANAGE_TIME permission set to true + * + * @access public + * @param User $user + * @return boolean + */ + function canManage(User $user) { + return $user->getProjectPermission($this->getProject(), ProjectUsers::CAN_MANAGE_TIME); + } // canManage + + /** + * Returns true if $user can view this time + * + * @param User $user + * @return boolean + */ + function canView(User $user) { + if(!$user->isProjectUser($this->getProject())) return false; + if($user->isAdministrator()) return true; + if($this->isPrivate() && !$user->isMemberOfOwnerCompany()) return false; + return true; + } // canView + + /** + * Check if specific user can add new time to specific project + * + * @access public + * @param User $user + * @param Project $project + * @return boolean + */ + function canAdd(User $user, Project $project) { + if(!$user->isProjectUser($project)) return false; + if($user->isAdministrator()) return true; + return $user->getProjectPermission($project, ProjectUsers::CAN_MANAGE_TIME); + } // canAdd + + /** + * Check if specific user can edit this time + * + * @access public + * @param User $user + * @return boolean + */ + function canEdit(User $user) { + if(!$user->isProjectUser($this->getProject())) return false; + if($user->isAdministrator()) return true; + if($this->getCreatedById() == $user->getId()) return true; + return false; + } // canEdit + + /** + * Can chagne status of this time + * + * @access public + * @param User $user + * @return boolean + */ + function canChangeStatus(User $user) { + if($this->canEdit($user)) return true; + + // Additional check - is this time assigned to this user or its company + if($this->getAssignedTo() instanceof User) { + if($user->getId() == $this->getAssignedTo()->getObjectId()) return true; + } elseif($this->getAssignedTo() instanceof Company) { + if($user->getCompanyId() == $this->getAssignedTo()->getObjectId()) return true; + } // if + return false; + } // canChangeStatus + + /** + * Check if specific user can delete this time + * + * @access public + * @param User $user + * @return boolean + */ + function canDelete(User $user) { + if(!$user->isProjectUser($this->getProject())) return false; + if($user->isAdministrator()) return true; + return false; + } // canDelete + + // --------------------------------------------------- + // URL + // --------------------------------------------------- + + function getViewUrl() { + return get_url('time', 'view', array('id' => $this->getId(), 'active_project' => $this->getProjectId())); + } // getViewUrl + + /** + * Return edit time URL + * + * @access public + * @param void + * @return string + */ + function getEditUrl() { + return get_url('time', 'edit', array('id' => $this->getId(), 'active_project' => $this->getProjectId())); + } // getEditUrl + + /** + * Return delete time URL + * + * @access public + * @param void + * @return string + */ + function getDeleteUrl() { + return get_url('time', 'delete', array('id' => $this->getId(), 'active_project' => $this->getProjectId())); + } // getDeleteUrl + + /** + * Return complete time url + * + * @access public + * @param void + * @return string + */ + function getCompleteUrl() { + return get_url('time', 'complete', array('id' => $this->getId(), 'active_project' => $this->getProjectId())); + } // getCompleteUrl + + // --------------------------------------------------- + // System functions + // --------------------------------------------------- + + /** + * Validate before save + * + * @access public + * @param array $errors + * @return boolean + */ + function validate(&$errors) { + if(!$this->validatePresenceOf('name')) $errors[] = lang('time name required'); + #if(!$this->validatePresenceOf('done_date')) $errors[] = lang('time date required'); + #if(!$this->validatePresenceOf('hours')) $errors[] = lang('time hours required'); + } // validate + + /** + * Delete this object and reset all relationship. This function will not delete any of related objec + * + * @access public + * @param void + * @return boolean + */ + function delete() { + + try { + return parent::delete(); + } catch(Exception $e) { + throw $e; + } // try + + } // delete + + // --------------------------------------------------- + // ApplicationDataObject implementation + // --------------------------------------------------- + + /** + * Return object type name + * + * @param void + * @return string + */ + function getObjectTypeName() { + return lang('time'); + } // getObjectTypeName + + /** + * Return object URl + * + * @access public + * @param void + * @return string + */ + function getObjectUrl() { + return $this->getViewUrl(); + } // getObjectUrl + + } // ProjectTime + +?> Index: application/models/project_times/ProjectTimes.class.php =================================================================== --- application/models/project_times/ProjectTimes.class.php (revision 0) +++ application/models/project_times/ProjectTimes.class.php (revision 0) @@ -0,0 +1,49 @@ +getActiveProjects(); + if(!is_array($projects) || !count($projects)) { + return null; + } // if + + $project_ids = array(); + foreach($projects as $project) { + $project_ids[] = $project->getId(); + } // foreach + + return self::findAll(array( + 'conditions' => array('(`assigned_to_user_id` = ? OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?)) AND `project_id` IN (?)', $user->getId(), 0, 0, $project_ids), + 'order' => '`done_date`' + )); // findAll + } // getTimeByUser + + /** + * Return times that are assigned to the specific user and belongs to specific project + * + * @param User $user + * @param Project $project + * @return array + */ + static function getTimeByUserAndProject(User $user, Project $project) { + return self::findAll(array( + 'conditions' => array('(`assigned_to_user_id` = ? OR (`assigned_to_user_id` = ? AND `assigned_to_company_id` = ?)) AND `project_id` = ?', $user->getId(), 0, 0, $project->getId()), + 'order' => '`done_date`' + )); // findAll + } // getTimeByUserAndProject + + } // ProjectTimes + +?> Index: application/models/project_times/base/BaseProjectTime.class.php =================================================================== --- application/models/project_times/base/BaseProjectTime.class.php (revision 0) +++ application/models/project_times/base/BaseProjectTime.class.php (revision 0) @@ -0,0 +1,381 @@ +getColumnValue('id'); + } // getId() + + /** + * Set value of 'id' field + * + * @access public + * @param integer $value + * @return boolean + */ + function setId($value) { + return $this->setColumnValue('id', $value); + } // setId() + + /** + * Return value of 'project_id' field + * + * @access public + * @param void + * @return integer + */ + function getProjectId() { + return $this->getColumnValue('project_id'); + } // getProjectId() + + /** + * Set value of 'project_id' field + * + * @access public + * @param integer $value + * @return boolean + */ + function setProjectId($value) { + return $this->setColumnValue('project_id', $value); + } // setProjectId() + + /** + * Return value of 'name' field + * + * @access public + * @param void + * @return string + */ + function getName() { + return $this->getColumnValue('name'); + } // getName() + + /** + * Set value of 'name' field + * + * @access public + * @param string $value + * @return boolean + */ + function setName($value) { + return $this->setColumnValue('name', $value); + } // setName() + + /** + * Return value of 'hours' field + * + * @access public + * @param void + * @return string + */ + function getHours() { + return $this->getColumnValue('hours'); + } // getHours() + + /** + * Set value of 'hours' field + * + * @access public + * @param string $value + * @return boolean + */ + function setHours($value) { + return $this->setColumnValue('hours', $value); + } // setHours() + + /** + * Return value of 'is_billable' field + * + * @access public + * @param void + * @return string + */ + function getBillable() { + return $this->getColumnValue('is_billable'); + } // getBillable() + + /** + * Set value of 'is_billable' field + * + * @access public + * @param string $value + * @return boolean + */ + function setBillable($value) { + return $this->setColumnValue('is_billable', $value); + } // setBillable() + + /** + * Return value of 'description' field + * + * @access public + * @param void + * @return string + */ + function getDescription() { + return $this->getColumnValue('description'); + } // getDescription() + + /** + * Set value of 'description' field + * + * @access public + * @param string $value + * @return boolean + */ + function setDescription($value) { + return $this->setColumnValue('description', $value); + } // setDescription() + + /** + * Return value of 'due_date' field + * + * @access public + * @param void + * @return DateTimeValue + */ + function getDoneDate() { + return $this->getColumnValue('done_date'); + } // getDoneDate() + + /** + * Set value of 'due_date' field + * + * @access public + * @param DateTimeValue $value + * @return boolean + */ + function setDueDate($value) { + return $this->setColumnValue('due_date', $value); + } // setDueDate() + + /** + * Return value of 'assigned_to_company_id' field + * + * @access public + * @param void + * @return integer + */ + function getAssignedToCompanyId() { + return $this->getColumnValue('assigned_to_company_id'); + } // getAssignedToCompanyId() + + /** + * Set value of 'assigned_to_company_id' field + * + * @access public + * @param integer $value + * @return boolean + */ + function setAssignedToCompanyId($value) { + return $this->setColumnValue('assigned_to_company_id', $value); + } // setAssignedToCompanyId() + + /** + * Return value of 'assigned_to_user_id' field + * + * @access public + * @param void + * @return integer + */ + function getAssignedToUserId() { + return $this->getColumnValue('assigned_to_user_id'); + } // getAssignedToUserId() + + /** + * Set value of 'assigned_to_user_id' field + * + * @access public + * @param integer $value + * @return boolean + */ + function setAssignedToUserId($value) { + return $this->setColumnValue('assigned_to_user_id', $value); + } // setAssignedToUserId() + + /** + * Return value of 'is_private' field + * + * @access public + * @param void + * @return boolean + */ + function getIsPrivate() { + return $this->getColumnValue('is_private'); + } // getIsPrivate() + + /** + * Set value of 'is_private' field + * + * @access public + * @param boolean $value + * @return boolean + */ + function setIsPrivate($value) { + return $this->setColumnValue('is_private', $value); + } // setIsPrivate() + + /** + * Return value of 'completed_on' field + * + * @access public + * @param void + * @return DateTimeValue + */ + function getCompletedOn() { + return $this->getColumnValue('completed_on'); + } // getCompletedOn() + + /** + * Set value of 'completed_on' field + * + * @access public + * @param DateTimeValue $value + * @return boolean + */ + function setCompletedOn($value) { + return $this->setColumnValue('completed_on', $value); + } // setCompletedOn() + + /** + * Return value of 'completed_by_id' field + * + * @access public + * @param void + * @return integer + */ + function getCompletedById() { + return $this->getColumnValue('completed_by_id'); + } // getCompletedById() + + /** + * Set value of 'completed_by_id' field + * + * @access public + * @param integer $value + * @return boolean + */ + function setCompletedById($value) { + return $this->setColumnValue('completed_by_id', $value); + } // setCompletedById() + + /** + * Return value of 'created_on' field + * + * @access public + * @param void + * @return DateTimeValue + */ + function getCreatedOn() { + return $this->getColumnValue('created_on'); + } // getCreatedOn() + + /** + * Set value of 'created_on' field + * + * @access public + * @param DateTimeValue $value + * @return boolean + */ + function setCreatedOn($value) { + return $this->setColumnValue('created_on', $value); + } // setCreatedOn() + + /** + * Return value of 'created_by_id' field + * + * @access public + * @param void + * @return integer + */ + function getCreatedById() { + return $this->getColumnValue('created_by_id'); + } // getCreatedById() + + /** + * Set value of 'created_by_id' field + * + * @access public + * @param integer $value + * @return boolean + */ + function setCreatedById($value) { + return $this->setColumnValue('created_by_id', $value); + } // setCreatedById() + + /** + * Return value of 'updated_on' field + * + * @access public + * @param void + * @return DateTimeValue + */ + function getUpdatedOn() { + return $this->getColumnValue('updated_on'); + } // getUpdatedOn() + + /** + * Set value of 'updated_on' field + * + * @access public + * @param DateTimeValue $value + * @return boolean + */ + function setUpdatedOn($value) { + return $this->setColumnValue('updated_on', $value); + } // setUpdatedOn() + + /** + * Return value of 'updated_by_id' field + * + * @access public + * @param void + * @return integer + */ + function getUpdatedById() { + return $this->getColumnValue('updated_by_id'); + } // getUpdatedById() + + /** + * Set value of 'updated_by_id' field + * + * @access public + * @param integer $value + * @return boolean + */ + function setUpdatedById($value) { + return $this->setColumnValue('updated_by_id', $value); + } // setUpdatedById() + + + /** + * Return manager instance + * + * @access protected + * @param void + * @return ProjectTimes + */ + function manager() { + if(!($this->manager instanceof ProjectTimes)) $this->manager = ProjectTimes::instance(); + return $this->manager; + } // manager + + } // BaseProjectTime + +?> Index: application/models/project_times/base/BaseProjectTimes.class.php =================================================================== --- application/models/project_times/base/BaseProjectTimes.class.php (revision 0) +++ application/models/project_times/base/BaseProjectTimes.class.php (revision 0) @@ -0,0 +1,234 @@ + Column type map + * + * @var array + * @static + */ + static private $columns = array('id' => DATA_TYPE_INTEGER, 'project_id' => DATA_TYPE_INTEGER, 'name' => DATA_TYPE_STRING, 'description' => DATA_TYPE_STRING, 'done_date' => DATA_TYPE_DATETIME, 'hours' => DATA_TYPE_FLOAT, 'is_billable' => DATA_TYPE_BOOLEAN, 'assigned_to_company_id' => DATA_TYPE_INTEGER, 'assigned_to_user_id' => DATA_TYPE_INTEGER, 'is_private' => DATA_TYPE_BOOLEAN, 'created_on' => DATA_TYPE_DATETIME, 'created_by_id' => DATA_TYPE_INTEGER, 'updated_on' => DATA_TYPE_DATETIME, 'updated_by_id' => DATA_TYPE_INTEGER); + + /** + * Construct + * + * @return BaseProjectTimes + */ + function __construct() { + parent::__construct('ProjectTime', 'project_time', true); + } // __construct + + // ------------------------------------------------------- + // Description methods + // ------------------------------------------------------- + + /** + * Return array of object columns + * + * @access public + * @param void + * @return array + */ + function getColumns() { + return array_keys(self::$columns); + } // getColumns + + /** + * Return column type + * + * @access public + * @param string $column_name + * @return string + */ + function getColumnType($column_name) { + if(isset(self::$columns[$column_name])) { + return self::$columns[$column_name]; + } else { + return DATA_TYPE_STRING; + } // if + } // getColumnType + + /** + * Return array of PK columns. If only one column is PK returns its name as string + * + * @access public + * @param void + * @return array or string + */ + function getPkColumns() { + return 'id'; + } // getPkColumns + + /** + * Return name of first auto_incremenent column if it exists + * + * @access public + * @param void + * @return string + */ + function getAutoIncrementColumn() { + return 'id'; + } // getAutoIncrementColumn + + // ------------------------------------------------------- + // Finders + // ------------------------------------------------------- + + /** + * Do a SELECT query over database with specified arguments + * + * @access public + * @param array $arguments Array of query arguments. Fields: + * + * - one - select first row + * - conditions - additional conditions + * - order - order by string + * - offset - limit offset, valid only if limit is present + * - limit + * + * @return one or ProjectTimes objects + * @throws DBQueryError + */ + function find($arguments = null) { + if(isset($this) && instance_of($this, 'ProjectTimes')) { + return parent::find($arguments); + } else { + return ProjectTimes::instance()->find($arguments); + //$instance =& ProjectTimes::instance(); + //return $instance->find($arguments); + } // if + } // find + + /** + * Find all records + * + * @access public + * @param array $arguments + * @return one or ProjectTimes objects + */ + function findAll($arguments = null) { + if(isset($this) && instance_of($this, 'ProjectTimes')) { + return parent::findAll($arguments); + } else { + return ProjectTimes::instance()->findAll($arguments); + //$instance =& ProjectTimes::instance(); + //return $instance->findAll($arguments); + } // if + } // findAll + + /** + * Find one specific record + * + * @access public + * @param array $arguments + * @return ProjectTime + */ + function findOne($arguments = null) { + if(isset($this) && instance_of($this, 'ProjectTimes')) { + return parent::findOne($arguments); + } else { + return ProjectTimes::instance()->findOne($arguments); + //$instance =& ProjectTimes::instance(); + //return $instance->findOne($arguments); + } // if + } // findOne + + /** + * Return object by its PK value + * + * @access public + * @param mixed $id + * @param boolean $force_reload If true cache will be skipped and data will be loaded from database + * @return ProjectTime + */ + function findById($id, $force_reload = false) { + if(isset($this) && instance_of($this, 'ProjectTimes')) { + return parent::findById($id, $force_reload); + } else { + return ProjectTimes::instance()->findById($id, $force_reload); + //$instance =& ProjectTimes::instance(); + //return $instance->findById($id, $force_reload); + } // if + } // findById + + /** + * Return number of rows in this table + * + * @access public + * @param string $conditions Query conditions + * @return integer + */ + function count($condition = null) { + if(isset($this) && instance_of($this, 'ProjectTimes')) { + return parent::count($condition); + } else { + return ProjectTimes::instance()->count($condition); + //$instance =& ProjectTimes::instance(); + //return $instance->count($condition); + } // if + } // count + + /** + * Delete rows that match specific conditions. If $conditions is NULL all rows from table will be deleted + * + * @access public + * @param string $conditions Query conditions + * @return boolean + */ + function delete($condition = null) { + if(isset($this) && instance_of($this, 'ProjectTimes')) { + return parent::delete($condition); + } else { + return ProjectTimes::instance()->delete($condition); + //$instance =& ProjectTimes::instance(); + //return $instance->delete($condition); + } // if + } // delete + + /** + * This function will return paginated result. Result is an array where first element is + * array of returned object and second populated pagination object that can be used for + * obtaining and rendering pagination data using various helpers. + * + * Items and pagination array vars are indexed with 0 for items and 1 for pagination + * because you can't use associative indexing with list() construct + * + * @access public + * @param array $arguments Query argumens (@see find()) Limit and offset are ignored! + * @param integer $items_per_page Number of items per page + * @param integer $current_page Current page number + * @return array + */ + function paginate($arguments = null, $items_per_page = 10, $current_page = 1) { + if(isset($this) && instance_of($this, 'ProjectTimes')) { + return parent::paginate($arguments, $items_per_page, $current_page); + } else { + return ProjectTimes::instance()->paginate($arguments, $items_per_page, $current_page); + //$instance =& ProjectTimes::instance(); + //return $instance->paginate($arguments, $items_per_page, $current_page); + } // if + } // paginate + + /** + * Return manager instance + * + * @return ProjectTimes + */ + function instance() { + static $instance; + if(!instance_of($instance, 'ProjectTimes')) { + $instance = new ProjectTimes(); + } // if + return $instance; + } // instance + + } // ProjectTimes + +?> Index: application/controllers/TimeController.class.php =================================================================== --- application/controllers/TimeController.class.php (revision 0) +++ application/controllers/TimeController.class.php (revision 0) @@ -0,0 +1,229 @@ +addHelper('textile'); + $project = active_project(); + + tpl_assign('times', $project->getTimes()); + + $this->setSidebar(get_template_path('index_sidebar', 'time')); + } // index + + /** + * Show view time page + * + * @access public + * @param void + * @return null + */ + function view() { + $this->addHelper('textile'); + + $time = ProjectTimes::findById(get_id()); + if(!($time instanceof ProjectTime)) { + flash_error(lang('time dnx')); + $this->redirectTo('time', 'index'); + } // if + + if(!$time->canView(logged_user())) { + flash_error(lang('no access permissions')); + $this->redirectToReferer(get_url('time')); + } // if + + tpl_assign('time', $time); + } // view + + /** + * Process add time form + * + * @access public + * @param void + * @return null + */ + function add() { + $this->setTemplate('add_time'); + + if(!ProjectTime::canAdd(logged_user(), active_project())) { + flash_error(lang('no access permissions')); + $this->redirectToReferer(get_url('time')); + } // if + + $time_data = array_var($_POST, 'time'); + if(!is_array($time_data)) { + $user = logged_user(); + $time_data = array( + 'done_date' => DateTimeValueLib::now(), + 'is_billable' => true, + 'is_private' => true, + 'assigned_to' => logged_user()->getCompanyId() . ":" . logged_user()->getId() + ); // array + } // if + $time = new ProjectTime(); + tpl_assign('time_data', $time_data); + tpl_assign('time', $time); + + if(is_array(array_var($_POST, 'time'))) { + $time_data['done_date'] = DateTimeValueLib::make(0, 0, 0, array_var($_POST, 'time_done_date_month', 1), array_var($_POST, 'time_done_date_day', 1), array_var($_POST, 'time_done_date_year', 1970)); + + $assigned_to = explode(':', array_var($time_data, 'assigned_to', '')); + + $time->setFromAttributes($time_data); + if(!logged_user()->isMemberOfOwnerCompany()) $time->setIsPrivate(false); + + $time->setProjectId(active_project()->getId()); + $time->setAssignedToCompanyId(array_var($assigned_to, 0, 0)); + $time->setAssignedToUserId(array_var($assigned_to, 1, 0)); + + try { + DB::beginWork(); + + $time->save(); + ApplicationLogs::createLog($time, active_project(), ApplicationLogs::ACTION_ADD); + + DB::commit(); + + flash_success(lang('success add time', $time->getName())); + $this->redirectTo('time'); + + } catch(Exception $e) { + DB::rollback(); + tpl_assign('error', $e); + } // try + } // if + } // add + + /** + * Show and process edit time form + * + * @access public + * @param void + * @return null + */ + function edit() { + $this->setTemplate('add_time'); + + $time = ProjectTimes::findById(get_id()); + if(!($time instanceof ProjectTime)) { + flash_error(lang('time dnx')); + $this->redirectTo('time', 'index'); + } // if + + if(!$time->canEdit(logged_user())) { + flash_error(lang('no access permissions')); + $this->redirectToReferer(get_url('time')); + } + + $time_data = array_var($_POST, 'time'); + if(!is_array($time_data)) { + $time_data = array( + 'name' => $time->getName(), + 'hours' => $time->getHours(), + 'is_billable' => $time->getBillable(), + 'done_date' => $time->getDoneDate(), + 'description' => $time->getDescription(), + 'assigned_to' => $time->getAssignedToCompanyId() . ':' . $time->getAssignedToUserId(), + 'is_private' => $time->isPrivate(), + ); // array + } // if + + tpl_assign('time_data', $time_data); + tpl_assign('time', $time); + + if(is_array(array_var($_POST, 'time'))) { + $old_owner = $time->getAssignedTo(); // remember the old owner + $time_data['done_date'] = DateTimeValueLib::make(0, 0, 0, array_var($_POST, 'time_done_date_month', 1), array_var($_POST, 'time_done_date_day', 1), array_var($_POST, 'time_done_date_year', 1970)); + + $assigned_to = explode(':', array_var($time_data, 'assigned_to', '')); + + $old_is_private = $time->isPrivate(); + $time->setFromAttributes($time_data); + if(!logged_user()->isMemberOfOwnerCompany()) $time->setIsPrivate($old_is_private); + + $time->setProjectId(active_project()->getId()); + $time->setAssignedToCompanyId(array_var($assigned_to, 0, 0)); + $time->setAssignedToUserId(array_var($assigned_to, 1, 0)); + + try { + DB::beginWork(); + $time->save(); + + ApplicationLogs::createLog($time, active_project(), ApplicationLogs::ACTION_EDIT); + DB::commit(); + + flash_success(lang('success edit time', $time->getName())); + $this->redirectTo('time'); + + } catch(Exception $e) { + DB::rollback(); + tpl_assign('error', $e); + } // try + } // if + } // edit + + /** + * Delete single time + * + * @access public + * @param void + * @return null + */ + function delete() { + $time = ProjectTimes::findById(get_id()); + if(!($time instanceof ProjectTime)) { + flash_error(lang('time dnx')); + $this->redirectTo('time'); + } // if + + if(!$time->canDelete(logged_user())) { + flash_error(lang('no access permissions')); + $this->redirectToReferer(get_url('time')); + } // if + + try { + + DB::beginWork(); + $time->delete(); + ApplicationLogs::createLog($time, $time->getProject(), ApplicationLogs::ACTION_DELETE); + DB::commit(); + + flash_success(lang('success deleted time', $time->getName())); + } catch(Exception $e) { + DB::rollback(); + flash_error(lang('error delete time')); + } // try + + $this->redirectTo('time'); + } // delete + + } // TimeController + +?> \ No newline at end of file Index: application/views/time/view.php =================================================================== --- application/views/time/view.php (revision 0) +++ application/views/time/view.php (revision 0) @@ -0,0 +1,13 @@ +getName()); + project_tabbed_navigation(PROJECT_TAB_TIME); + project_crumbs(array( + array(lang('time'), get_url('time')), + array($time->getName()) + )); + +?> +
+includeTemplate(get_template_path('view_time', 'time')) ?> +
Index: application/views/time/index_sidebar.php =================================================================== --- application/views/time/index_sidebar.php (revision 0) +++ application/views/time/index_sidebar.php (revision 0) @@ -0,0 +1 @@ + Index: application/views/time/add_time.php =================================================================== --- application/views/time/add_time.php (revision 0) +++ application/views/time/add_time.php (revision 0) @@ -0,0 +1,59 @@ +isNew() ? lang('add time') : lang('edit time')); + project_tabbed_navigation(PROJECT_TAB_TIME); + if($time->isNew()) { + project_crumbs(lang('add time')); + } else { + project_crumbs(lang('edit time')); + } + +?> +isNew()) { ?> +
+ + + + + + +
+ + 'long', 'id' => 'timeFormName')) ?> +
+ +
+ + 'short', 'id' => 'timeFormHours')) ?> +
+ +
+ + 'short', 'id' => 'timeFormDesc')) ?> +
+ +
+ + +
+ +isMemberOfOwnerCompany()) { ?> +
+ + +
+
+ +