diff -urN projectpier-0.8.0.3/application/controllers/CommentController.class.php projectpier-0.8.0.3-trackerpatch/application/controllers/CommentController.class.php
--- projectpier-0.8.0.3/application/controllers/CommentController.class.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/controllers/CommentController.class.php Wed Aug 6 22:01:59 2008
@@ -78,8 +78,8 @@
ApplicationLogs::createLog($comment, active_project(), ApplicationLogs::ACTION_ADD);
- // Subscribe user to message (if $object is message)
- if ($object instanceof ProjectMessage) {
+ // Subscribe user to object (if $object is subscribible)
+ if($object->isSubscribible()) {
if (!$object->isSubscriber(logged_user())) {
$object->subscribeUser(logged_user());
} // if
diff -urN projectpier-0.8.0.3/application/controllers/DashboardController.class.php projectpier-0.8.0.3-trackerpatch/application/controllers/DashboardController.class.php
--- projectpier-0.8.0.3/application/controllers/DashboardController.class.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/controllers/DashboardController.class.php Wed Aug 6 22:00:17 2008
@@ -75,6 +75,17 @@
tpl_assign('active_projects', logged_user()->getActiveProjects());
$this->setSidebar(get_template_path('my_tasks_sidebar', 'dashboard'));
} // my_tasks
+
+ /**
+ * Return all tickets assigned to this user
+ *
+ * @param void
+ * @return array
+ */
+ function my_tickets() {
+ tpl_assign('active_projects', logged_user()->getActiveProjects());
+ $this->setSidebar(get_template_path('index_sidebar', 'trac'));
+ } // my_trac
} // DashboardController
diff -urN projectpier-0.8.0.3/application/controllers/FilesController.class.php projectpier-0.8.0.3-trackerpatch/application/controllers/FilesController.class.php
--- projectpier-0.8.0.3/application/controllers/FilesController.class.php Sun Feb 17 15:12:58 2008
+++ projectpier-0.8.0.3-trackerpatch/application/controllers/FilesController.class.php Wed Aug 6 22:00:17 2008
@@ -760,6 +760,7 @@
} // foreach
DB::commit();
+ $object->onAttachFiles($attach_files);
flash_success(lang('success attach files', $counter));
$this->redirectToUrl($object->getObjectUrl());
diff -urN projectpier-0.8.0.3/application/controllers/MessageController.class.php projectpier-0.8.0.3-trackerpatch/application/controllers/MessageController.class.php
--- projectpier-0.8.0.3/application/controllers/MessageController.class.php Fri Feb 15 12:51:56 2008
+++ projectpier-0.8.0.3-trackerpatch/application/controllers/MessageController.class.php Wed Aug 6 22:03:39 2008
@@ -385,9 +385,9 @@
} // if
if ($message->subscribeUser(logged_user())) {
- flash_success('success subscribe to message');
+ flash_success(lang('success subscribe to message'));
} else {
- flash_error('error subscribe to message');
+ flash_error(lang('error subscribe to message'));
} // if
$this->redirectToUrl($message->getViewUrl());
} // subscribe
@@ -411,9 +411,9 @@
} // if
if ($message->unsubscribeUser(logged_user())) {
- flash_success('success unsubscribe to message');
+ flash_success(lang('success unsubscribe to message'));
} else {
- flash_error('error unsubscribe to message');
+ flash_error(lang('error unsubscribe to message'));
} // if
$this->redirectToUrl($message->getViewUrl());
} // unsubscribe
diff -urN projectpier-0.8.0.3/application/controllers/TracController.class.php projectpier-0.8.0.3-trackerpatch/application/controllers/TracController.class.php
--- projectpier-0.8.0.3/application/controllers/TracController.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/controllers/TracController.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,686 @@
+getId());
+
+ list($categories, $pagination) = Categories::paginate(
+ array(
+ 'conditions' => $conditions,
+ 'order' => '`name`'
+ ),
+ config_option('categories_per_page', 25),
+ $page
+ ); // paginate
+
+ tpl_assign('categories', $categories);
+ tpl_assign('categories_pagination', $pagination);
+
+ $this->setSidebar(get_template_path('trac_sidebar', 'trac'));
+ } // categories
+
+ /**
+ * Return project tickets
+ *
+ * @access public
+ * @param void
+ * @return array
+ */
+ function index() {
+ $page = (integer) array_var($_GET, 'page', 1);
+ if($page < 0) $page = 1;
+
+ $closed = (boolean) array_var($_GET, 'closed', false);
+ $conditions = DB::prepareString('`closed_on` '.($closed ? '>' : '=').' ? and `project_id` = ?', array(EMPTY_DATETIME, active_project()->getId()));
+ if(!logged_user()->isMemberOfOwnerCompany()) {
+ $conditions .= DB::prepareString(' AND `is_private` = ?', array(0));
+ } // if
+
+ if ($closed) {
+ $order = '`closed_on` DESC';
+ } else {
+ $order = '`created_on` DESC';
+ } // if
+
+ list($tickets, $pagination) = ProjectTickets::paginate(
+ array(
+ 'conditions' => $conditions,
+ 'order' => $order
+ ),
+ config_option('tickets_per_page', 25),
+ $page
+ ); // paginate
+
+ tpl_assign('closed', $closed);
+ tpl_assign('tickets', $tickets);
+ tpl_assign('tickets_pagination', $pagination);
+
+ $this->setSidebar(get_template_path('index_sidebar', 'trac'));
+ } // index
+
+ /**
+ * Add ticket
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function add() {
+ $this->addHelper('ticket');
+
+ if(!ProjectTicket::canAdd(logged_user(), active_project())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectToReferer(get_url('trac'));
+ } // if
+
+ $ticket = new ProjectTicket();
+ $ticket->setProjectId(active_project()->getId());
+ $ticket_data = array_var($_POST, 'ticket');
+
+ tpl_assign('ticket', $ticket);
+ tpl_assign('ticket_data', $ticket_data);
+
+ if(is_array(array_var($_POST, 'ticket'))) {
+ try {
+ $uploaded_files = ProjectFiles::handleHelperUploads(active_project());
+ } catch(Exception $e) {
+ $uploaded_files = null;
+ } // try
+
+ try {
+ $ticket->setFromAttributes($ticket_data);
+
+ $assigned_to = explode(':', array_var($ticket_data, 'assigned_to', ''));
+ $ticket->setAssignedToCompanyId(array_var($assigned_to, 0, 0));
+ $ticket->setAssignedToUserId(array_var($assigned_to, 1, 0));
+
+ // Options are reserved only for members of owner company
+ if(!logged_user()->isMemberOfOwnerCompany()) {
+ $ticket->setIsPrivate(false);
+ } // if
+
+ DB::beginWork();
+ $ticket->save();
+
+ if(is_array($uploaded_files)) {
+ foreach($uploaded_files as $uploaded_file) {
+ $ticket->attachFile($uploaded_file);
+ $uploaded_file->setIsPrivate($ticket->isPrivate());
+ $uploaded_file->setIsVisible(true);
+ $uploaded_file->setExpirationTime(EMPTY_DATETIME);
+ $uploaded_file->save();
+ } // if
+ } // if
+
+ ApplicationLogs::createLog($ticket, active_project(), ApplicationLogs::ACTION_ADD);
+ DB::commit();
+
+ // Try to send notifications but don't break submission in case of an error
+ try {
+ if ($ticket->getAssignedToUserId()) {
+ $ticket_data['notify_user_' . $ticket->getAssignedToUserId()] = 'checked';
+ }
+
+ $notify_people = array();
+ $project_companies = active_project()->getCompanies();
+ foreach($project_companies as $project_company) {
+ $company_users = $project_company->getUsersOnProject(active_project());
+ if(is_array($company_users)) {
+ foreach($company_users as $company_user) {
+ if((array_var($ticket_data, 'notify_company_' . $project_company->getId()) == 'checked') || (array_var($ticket_data, 'notify_user_' . $company_user->getId()))) {
+ $ticket->subscribeUser($company_user); // subscribe
+ $notify_people[] = $company_user;
+ } // if
+ } // if
+ } // if
+ } // if
+
+ Notifier::ticket($ticket, $notify_people, 'new_ticket', $ticket->getCreatedBy());
+ } catch(Exception $e) {
+
+ } // try
+
+ flash_success(lang('success add ticket', $ticket->getSummary()));
+ $this->redirectTo('trac');
+
+ // Error...
+ } catch(Exception $e) {
+ DB::rollback();
+
+ if(is_array($uploaded_files)) {
+ foreach($uploaded_files as $uploaded_file) {
+ $uploaded_file->delete();
+ } // foreach
+ } // if
+
+ $ticket->setNew(true);
+ tpl_assign('error', $e);
+ } // try
+
+ } // if
+ } // add
+
+ /**
+ * Edit specific ticket
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function edit() {
+ $this->addHelper('textile');
+ $this->addHelper('ticket');
+
+ $ticket = ProjectTickets::findById(get_id());
+ if(!($ticket instanceof ProjectTicket)) {
+ flash_error(lang('ticket dnx'));
+ $this->redirectTo('trac');
+ } // if
+
+ if(!$ticket->canView(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectToReferer(get_url('trac'));
+ } // if
+
+ $ticket_data = array_var($_POST, 'ticket');
+ if(!is_array($ticket_data)) {
+ $ticket_data = array(
+ 'is_private' => $ticket->isPrivate(),
+ 'summary' => $ticket->getSummary(),
+ 'priority' => $ticket->getPriority(),
+ 'type' => $ticket->getType(),
+ 'category_id' => $ticket->getCategoryId(),
+ 'assigned_to' => $ticket->getAssignedToCompanyId() . ':' . $ticket->getAssignedToUserId()
+ ); // array
+ } // if
+
+ tpl_assign('ticket', $ticket);
+ tpl_assign('ticket_data', $ticket_data);
+ tpl_assign('subscribers', $ticket->getSubscribers());
+ tpl_assign('changes', $ticket->getChanges());
+
+ $this->setSidebar(get_template_path('edit_sidebar', 'trac'));
+
+ if(is_array(array_var($_POST, 'ticket'))) {
+ if(!$ticket->canEdit(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectTo('trac');
+ } else {
+ $old_fields = array(
+ 'summary' => $ticket->getSummary(),
+ 'priority' => $ticket->getPriority(),
+ 'type' => $ticket->getType(),
+ 'category' => $ticket->getCategory(),
+ 'assigned to' => $ticket->getAssignedTo()
+ );
+ $old_private = $ticket->isPrivate();
+
+ try {
+ $ticket->setFromAttributes($ticket_data);
+ $ticket->setUpdated('settings');
+
+ // Options are reserved only for members of owner company
+ if(!logged_user()->isMemberOfOwnerCompany()) {
+ $ticket->setIsPrivate($old_private);
+ } // if
+
+ $old_assigned_user_id = $ticket->getAssignedToUserId();
+ $assigned_to = explode(':', array_var($ticket_data, 'assigned_to', ''));
+ $ticket->setAssignedToCompanyId(array_var($assigned_to, 0, 0));
+ $ticket->setAssignedToUserId(array_var($assigned_to, 1, 0));
+
+ DB::beginWork();
+ $ticket->save();
+
+ ApplicationLogs::createLog($ticket, $ticket->getProject(), ApplicationLogs::ACTION_EDIT);
+ DB::commit();
+
+ $user = $ticket->getAssignedToUser();
+ if ($user instanceof User && $user->getId() != $old_assigned_user_id) {
+ if(!$ticket->isSubscriber($user)) {
+ $ticket->subscribeUser($user);
+ } // if
+ } // if
+
+ $new_fields = array(
+ 'summary' => $ticket->getSummary(),
+ 'priority' => $ticket->getPriority(),
+ 'type' => $ticket->getType(),
+ 'category' => $ticket->getCategory(),
+ 'assigned to' => $ticket->getAssignedTo()
+ );
+
+ foreach ($old_fields as $type => $old_field) {
+ $new_field = $new_fields[$type];
+ if ($old_field === $new_field) {
+ continue;
+ }
+ $from_data = ($old_field instanceof ApplicationDataObject) ? $old_field->getObjectName() : $old_field;
+ $to_data = ($new_field instanceof ApplicationDataObject) ? $new_field->getObjectName() : $new_field;
+
+ $change = new TicketChange();
+ $change->setTicketId($ticket->getId());
+ $change->setType($type);
+ $change->setFromData($from_data);
+ $change->setToData($to_data);
+ $change->save();
+ } // foreach
+
+ try {
+ Notifier::ticket($ticket, $ticket->getSubscribers(), 'edit_ticket', $ticket->getUpdatedBy());
+ } catch(Exception $e) {
+ // nothing here, just suppress error...
+ } // try
+
+ flash_success(lang('success edit ticket', $ticket->getSummary()));
+ $this->redirectToUrl($ticket->getViewUrl());
+
+ } catch(Exception $e) {
+ DB::rollback();
+ tpl_assign('error', $e);
+ } // try
+ } // if
+ } // if
+ } // edit
+
+ /**
+ * Update message options. This is execute only function and if we don't have
+ * options in post it will redirect back to the message
+ *
+ * @param void
+ * @return null
+ */
+ function update_options() {
+ $ticket = ProjectTickets::findById(get_id());
+ if(!($ticket instanceof ProjectTicket)) {
+ flash_error(lang('ticket dnx'));
+ $this->redirectTo('trac');
+ } // if
+
+ if(!$ticket->canUpdateOptions(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectToReferer(get_url('trac'));
+ } // if
+
+ $ticket_data = array_var($_POST, 'ticket');
+ if(is_array(array_var($_POST, 'ticket'))) {
+ try {
+ $old_private = $ticket->isPrivate();
+ $ticket->setIsPrivate((boolean) array_var($ticket_data, 'is_private', $ticket->isPrivate()));
+
+ DB::beginWork();
+ $ticket->save();
+ ApplicationLogs::createLog($ticket, $ticket->getProject(), ApplicationLogs::ACTION_EDIT);
+ DB::commit();
+
+ if ($old_private != $ticket->isPrivate()) {
+ $change = new TicketChange();
+ $change->setTicketId($ticket->getId());
+ $change->setType('private');
+ $change->setFromData($old_private ? 'yes' : 'no');
+ $change->setToData($ticket->isPrivate() ? 'yes' : 'no');
+ $change->save();
+ }
+
+ flash_success(lang('success edit ticket', $ticket->getSummary()));
+ } catch(Exception $e) {
+ flash_error(lang('error update ticket options'), $ticket->getSummary());
+ } // try
+ } // if
+ $this->redirectToUrl($ticket->getViewUrl());
+ } // update_options
+
+ /**
+ * Close specific ticket
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function close() {
+ $ticket = ProjectTickets::findById(get_id());
+ if(!($ticket instanceof ProjectTicket)) {
+ flash_error(lang('ticket dnx'));
+ $this->redirectTo('trac');
+ } // if
+
+ if(!$ticket->canChangeStatus(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectToReferer(get_url('trac'));
+ } // if
+
+ $status = $ticket->isClosed() ? 'closed' : 'open';
+
+ try {
+ DB::beginWork();
+ $ticket->closeTicket();
+ ApplicationLogs::createLog($ticket, active_project(), ApplicationLogs::ACTION_CLOSE);
+ DB::commit();
+
+ if ($status != 'closed') {
+ $change = new TicketChange();
+ $change->setTicketId($ticket->getId());
+ $change->setType('status');
+ $change->setFromData($status);
+ $change->setToData('closed');
+ $change->save();
+ }
+
+ try {
+ Notifier::ticket($ticket, $ticket->getSubscribers(), 'close_ticket', $ticket->getClosedBy());
+ } catch(Exception $e) {
+ // nothing here, just suppress error...
+ } // try
+
+ flash_success(lang('success close ticket'));
+ } catch(Exception $e) {
+ flash_error(lang('error close ticket'));
+ DB::rollback();
+ } // try
+
+ $this->redirectToUrl(ProjectTickets::getIndexUrl(true));
+ } // close
+
+ /**
+ * Open specific ticket
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function open() {
+ $ticket = ProjectTickets::findById(get_id());
+ if(!($ticket instanceof ProjectTicket)) {
+ flash_error(lang('ticket dnx'));
+ $this->redirectTo('trac');
+ } // if
+
+ if(!$ticket->canChangeStatus(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectToReferer(get_url('trac'));
+ } // if
+
+ $status = $ticket->isClosed() ? 'closed' : 'open';
+
+ try {
+ DB::beginWork();
+ $ticket->openTicket();
+ ApplicationLogs::createLog($ticket, active_project(), ApplicationLogs::ACTION_OPEN);
+ DB::commit();
+
+ if ($status != 'open') {
+ $change = new TicketChange();
+ $change->setTicketId($ticket->getId());
+ $change->setType('status');
+ $change->setFromData($status);
+ $change->setToData('open');
+ $change->save();
+ }
+
+ try {
+ Notifier::ticket($ticket, $ticket->getSubscribers(), 'open_ticket', logged_user());
+ } catch(Exception $e) {
+ // nothing here, just suppress error...
+ } // try
+
+ flash_success(lang('success open ticket'));
+ } catch(Exception $e) {
+ flash_error(lang('error open ticket'));
+ DB::rollback();
+ } // try
+
+ $this->redirectToUrl(ProjectTickets::getIndexUrl());
+ } // open
+
+ /**
+ * Delete specific ticket
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function delete() {
+ $ticket = ProjectTickets::findById(get_id());
+ if(!($ticket instanceof ProjectTicket)) {
+ flash_error(lang('ticket dnx'));
+ $this->redirectTo('trac');
+ } // if
+
+ if(!$ticket->canDelete(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectTo('trac');
+ } // if
+
+ try {
+
+ DB::beginWork();
+ $ticket->delete();
+ ApplicationLogs::createLog($ticket, $ticket->getProject(), ApplicationLogs::ACTION_DELETE);
+ DB::commit();
+
+ flash_success(lang('success deleted ticket', $ticket->getSummary()));
+ } catch(Exception $e) {
+ DB::rollback();
+ flash_error(lang('error delete ticket'));
+ } // try
+
+ $this->redirectTo('trac');
+ } // delete
+
+ /**
+ * Add a new category
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function add_category() {
+ if(!Category::canAdd(logged_user(), active_project())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectToReferer(get_url('trac', 'categories'));
+ } // if
+
+ $category = new Category();
+ $category_data = array_var($_POST, 'category');
+
+ tpl_assign('category', $category);
+ tpl_assign('category_data', $category_data);
+
+ if(is_array(array_var($_POST, 'category'))) {
+ try {
+ $category->setFromAttributes($category_data);
+ $category->setProjectId(active_project()->getId());
+
+ DB::beginWork();
+ $category->save();
+
+ ApplicationLogs::createLog($category, active_project(), ApplicationLogs::ACTION_ADD);
+ DB::commit();
+
+ flash_success(lang('success add category', $category->getName()));
+ $this->redirectTo('trac', 'categories');
+
+ // Error...
+ } catch(Exception $e) {
+ DB::rollback();
+
+ $category->setNew(true);
+ tpl_assign('error', $e);
+ } // try
+
+ } // if
+ } // add_category
+
+ /**
+ * Edit specific category
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function edit_category() {
+ $this->setTemplate('add_category');
+
+ $category = Categories::findById(get_id());
+ if(!($category instanceof Category)) {
+ flash_error(lang('category dnx'));
+ $this->redirectTo('trac', 'categories');
+ } // if
+
+ if(!$category->canView(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectToReferer(get_url('trac', 'categories'));
+ } // if
+
+ $category_data = array_var($_POST, 'category');
+ if(!is_array($category_data)) {
+ $category_data = array(
+ 'name' => $category->getName(),
+ 'description' => $category->getDescription()
+ ); // array
+ } // if
+
+ tpl_assign('category', $category);
+ tpl_assign('category_data', $category_data);
+
+ if(is_array(array_var($_POST, 'category'))) {
+ if(!$category->canEdit(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectTo('trac', 'categories');
+ } else {
+ try {
+ $category->setFromAttributes($category_data);
+
+ DB::beginWork();
+ $category->save();
+
+ ApplicationLogs::createLog($category, $category->getProject(), ApplicationLogs::ACTION_EDIT);
+ DB::commit();
+
+ flash_success(lang('success edit category', $category->getName()));
+ $this->redirectToUrl($category->getViewUrl());
+
+ } catch(Exception $e) {
+ DB::rollback();
+ tpl_assign('error', $e);
+ } // try
+ } // if
+ } // if
+ } // edit_category
+
+ /**
+ * Delete specific category
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function delete_category() {
+ $category = Categories::findById(get_id());
+ if(!($category instanceof Category)) {
+ flash_error(lang('category dnx'));
+ $this->redirectTo('trac', 'categories');
+ } // if
+
+ if(!$category->canDelete(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectToReferer(get_url('trac', 'categories'));
+ } // if
+
+ try {
+
+ DB::beginWork();
+ $category->delete();
+ ApplicationLogs::createLog($category, $category->getProject(), ApplicationLogs::ACTION_DELETE);
+ DB::commit();
+
+ flash_success(lang('success deleted category', $category->getName()));
+ } catch(Exception $e) {
+ DB::rollback();
+ flash_error(lang('error delete category'));
+ } // try
+
+ $this->redirectTo('trac', 'categories');
+ } // delete
+
+ // ---------------------------------------------------
+ // Subscriptions
+ // ---------------------------------------------------
+
+ /**
+ * Subscribe to ticket
+ *
+ * @param void
+ * @return null
+ */
+ function subscribe() {
+ $ticket = ProjectTickets::findById(get_id());
+ if(!($ticket instanceof ProjectTicket)) {
+ flash_error(lang('ticket dnx'));
+ $this->redirectTo('trac');
+ } // if
+
+ if(!$ticket->canView(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectTo('trac');
+ } // if
+
+ if($ticket->subscribeUser(logged_user())) {
+ flash_success(lang('success subscribe to ticket'));
+ } else {
+ flash_error(lang('error subscribe to ticket'));
+ } // if
+ $this->redirectToUrl($ticket->getViewUrl());
+ } // subscribe
+
+ /**
+ * Unsubscribe from message
+ *
+ * @param void
+ * @return null
+ */
+ function unsubscribe() {
+ $ticket = ProjectTickets::findById(get_id());
+ if(!($ticket instanceof ProjectTicket)) {
+ flash_error(lang('ticket dnx'));
+ $this->redirectTo('trac');
+ } // if
+
+ if(!$ticket->canView(logged_user())) {
+ flash_error(lang('no access permissions'));
+ $this->redirectTo('trac');
+ } // if
+
+ if($ticket->unsubscribeUser(logged_user())) {
+ flash_success(lang('success unsubscribe to ticket'));
+ } else {
+ flash_error(lang('error unsubscribe to ticket'));
+ } // if
+ $this->redirectToUrl($ticket->getViewUrl());
+ } // unsubscribe
+
+ } // TracController
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/helpers/company_website.php projectpier-0.8.0.3-trackerpatch/application/helpers/company_website.php
--- projectpier-0.8.0.3/application/helpers/company_website.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/helpers/company_website.php Wed Aug 6 22:00:17 2008
@@ -26,6 +26,7 @@
define('DASHBOARD_TAB_OVERVIEW', 'overview');
define('DASHBOARD_TAB_MY_PROJECTS', 'my_projects');
define('DASHBOARD_TAB_MY_TASKS', 'my_task');
+ define('DASHBOARD_TAB_MY_TICKETS', 'my_tickets');
/**
* Prepare dashboard tabbed navigation
@@ -49,6 +50,11 @@
DASHBOARD_TAB_MY_TASKS,
lang('my tasks'),
get_url('dashboard', 'my_tasks')
+ ));
+ add_tabbed_navigation_item(new TabbedNavigationItem(
+ DASHBOARD_TAB_MY_TICKETS,
+ lang('my tickets'),
+ get_url('dashboard', 'my_tickets')
));
tabbed_navigation_set_selected($selected);
diff -urN projectpier-0.8.0.3/application/helpers/page.php projectpier-0.8.0.3-trackerpatch/application/helpers/page.php
--- projectpier-0.8.0.3/application/helpers/page.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/helpers/page.php Wed Aug 6 22:04:53 2008
@@ -525,11 +525,10 @@
$href = get_stylesheet_url($href);
}
$page = PageDescription::instance();
- $page->addRelLink($href, 'Stylesheet', array(
- 'type' => 'text/css',
- 'title' => $title,
- 'media' => $media
- )); // addRelLink
+ $attributes = array('type' => 'text/css');
+ if ($title) $attributes['title'] = $title;
+ if ($media) $attributes['media'] = $media;
+ $page->addRelLink($href, 'Stylesheet', $attributes); // addRelLink
} // add_stylesheet_to_page
/**
diff -urN projectpier-0.8.0.3/application/helpers/project_website.php projectpier-0.8.0.3-trackerpatch/application/helpers/project_website.php
--- projectpier-0.8.0.3/application/helpers/project_website.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/helpers/project_website.php Wed Aug 6 22:00:17 2008
@@ -17,12 +17,13 @@
}
BreadCrumbs::instance()->addByFunctionArguments($args);
- } // dashboard_crumbs
+ } // project_crumbs
// Tab IDs
define('PROJECT_TAB_OVERVIEW', 'overview');
define('PROJECT_TAB_MESSAGES', 'messages');
define('PROJECT_TAB_TASKS', 'tasks');
+ define('PROJECT_TAB_TICKETS', 'tickets');
define('PROJECT_TAB_MILESTONES', 'milestones');
define('PROJECT_TAB_FILES', 'files');
define('PROJECT_TAB_TAGS', 'tags');
@@ -52,6 +53,11 @@
get_url('task')
));
add_tabbed_navigation_item(new TabbedNavigationItem(
+ PROJECT_TAB_TICKETS,
+ lang('tickets'),
+ get_url('trac')
+ ));
+ add_tabbed_navigation_item(new TabbedNavigationItem(
PROJECT_TAB_MILESTONES,
lang('milestones'),
get_url('milestone')
@@ -79,6 +85,6 @@
get_url('project', 'people')
));
tabbed_navigation_set_selected($selected);
- } // dashboard_tabbed_navigation
+ } // project_tabbed_navigation
?>
diff -urN projectpier-0.8.0.3/application/helpers/ticket.php projectpier-0.8.0.3-trackerpatch/application/helpers/ticket.php
--- projectpier-0.8.0.3/application/helpers/ticket.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/helpers/ticket.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,67 @@
+ 'selected') : null;
+ $options[] = option_tag(lang($type), $type, $option_attributes);
+ } // foreach
+ return select_box($name, $options, $attributes);
+ } // select_ticket_type
+
+ /**
+ * Render select ticket priority
+ *
+ * @param string $selected priority of ticket
+ * @param array $attributes Additional attributes
+ * @return string
+ */
+ function select_ticket_priority($name, $selected = null, $attributes = null) {
+ if ($selected == null) $selected = 'minor';
+ $types = array('critical', 'major', 'minor', 'trivial');
+ $options = array();
+ foreach($types as $type) {
+ $option_attributes = $type == $selected ? array('selected' => 'selected') : null;
+ $options[] = option_tag(lang($type), $type, $option_attributes);
+ } // foreach
+ return select_box($name, $options, $attributes);
+ } // select_ticket_priority
+
+ /**
+ * Render select ticket priority
+ *
+ * @param Project $project ticket's project to get the categories
+ * @param int $selected category id of ticket
+ * @param array $attributes Additional attributes
+ * @return string
+ */
+ function select_ticket_category($name, $project, $selected = null, $attributes = null) {
+ $categories = $project->getCategories();
+ $option_attributes = $selected ? null: array('selected' => 'selected');
+ $options = array(option_tag(lang('none'), 0, $option_attributes));
+ if ($categories && count($categories)) {
+ foreach($categories as $category) {
+ $option_attributes = $category->getId() == $selected ? array('selected' => 'selected') : null;
+ $options[] = option_tag($category->getName(), $category->getId(), $option_attributes);
+ } // foreach
+ } // if
+ return select_box($name, $options, $attributes);
+ } // select_ticket_priority
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/ProjectDataObject.class.php projectpier-0.8.0.3-trackerpatch/application/models/ProjectDataObject.class.php
--- projectpier-0.8.0.3/application/models/ProjectDataObject.class.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/models/ProjectDataObject.class.php Wed Aug 6 22:00:17 2008
@@ -114,6 +114,17 @@
*/
protected $attached_files;
+ // ---------------------------------------------------
+ // Subscribers
+ // ---------------------------------------------------
+
+ /**
+ * Mark this object as subscribible
+ *
+ * @var boolean
+ */
+ protected $is_subscribible = false;
+
/**
* Return owner project. If project_id field does not exists NULL is returned
*
@@ -700,6 +711,30 @@
'active_project' => $this->getProject()->getId()
)); // get_url
} // getDetachFileUrl
+
+ /**
+ * This event is triggered when we attach new files
+ *
+ * @param array $files
+ * @return boolean
+ */
+ function onAttachFiles($files) {
+ return true;
+ } // onAttachFiles
+
+ // ---------------------------------------------------
+ // Subscribible
+ // ---------------------------------------------------
+
+ /**
+ * Returns true if users can subscribe to this object
+ *
+ * @param void
+ * @return boolean
+ */
+ function isSubscribible() {
+ return (boolean) $this->is_subscribible;
+ } // isSubscribible
// ---------------------------------------------------
// System
diff -urN projectpier-0.8.0.3/application/models/notifier/Notifier.class.php projectpier-0.8.0.3-trackerpatch/application/models/notifier/Notifier.class.php
--- projectpier-0.8.0.3/application/models/notifier/Notifier.class.php Sun Feb 24 17:29:56 2008
+++ projectpier-0.8.0.3-trackerpatch/application/models/notifier/Notifier.class.php Wed Aug 6 22:12:21 2008
@@ -95,6 +95,82 @@
tpl_fetch(get_template_path('new_message', 'notifier'))
); // send
} // newMessage
+
+ /**
+ * Send ticket notification to the list of users ($people)
+ *
+ * @param ProjectTicket $ticket New ticket
+ * @param array $people
+ * @param string $template template to send notification
+ * @param User $user user who send the notification
+ * @return boolean
+ * @throws NotifierConnectionError
+ */
+ static function ticket(ProjectTicket $ticket, $people, $template, $user) {
+ if(!is_array($people) || !count($people)) {
+ return; // nothing here...
+ } // if
+
+ $recepients = array();
+ foreach($people as $subscriber) {
+ if($subscriber->getId() == $user->getId()) {
+ continue; // skip comment author
+ } // if
+
+ $recepients[] = self::prepareEmailAddress($subscriber->getEmail(), $subscriber->getDisplayName());
+ } // foreach
+
+ if(!count($recepients)) {
+ return true; // no recepients
+ } // if
+
+ tpl_assign('ticket', $ticket);
+
+ return self::sendEmail(
+ $recepients,
+ self::prepareEmailAddress($user->getEmail(), $user->getDisplayName()),
+ $ticket->getProject()->getName() . ' - ' . $ticket->getSummary(),
+ tpl_fetch(get_template_path($template, 'notifier'))
+ ); // send
+ } // ticket
+
+ /**
+ * Send some files attached to ticket notification to ticket subscribers
+ *
+ * @param ProjectTicket $ticket
+ * @param array $attached_files Files attached to ticket
+ * @return boolean
+ * @throws NotifierConnectionError
+ */
+ static function attachFilesToTicket(ProjectTicket $ticket, $attached_files) {
+ $all_subscribers = $ticket->getSubscribers();
+ if(!is_array($all_subscribers)) {
+ return true; // no subscribers
+ } // if
+
+ $recepients = array();
+ foreach($all_subscribers as $subscriber) {
+ if($subscriber->getId() == $ticket->getUpdatedById()) {
+ continue; // skip comment author
+ } // if
+
+ $recepients[] = self::prepareEmailAddress($subscriber->getEmail(), $subscriber->getDisplayName());
+ } // foreach
+
+ if(!count($recepients)) {
+ return true; // no recepients
+ } // if
+
+ tpl_assign('ticket', $ticket);
+ tpl_assign('attached_files', $attached_files);
+
+ return self::sendEmail(
+ $recepients,
+ self::prepareEmailAddress($ticket->getUpdatedBy()->getEmail(), $ticket->getUpdatedBy()->getDisplayName()),
+ $ticket->getProject()->getName() . ' - ' . $ticket->getSummary(),
+ tpl_fetch(get_template_path('attach_files_ticket', 'notifier'))
+ ); // send
+ } // attachFilesToTicket
/**
* Send new comment notification to message subscriber
@@ -109,7 +185,36 @@
throw new Error('Invalid comment object');
} // if
- $all_subscribers = $message->getSubscribers();
+ return self::newComment($comment, $message->getSubscribers());
+ } // newMessageComment
+
+ /**
+ * Send new comment notification to ticket subscriber
+ *
+ * @param TicketComment $comment
+ * @return boolean
+ * @throws NotifierConnectionError
+ */
+ static function newTicketComment(Comment $comment) {
+ $ticket = $comment->getObject();
+ if(!($ticket instanceof ProjectTicket)) {
+ throw new Error('Invalid comment object');
+ } // if
+
+ return self::newComment($comment, $ticket->getSubscribers());
+ } // newTicketComment
+
+ /**
+ * Send new comment notification to subscribers
+ *
+ * @access private
+ * @param Comment $comment
+ * @param string $title title of object for subject
+ * @param array $all_subscribers subscribers
+ * @return boolean
+ * @throws NotifierConnectionError
+ */
+ static function newComment(Comment $comment, $all_subscribers) {
if (!is_array($all_subscribers)) {
return true; // no subscribers
} // if
@@ -138,10 +243,10 @@
return self::sendEmail(
$recipients,
self::prepareEmailAddress($comment->getCreatedBy()->getEmail(), $comment->getCreatedByDisplayName()),
- $comment->getProject()->getName() . ' - ' . $message->getTitle(),
+ $comment->getProject()->getName() . ' - ' . $comment->getObject()->getTitle(),
tpl_fetch(get_template_path('new_comment', 'notifier'))
); // send
- } // newMessageComment
+ } // newComment
// ---------------------------------------------------
// Milestone
diff -urN projectpier-0.8.0.3/application/models/project_categories/Categories.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_categories/Categories.class.php
--- projectpier-0.8.0.3/application/models/project_categories/Categories.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_categories/Categories.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,27 @@
+ array('`project_id` = ?', $project->getId()),
+ 'order' => '`name`',
+ )); // findAll
+ } // getProjectCategories
+
+ } // Categories
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/project_categories/Category.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_categories/Category.class.php
--- projectpier-0.8.0.3/application/models/project_categories/Category.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_categories/Category.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,186 @@
+getProjectId());
+ } // getProject
+
+ /**
+ * Return shortened description
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getShortDescription() {
+ $return = substr_utf($this->getDescription(), 0, 50);
+ return strlen_utf($this->getDescription()) > 50 ? $return . '...' : $return;
+ } // getShortDescription
+
+ // ---------------------------------------------------
+ // Permissions
+ // ---------------------------------------------------
+
+ /**
+ * Return true if $user can view this category
+ *
+ * @param User $user
+ * @return boolean
+ */
+ function canView(User $user) {
+ if(!$user->isProjectUser($this->getProject())) {
+ return false; // user have access to project
+ } // if
+ return true;
+ } // canView
+
+ /**
+ * Check if user can add categories in specific project
+ *
+ * @param User $user
+ * @param Project $project
+ * @return boolean
+ */
+ function canAdd(User $user, Project $project) {
+ if(!$user->isProjectUser($project)) {
+ return false; // user is on project
+ } // if
+ if($user->isAdministrator()) {
+ return true; // user is administrator or root
+ } // if
+ return $user->getProjectPermission($project, ProjectUsers::CAN_MANAGE_TICKETS);
+ } // canAdd
+
+ /**
+ * Check if specific user can update this category
+ *
+ * @param User $user
+ * @return boolean
+ */
+ function canEdit(User $user) {
+ if(!$user->isProjectUser($this->getProject())) {
+ return false; // user is on project
+ } // if
+ if($user->isAdministrator()) {
+ return true; // user is administrator or root
+ } // if
+ return $user->getProjectPermission($this->getProject(), ProjectUsers::CAN_MANAGE_TICKETS);
+ } // canEdit
+
+ /**
+ * Check if specific user can delete this
+ *
+ * @param User $user
+ * @return boolean
+ */
+ function canDelete(User $user) {
+ if(!$user->isProjectUser($this->getProject())) {
+ return false; // user is on project
+ } // if
+ if($user->isAdministrator()) {
+ return true; // user is administrator or root
+ } // if
+ return $user->getProjectPermission($this->getProject(), ProjectUsers::CAN_MANAGE_TICKETS);
+ } // canDelete
+
+ // ---------------------------------------------------
+ // URLs
+ // ---------------------------------------------------
+
+ /**
+ * Return tag URL
+ *
+ * @param void
+ * @return string
+ */
+ function getViewUrl() {
+ return $this->getEditUrl();
+ } // getViewUrl
+
+ /**
+ * Return edit URL
+ *
+ * @param void
+ * @return string
+ */
+ function getEditUrl() {
+ return get_url('trac', 'edit_category', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
+ } // getEditUrl
+
+ /**
+ * Return delete URL
+ *
+ * @param void
+ * @return string
+ */
+ function getDeleteUrl() {
+ return get_url('trac', 'delete_category', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
+ } // getDeleteUrl
+
+ // ---------------------------------------------------
+ // System
+ // ---------------------------------------------------
+
+ /**
+ * Validate before save
+ *
+ * @param array $error
+ * @return null
+ */
+ function validate(&$errors) {
+ if(!$this->validatePresenceOf('name')) {
+ $errors[] = lang('category name required');
+ } // if
+ } // validate
+
+ // ---------------------------------------------------
+ // ApplicationDataObject implementation
+ // ---------------------------------------------------
+
+ /**
+ * Return object name
+ *
+ * @param void
+ * @return string
+ */
+ function getObjectName() {
+ return $this->getName();
+ } // getObjectName
+
+ /**
+ * Return object type name
+ *
+ * @param void
+ * @return string
+ */
+ function getObjectTypeName() {
+ return lang('category');
+ } // getObjectTypeName
+
+ /**
+ * Return view tag URL
+ *
+ * @param void
+ * @return string
+ */
+ function getObjectUrl() {
+ return $this->getViewUrl();
+ } // getObjectUrl
+
+ } // Comment
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/project_categories/base/BaseCategories.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_categories/base/BaseCategories.class.php
--- projectpier-0.8.0.3/application/models/project_categories/base/BaseCategories.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_categories/base/BaseCategories.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,220 @@
+ 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);
+
+ /**
+ * Construct
+ *
+ * @return BaseCategories
+ */
+ function __construct() {
+ parent::__construct('Category', 'project_categories', 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 Categories objects
+ * @throws DBQueryError
+ */
+ function find($arguments = null) {
+ if(isset($this) && instance_of($this, 'Categories')) {
+ return parent::find($arguments);
+ } else {
+ return Categories::instance()->find($arguments);
+ } // if
+ } // find
+
+ /**
+ * Find all records
+ *
+ * @access public
+ * @param array $arguments
+ * @return one or Categories objects
+ */
+ function findAll($arguments = null) {
+ if(isset($this) && instance_of($this, 'Categories')) {
+ return parent::findAll($arguments);
+ } else {
+ return Categories::instance()->findAll($arguments);
+ } // if
+ } // findAll
+
+ /**
+ * Find one specific record
+ *
+ * @access public
+ * @param array $arguments
+ * @return Category
+ */
+ function findOne($arguments = null) {
+ if(isset($this) && instance_of($this, 'Categories')) {
+ return parent::findOne($arguments);
+ } else {
+ return Categories::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 Category
+ */
+ function findById($id, $force_reload = false) {
+ if(isset($this) && instance_of($this, 'Categories')) {
+ return parent::findById($id, $force_reload);
+ } else {
+ return Categories::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, 'Categories')) {
+ return parent::count($condition);
+ } else {
+ return Categories::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, 'Categories')) {
+ return parent::delete($condition);
+ } else {
+ return Categories::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, 'Categories')) {
+ return parent::paginate($arguments, $items_per_page, $current_page);
+ } else {
+ return Categories::instance()->paginate($arguments, $items_per_page, $current_page);
+ } // if
+ } // paginate
+
+ /**
+ * Return manager instance
+ *
+ * @return Categories
+ */
+ function instance() {
+ static $instance;
+ if(!instance_of($instance, 'Categories')) {
+ $instance = new Categories();
+ } // if
+ return $instance;
+ } // instance
+
+ } // Categories
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/project_categories/base/BaseCategory.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_categories/base/BaseCategory.class.php
--- projectpier-0.8.0.3/application/models/project_categories/base/BaseCategory.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_categories/base/BaseCategory.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,117 @@
+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 integer
+ */
+ function getName() {
+ return $this->getColumnValue('name');
+ } // getName()
+
+ /**
+ * Set value of 'name' field
+ *
+ * @access public
+ * @param integer $value
+ * @return boolean
+ */
+ function setName($value) {
+ return $this->setColumnValue('name', $value);
+ } // setName()
+
+ /**
+ * 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 manager instance
+ *
+ * @access protected
+ * @param void
+ * @return Comments
+ */
+ function manager() {
+ if(!($this->manager instanceof Categories)) $this->manager = Categories::instance();
+ return $this->manager;
+ } // manager
+
+ } // BaseComment
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/project_messages/ProjectMessage.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_messages/ProjectMessage.class.php
--- projectpier-0.8.0.3/application/models/project_messages/ProjectMessage.class.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_messages/ProjectMessage.class.php Wed Aug 6 22:19:27 2008
@@ -42,7 +42,14 @@
* @var boolean
*/
protected $is_file_container = true;
-
+
+ /**
+ * Message is subscribible
+ *
+ * @var boolean
+ */
+ protected $is_subscribible = true;
+
/**
* Cached array of subscribers
*
diff -urN projectpier-0.8.0.3/application/models/project_tickets/ProjectTicket.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_tickets/ProjectTicket.class.php
--- projectpier-0.8.0.3/application/models/project_tickets/ProjectTicket.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_tickets/ProjectTicket.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,654 @@
+setUpdated('comment');
+ $this->save();
+
+ $change = new TicketChange();
+ $change->setTicketId($this->getId());
+ $change->setType('comment');
+ $change->setToData('#'.$this->countAllComments());
+ $change->save();
+
+ Notifier::newTicketComment($comment);
+ } catch(Exception $e) {
+ // nothing here, just suppress error...
+ } // try
+ } // onAddComment
+
+ // ---------------------------------------------------
+ // Files
+ // ---------------------------------------------------
+
+ /**
+ * Handle on add comment event
+ *
+ * @param array $files Attached files
+ * @return null
+ */
+ function onAttachFiles($files) {
+ try {
+ $this->setUpdated('attachment');
+ $this->save();
+
+ foreach ($files as $file) {
+ $change = new TicketChange();
+ $change->setTicketId($this->getId());
+ $change->setType('attachment');
+ $change->setToData($file->getFilename());
+ $change->save();
+ } // foreach
+
+ Notifier::attachFilesToTicket($this, $files);
+ } catch(Exception $e) {
+ // nothing here, just suppress error...
+ } // try
+ } // onAttachFiles
+
+ // ---------------------------------------------------
+ // Changes
+ // ---------------------------------------------------
+
+ /**
+ * Return array of changes
+ *
+ * @param void
+ * @return array
+ */
+ function getChanges() {
+ if(is_null($this->changes)) $this->changes = TicketChanges::getChangesByTicket($this);
+ return $this->changes;
+ } // getChanges
+
+ // ---------------------------------------------------
+ // Subscriptions
+ // ---------------------------------------------------
+
+ /**
+ * Return array of subscribers
+ *
+ * @param void
+ * @return array
+ */
+ function getSubscribers() {
+ if(is_null($this->subscribers)) $this->subscribers = TicketSubscriptions::getUsersByTicket($this);
+ return $this->subscribers;
+ } // getSubscribers
+
+ /**
+ * Check if specific user is subscriber
+ *
+ * @param User $user
+ * @return boolean
+ */
+ function isSubscriber(User $user) {
+ $subscription = TicketSubscriptions::findById(array(
+ 'ticket_id' => $this->getId(),
+ 'user_id' => $user->getId()
+ )); // findById
+ return $subscription instanceof TicketSubscription;
+ } // isSubscriber
+
+ /**
+ * Subscribe specific user to this ticket
+ *
+ * @param User $user
+ * @return boolean
+ */
+ function subscribeUser(User $user) {
+ if($this->isNew()) {
+ throw new Error('Can\'t subscribe user to ticket that is not saved');
+ } // if
+ if($this->isSubscriber($user)) {
+ return true;
+ } // if
+
+ // New subscription
+ $subscription = new TicketSubscription();
+ $subscription->setTicketId($this->getId());
+ $subscription->setUserId($user->getId());
+ return $subscription->save();
+ } // subscribeUser
+
+ /**
+ * Unsubscribe user
+ *
+ * @param User $user
+ * @return boolean
+ */
+ function unsubscribeUser(User $user) {
+ $subscription = TicketSubscriptions::findById(array(
+ 'ticket_id' => $this->getId(),
+ 'user_id' => $user->getId()
+ )); // findById
+ if($subscription instanceof TicketSubscription) {
+ return $subscription->delete();
+ } else {
+ return true;
+ } // if
+ } // unsubscribeUser
+
+ /**
+ * Clear all ticket subscriptions
+ *
+ * @param void
+ * @return boolean
+ */
+ function clearSubscriptions() {
+ return TicketSubscriptions::clearByTicket($this);
+ } // clearSubscriptions
+
+ // ---------------------------------------------------
+ // Operations
+ // ---------------------------------------------------
+
+ /**
+ * Return object name
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getTitle() {
+ return $this->getSummary();
+ } // getObjectName
+
+ /**
+ * Return owner project obj
+ *
+ * @access public
+ * @param void
+ * @return Project
+ */
+ function getProject() {
+ return Projects::findById($this->getProjectId());
+ } // getProject
+
+ /**
+ * Return user object of person who created this ticket
+ *
+ * @access public
+ * @param void
+ * @return User
+ */
+ function getClosedBy() {
+ return Users::findById($this->getClosedById());
+ } // getCreatedBy
+
+ /**
+ * Return owner user or company
+ *
+ * @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 owner comapny
+ *
+ * @access public
+ * @param void
+ * @return Company
+ */
+ function getAssignedToCompany() {
+ return Companies::findById($this->getAssignedToCompanyId());
+ } // getAssignedToCompany
+
+ /**
+ * Return owner user
+ *
+ * @access public
+ * @param void
+ * @return User
+ */
+ function getAssignedToUser() {
+ return Users::findById($this->getAssignedToUserId());
+ } // getAssignedToUser
+
+ /**
+ * Return owner user or company
+ *
+ * @access public
+ * @param void
+ * @return ApplicationDataObject
+ */
+ function getCategory() {
+ if($this->getCategoryId() > 0) {
+ return Categories::findById($this->getCategoryId());
+ } else {
+ return null;
+ } // if
+ } // getAssignedTo
+
+ /**
+ * Return status of ticket
+ *
+ * @access public
+ * @param void
+ * @return boolean
+ */
+ function getStatus() {
+ return $this->isClosed() ? 'closed' : 'open';
+ } // getStatus
+
+ /**
+ * Returns true if this ticket was not closed
+ *
+ * @access public
+ * @param void
+ * @return boolean
+ */
+ function isOpen() {
+ return !$this->isClosed();
+ } // isOpen
+
+ /**
+ * Returns true if this ticket is closed
+ *
+ * @access public
+ * @param void
+ * @return boolean
+ */
+ function isClosed() {
+ return $this->getClosedOn() instanceof DateTimeValue;
+ } // isClosed
+
+ // ---------------------------------------------------
+ // Permissions
+ // ---------------------------------------------------
+
+ /**
+ * Returns true if $user can access this ticket
+ *
+ * @param User $user
+ * @return boolean
+ */
+ function canView(User $user) {
+ if(!$user->isProjectUser($this->getProject())) {
+ return false; // user have access to project
+ } // if
+ if($this->isPrivate() && !$user->isMemberOfOwnerCompany()) {
+ return false; // user that is not member of owner company can't access private objects
+ } // if
+ return true;
+ } // canView
+
+ /**
+ * Check if specific user can add tickets to specific project
+ *
+ * @access public
+ * @param User $user
+ * @param Project $project
+ * @return booelean
+ */
+ function canAdd(User $user, Project $project) {
+ if(!$user->isProjectUser($project)) {
+ return false; // user is on project
+ } // if
+ return true;
+ } // canAdd
+
+ /**
+ * Check if specific user can update this ticket
+ *
+ * @access public
+ * @param User $user
+ * @return boolean
+ */
+ function canChangeStatus(User $user) {
+ if(!$user->isProjectUser($this->getProject())) {
+ return false;
+ } // if
+ if($this->canEdit($user)) {
+ return true;
+ } // if
+
+ return $user->getId() == $this->getCreatedById();
+ } // canEdit
+
+ /**
+ * Check if specific user can update this ticket
+ *
+ * @access public
+ * @param User $user
+ * @return boolean
+ */
+ function canEdit(User $user) {
+ if(!$user->isProjectUser($this->getProject())) {
+ return false;
+ } // if
+ if($user->isAdministrator()) {
+ return true;
+ } // if
+ if($this->isPrivate() && !$user->isMemberOfOwnerCompany()) {
+ return false; // user that is not member of owner company can't access private objects
+ } // if
+
+ $assigned_to = $this->getAssignedTo();
+ if($assigned_to instanceof User) {
+ if($user->getId() == $assigned_to->getId()) {
+ return true;
+ } // if
+ } elseif($assigned_to instanceof Company) {
+ if($user->getCompanyId() == $assigned_to->getId()) {
+ return true;
+ } // if
+ } // if
+
+ return $user->getProjectPermission($this->getProject(), ProjectUsers::CAN_MANAGE_TICKETS);
+ } // canEdit
+
+ /**
+ * Check if $user can update message options
+ *
+ * @param User $user
+ * @return boolean
+ */
+ function canUpdateOptions(User $user) {
+ return $user->isMemberOfOwnerCompany() && $this->canEdit($user);
+ } // canUpdateOptions
+
+ /**
+ * Check if specific user can delete this task
+ *
+ * @access public
+ * @param User $user
+ * @return boolean
+ */
+ function canDelete(User $user) {
+ if(!$user->isProjectUser($this->getProject())) {
+ return false;
+ } // if
+ if($user->isAdministrator()) {
+ return true;
+ } // if
+
+ return false; // no no
+ } // canDelete
+
+ // ---------------------------------------------------
+ // Operations
+ // ---------------------------------------------------
+
+ /**
+ * Complete this task and check if we need to complete the list
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function closeTicket() {
+ $this->setClosedOn(DateTimeValueLib::now());
+ $this->setClosedById(logged_user()->getId());
+ $this->setUpdated('closed');
+ $this->save();
+ } // completeTask
+
+ /**
+ * Open this task and check if we need to reopen list again
+ *
+ * @access public
+ * @param void
+ * @return null
+ */
+ function openTicket() {
+ $this->setClosedOn(null);
+ $this->setClosedById(0);
+ $this->setUpdated('open');
+ $this->save();
+ } // openTask
+
+ // ---------------------------------------------------
+ // URLs
+ // ---------------------------------------------------
+
+ /**
+ * Return view ticket URL
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getViewUrl() {
+ return $this->getEditUrl();
+ } // getViewUrl
+
+ /**
+ * Return edit task URL
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getEditUrl() {
+ return get_url('trac', 'edit', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
+ } // getEditUrl
+
+ /**
+ * Return delete task URL
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getDeleteUrl() {
+ return get_url('trac', 'delete', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
+ } // getDeleteUrl
+
+ /**
+ * Return comete task URL
+ *
+ * @access public
+ * @param string $redirect_to Redirect to this URL (referer will be used if this URL is not provided)
+ * @return string
+ */
+ function getCloseUrl($redirect_to = null) {
+ $params = array(
+ 'id' => $this->getId(),
+ 'active_project' => $this->getProjectId()
+ ); // array
+
+ if(trim($redirect_to)) {
+ $params['redirect_to'] = $redirect_to;
+ } // if
+
+ return get_url('trac', 'close', $params);
+ } // getCompleteUrl
+
+ /**
+ * Return open task URL
+ *
+ * @access public
+ * @param string $redirect_to Redirect to this URL (referer will be used if this URL is not provided)
+ * @return string
+ */
+ function getOpenUrl($redirect_to = null) {
+ $params = array(
+ 'id' => $this->getId(),
+ 'active_project' => $this->getProjectId()
+ ); // array
+
+ if(trim($redirect_to)) {
+ $params['redirect_to'] = $redirect_to;
+ } // if
+
+ return get_url('trac', 'open', $params);
+ } // getOpenUrl
+
+ /**
+ * Return update options URL
+ *
+ * @param void
+ * @return string
+ */
+ function getUpdateOptionsUrl() {
+ return get_url('trac', 'update_options', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
+ } // getUpdateOptionsUrl
+
+ /**
+ * Return subscribe URL
+ *
+ * @param void
+ * @return boolean
+ */
+ function getSubscribeUrl() {
+ return get_url('trac', 'subscribe', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
+ } // getSubscribeUrl
+
+ /**
+ * Return unsubscribe URL
+ *
+ * @param void
+ * @return boolean
+ */
+ function getUnsubscribeUrl() {
+ return get_url('trac', 'unsubscribe', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
+ } // getUnsubscribeUrl
+
+ // ---------------------------------------------------
+ // System
+ // ---------------------------------------------------
+
+ /**
+ * Validate before save
+ *
+ * @access public
+ * @param array $errors
+ * @return null
+ */
+ function validate(&$errors) {
+ if(!$this->validatePresenceOf('summary')) $errors[] = lang('ticket summary required');
+ if(!$this->validatePresenceOf('description')) $errors[] = lang('ticket description required');
+ } // validate
+
+ /**
+ * Delete this task
+ *
+ * @access public
+ * @param void
+ * @return boolean
+ */
+ function delete() {
+ $comments = $this->getComments();
+ if(is_array($comments)) foreach($comments as $comment) $comment->delete();
+
+ $this->clearSubscriptions();
+ return parent::delete();
+ } // delete
+
+ // ---------------------------------------------------
+ // ApplicationDataObject implementation
+ // ---------------------------------------------------
+
+ /**
+ * Return object name
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getObjectName() {
+ return $this->getSummary();
+ } // getObjectName
+
+ /**
+ * Return object type name
+ *
+ * @param void
+ * @return string
+ */
+ function getObjectTypeName() {
+ return lang('ticket');
+ } // getObjectTypeName
+
+ /**
+ * Return object URl
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getObjectUrl() {
+ return $this->getViewUrl();
+ } // getObjectUrl
+
+ } // ProjectTicket
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/project_tickets/ProjectTickets.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_tickets/ProjectTickets.class.php
--- projectpier-0.8.0.3/application/models/project_tickets/ProjectTickets.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_tickets/ProjectTickets.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,89 @@
+getId());
+ } else {
+ $conditions = array('`project_id` = ? AND `is_private` = ?', $project->getId(), false);
+ } // if
+
+ return self::findAll(array(
+ 'conditions' => $conditions,
+ 'order' => '`created_on` DESC',
+ )); // findAll
+ } // getProjectTickets
+
+ /**
+ * Return open tickets for specific project
+ *
+ * @param Project $project
+ * @param boolean $include_private Include private tickets
+ * @return array
+ */
+ static function getOpenProjectTickets(Project $project, $include_private = false) {
+ if($include_private) {
+ $conditions = array('`project_id` = ? AND `closed_on` = ?', $project->getId(), EMPTY_DATETIME);
+ } else {
+ $conditions = array('`project_id` = ? AND `closed_on` = ? AND `is_private` = ?', $project->getId(), EMPTY_DATETIME, false);
+ } // if
+
+ return self::findAll(array(
+ 'conditions' => $conditions,
+ 'order' => '`created_on` DESC',
+ )); // findAll
+ } // getOpenProjectTickets
+
+ /**
+ * Return closed tickets for specific project
+ *
+ * @param Project $project
+ * @param boolean $include_private Include private tickets
+ * @return array
+ */
+ static function getClosedProjectTickets(Project $project, $include_private = false) {
+ if($include_private) {
+ $conditions = array('`project_id` = ? AND `closed_on` > ?', $project->getId(), EMPTY_DATETIME);
+ } else {
+ $conditions = array('`project_id` = ? AND `closed_on` > ? AND `is_private` = ?', $project->getId(), EMPTY_DATETIME, false);
+ } // if
+
+ return self::findAll(array(
+ 'conditions' => $conditions,
+ 'order' => '`created_on` DESC',
+ )); // findAll
+ } // getClosedProjectTickets
+
+ /**
+ * Return trac index page
+ *
+ * @param string $order_by
+ * @param integer $page
+ * @return string
+ */
+ static function getIndexUrl($closed = false) {
+ if ($closed) {
+ $options = array('closed' => true);
+ } else {
+ $options = array();
+ } // if
+ return get_url('trac', 'index', $options);
+ } // getIndexUrl
+
+ } // ProjectTickets
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/project_tickets/base/BaseProjectTicket.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_tickets/base/BaseProjectTicket.class.php
--- projectpier-0.8.0.3/application/models/project_tickets/base/BaseProjectTicket.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_tickets/base/BaseProjectTicket.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,403 @@
+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 'category_id' field
+ *
+ * @access public
+ * @param void
+ * @return integer
+ */
+ function getCategoryId() {
+ return $this->getColumnValue('category_id');
+ } // getCategoryId()
+
+ /**
+ * Set value of 'category_id' field
+ *
+ * @access public
+ * @param integer $value
+ * @return boolean
+ */
+ function setCategoryId($value) {
+ return $this->setColumnValue('category_id', $value);
+ } // setCategoryId()
+
+ /**
+ * 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 'closed_by_id' field
+ *
+ * @access public
+ * @param void
+ * @return integer
+ */
+ function getClosedById() {
+ return $this->getColumnValue('closed_by_id');
+ } // getClosedById()
+
+ /**
+ * Set value of 'closed_by_id' field
+ *
+ * @access public
+ * @param integer $value
+ * @return boolean
+ */
+ function setClosedById($value) {
+ return $this->setColumnValue('closed_by_id', $value);
+ } // getClosedById()
+
+ /**
+ * 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 'summary' field
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getSummary() {
+ return $this->getColumnValue('summary');
+ } // getSummary()
+
+ /**
+ * Set value of 'summary' field
+ *
+ * @access public
+ * @param string $value
+ * @return boolean
+ */
+ function setSummary($value) {
+ return $this->setColumnValue('summary', $value);
+ } // setSummary()
+
+ /**
+ * Return value of 'type' field
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getType() {
+ return $this->getColumnValue('type');
+ } // getType()
+
+ /**
+ * Set value of 'type' field
+ *
+ * @access public
+ * @param string $value
+ * @return boolean
+ */
+ function setType($value) {
+ return $this->setColumnValue('type', $value);
+ } // setType()
+
+ /**
+ * 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 'priority' field
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getPriority() {
+ return $this->getColumnValue('priority');
+ } // getPriority()
+
+ /**
+ * Set value of 'priority' field
+ *
+ * @access public
+ * @param string $value
+ * @return boolean
+ */
+ function setPriority($value) {
+ return $this->setColumnValue('priority', $value);
+ } // setPriority()
+
+ /**
+ * 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 'closed_on' field
+ *
+ * @access public
+ * @param void
+ * @return DateTimeValue
+ */
+ function getClosedOn() {
+ return $this->getColumnValue('closed_on');
+ } // getClosedOn()
+
+ /**
+ * Set value of 'closed_on' field
+ *
+ * @access public
+ * @param DateTimeValue $value
+ * @return boolean
+ */
+ function setClosedOn($value) {
+ return $this->setColumnValue('closed_on', $value);
+ } // setClosedOn()
+
+ /**
+ * 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 value of 'updated' field
+ *
+ * @access public
+ * @param void
+ * @return integer
+ */
+ function getUpdated() {
+ return $this->getColumnValue('updated');
+ } // getUpdated()
+
+ /**
+ * Set value of 'updated' field
+ *
+ * @access public
+ * @param integer $value
+ * @return boolean
+ */
+ function setUpdated($value) {
+ return $this->setColumnValue('updated', $value);
+ } // setUpdated()
+
+ /**
+ * 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 manager instance
+ *
+ * @access protected
+ * @param void
+ * @return ProjectTickets
+ */
+ function manager() {
+ if(!($this->manager instanceof ProjectTickets)) $this->manager = ProjectTickets::instance();
+ return $this->manager;
+ } // manager
+
+ } // BaseProjectTicket
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/project_tickets/base/BaseProjectTickets.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_tickets/base/BaseProjectTickets.class.php
--- projectpier-0.8.0.3/application/models/project_tickets/base/BaseProjectTickets.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_tickets/base/BaseProjectTickets.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,220 @@
+ Column type map
+ *
+ * @var array
+ * @static
+ */
+ static private $columns = array('id' => DATA_TYPE_INTEGER, 'project_id' => DATA_TYPE_INTEGER, 'category_id' => DATA_TYPE_INTEGER, 'created_by_id' => DATA_TYPE_INTEGER, 'closed_by_id' => DATA_TYPE_INTEGER, 'assigned_to_user_id' => DATA_TYPE_INTEGER, 'assigned_to_company_id' => DATA_TYPE_INTEGER, 'summary' => DATA_TYPE_STRING, 'type' => DATA_TYPE_STRING, 'description' => DATA_TYPE_STRING, 'priority' => DATA_TYPE_STRING, 'created_on' => DATA_TYPE_DATETIME, 'closed_on' => DATA_TYPE_DATETIME, 'updated_on' => DATA_TYPE_DATETIME, 'updated_by_id' => DATA_TYPE_INTEGER, 'updated' => DATA_TYPE_STRING, 'is_private' => DATA_TYPE_BOOLEAN);
+
+ /**
+ * Construct
+ *
+ * @return BaseProjectTickets
+ */
+ function __construct() {
+ parent::__construct('ProjectTicket', 'project_tickets', 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 ProjectTickets objects
+ * @throws DBQueryError
+ */
+ function find($arguments = null) {
+ if(isset($this) && instance_of($this, 'ProjectTickets')) {
+ return parent::find($arguments);
+ } else {
+ return ProjectTickets::instance()->find($arguments);
+ } // if
+ } // find
+
+ /**
+ * Find all records
+ *
+ * @access public
+ * @param array $arguments
+ * @return one or ProjectTickets objects
+ */
+ function findAll($arguments = null) {
+ if(isset($this) && instance_of($this, 'ProjectTickets')) {
+ return parent::findAll($arguments);
+ } else {
+ return ProjectTickets::instance()->findAll($arguments);
+ } // if
+ } // findAll
+
+ /**
+ * Find one specific record
+ *
+ * @access public
+ * @param array $arguments
+ * @return ProjectTicket
+ */
+ function findOne($arguments = null) {
+ if(isset($this) && instance_of($this, 'ProjectTickets')) {
+ return parent::findOne($arguments);
+ } else {
+ return ProjectTickets::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 ProjectTicket
+ */
+ function findById($id, $force_reload = false) {
+ if(isset($this) && instance_of($this, 'ProjectTickets')) {
+ return parent::findById($id, $force_reload);
+ } else {
+ return ProjectTickets::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, 'ProjectTickets')) {
+ return parent::count($condition);
+ } else {
+ return ProjectTickets::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, 'ProjectTickets')) {
+ return parent::delete($condition);
+ } else {
+ return ProjectTickets::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, 'ProjectTickets')) {
+ return parent::paginate($arguments, $items_per_page, $current_page);
+ } else {
+ return ProjectTickets::instance()->paginate($arguments, $items_per_page, $current_page);
+ } // if
+ } // paginate
+
+ /**
+ * Return manager instance
+ *
+ * @return ProjectTickets
+ */
+ function instance() {
+ static $instance;
+ if(!instance_of($instance, 'ProjectTickets')) {
+ $instance = new ProjectTickets();
+ } // if
+ return $instance;
+ } // instance
+
+ } // BaseProjectTickets
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/project_users/ProjectUsers.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_users/ProjectUsers.class.php
--- projectpier-0.8.0.3/application/models/project_users/ProjectUsers.class.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_users/ProjectUsers.class.php Wed Aug 6 22:27:49 2008
@@ -14,6 +14,7 @@
const CAN_MANAGE_MILESTONES = 'can_manage_milestones';
const CAN_UPLOAD_FILES = 'can_upload_files';
const CAN_MANAGE_FILES = 'can_manage_files';
+ const CAN_MANAGE_TICKETS = 'can_manage_tickets';
const CAN_ASSIGN_TO_OWNERS = 'can_assign_to_owners';
const CAN_ASSIGN_TO_OTHER = 'can_assign_to_other';
@@ -125,6 +126,7 @@
self::CAN_MANAGE_MILESTONES,
self::CAN_UPLOAD_FILES,
self::CAN_MANAGE_FILES,
+ self::CAN_MANAGE_TICKETS,
self::CAN_ASSIGN_TO_OWNERS,
self::CAN_ASSIGN_TO_OTHER,
); // array
@@ -143,6 +145,7 @@
ProjectUsers::CAN_MANAGE_MILESTONES => lang('can manage milestones'),
ProjectUsers::CAN_UPLOAD_FILES => lang('can upload files'),
ProjectUsers::CAN_MANAGE_FILES => lang('can manage files'),
+ ProjectUsers::CAN_MANAGE_TICKETS => lang('can manage tickets'),
ProjectUsers::CAN_ASSIGN_TO_OWNERS => lang('can assign to owners'),
ProjectUsers::CAN_ASSIGN_TO_OTHER => lang('can assign to other'),
); // array
diff -urN projectpier-0.8.0.3/application/models/project_users/base/BaseProjectUser.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_users/base/BaseProjectUser.class.php
--- projectpier-0.8.0.3/application/models/project_users/base/BaseProjectUser.class.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_users/base/BaseProjectUser.class.php Wed Aug 6 22:21:15 2008
@@ -210,6 +210,28 @@
} // setCanManageFiles()
/**
+ * Return value of 'can_manage_tickets' field
+ *
+ * @access public
+ * @param void
+ * @return boolean
+ */
+ function getCanManageTickets() {
+ return $this->getColumnValue('can_manage_tickets');
+ } // getCanManageFiles()
+
+ /**
+ * Set value of 'can_manage_tickets' field
+ *
+ * @access public
+ * @param boolean $value
+ * @return boolean
+ */
+ function setCanManageTickets($value) {
+ return $this->setColumnValue('can_manage_tickets', $value);
+ } // setCanManageFiles()
+
+ /**
* Return value of 'can_assign_to_owners' field
*
* @access public
diff -urN projectpier-0.8.0.3/application/models/project_users/base/BaseProjectUsers.class.php projectpier-0.8.0.3-trackerpatch/application/models/project_users/base/BaseProjectUsers.class.php
--- projectpier-0.8.0.3/application/models/project_users/base/BaseProjectUsers.class.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/models/project_users/base/BaseProjectUsers.class.php Wed Aug 6 22:26:37 2008
@@ -14,7 +14,7 @@
* @var array
* @static
*/
- static private $columns = array('project_id' => DATA_TYPE_INTEGER, 'user_id' => DATA_TYPE_INTEGER, 'created_on' => DATA_TYPE_DATETIME, 'created_by_id' => DATA_TYPE_INTEGER, 'can_manage_messages' => DATA_TYPE_BOOLEAN, 'can_manage_tasks' => DATA_TYPE_BOOLEAN, 'can_manage_milestones' => DATA_TYPE_BOOLEAN, 'can_upload_files' => DATA_TYPE_BOOLEAN, 'can_manage_files' => DATA_TYPE_BOOLEAN, 'can_assign_to_owners' => DATA_TYPE_BOOLEAN, 'can_assign_to_other' => DATA_TYPE_BOOLEAN);
+ static private $columns = array('project_id' => DATA_TYPE_INTEGER, 'user_id' => DATA_TYPE_INTEGER, 'created_on' => DATA_TYPE_DATETIME, 'created_by_id' => DATA_TYPE_INTEGER, 'can_manage_messages' => DATA_TYPE_BOOLEAN, 'can_manage_tasks' => DATA_TYPE_BOOLEAN, 'can_manage_milestones' => DATA_TYPE_BOOLEAN, 'can_upload_files' => DATA_TYPE_BOOLEAN, 'can_manage_files' => DATA_TYPE_BOOLEAN, 'can_manage_tickets' => DATA_TYPE_BOOLEAN, 'can_assign_to_owners' => DATA_TYPE_BOOLEAN, 'can_assign_to_other' => DATA_TYPE_BOOLEAN);
/**
* Construct
diff -urN projectpier-0.8.0.3/application/models/projects/Project.class.php projectpier-0.8.0.3-trackerpatch/application/models/projects/Project.class.php
--- projectpier-0.8.0.3/application/models/projects/Project.class.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/models/projects/Project.class.php Wed Aug 6 22:34:21 2008
@@ -165,6 +165,62 @@
private $completed_task_lists;
// ---------------------------------------------------
+ // Trac
+ // ---------------------------------------------------
+
+ /**
+ * All categories in this project
+ *
+ * @var array
+ */
+ private $categories;
+
+ /**
+ * All tickets in this project
+ *
+ * @var array
+ */
+ private $all_tickets;
+
+ /**
+ * Array of all tickets. If user is not member of owner company private tickets
+ * will be excluded from the list
+ *
+ * @var array
+ */
+ private $tickets;
+
+ /**
+ * All open tickets in this project
+ *
+ * @var array
+ */
+ private $all_open_tickets;
+
+ /**
+ * Array of open tickets. If user is not member of owner company private tickets
+ * will be excluded from the list
+ *
+ * @var array
+ */
+ private $open_tickets;
+
+ /**
+ * All closed tickets in this project
+ *
+ * @var array
+ */
+ private $all_closed_tickets;
+
+ /**
+ * Array of closed tickets. If user is not member of owner company private tickets
+ * will be excluded from the list
+ *
+ * @var array
+ */
+ private $closed_tickets;
+
+ // ---------------------------------------------------
// Tags
// ---------------------------------------------------
@@ -609,6 +665,119 @@
} // getCompletedTaskLists
// ---------------------------------------------------
+ // Trac
+ // ---------------------------------------------------
+
+ /**
+ * Return all categories
+ *
+ * @param void
+ * @return array
+ */
+ function getCategories() {
+ if(is_null($this->categories)) {
+ $this->categories = Categories::getProjectCategories($this);
+ } // if
+ return $this->categories;
+ } // getCategories
+
+ /**
+ * This function will return all tickets in project and it will not exclude private
+ * tickets if logged user is not member of owner company
+ *
+ * @param void
+ * @return array
+ */
+ function getAllTickets() {
+ if(is_null($this->all_tickets)) {
+ $this->all_tickets = ProjectTickets::getProjectTickets($this, true);
+ } // if
+ return $this->all_tickets;
+ } // getAllTickets
+
+ /**
+ * Return only the tickets that current user can see (if not member of owner company private
+ * tickets will be excluded)
+ *
+ * @param void
+ * @return array
+ */
+ function getTickets() {
+ if(logged_user()->isMemberOfOwnerCompany()) {
+ return $this->getAllTickets(); // members of owner company can view all tickets
+ } // if
+
+ if(is_null($this->tickets)) {
+ $this->tickets = ProjectTickets::getProjectTickets($this, false);
+ } // if
+ return $this->tickets;
+ } // getTickets
+
+ /**
+ * This function will return all open tickets in project and it will not exclude private
+ * tickets if logged user is not member of owner company
+ *
+ * @param void
+ * @return array
+ */
+ function getAllOpenTickets() {
+ if(is_null($this->all_open_tickets)) {
+ $this->all_open_tickets = ProjectTickets::getOpenProjectTickets($this, true);
+ } // if
+ return $this->all_open_tickets;
+ } // getAllOpenTickets
+
+ /**
+ * Return only the open tickets that current user can see (if not member of owner company private
+ * tickets will be excluded)
+ *
+ * @param void
+ * @return array
+ */
+ function getOpenTickets() {
+ if(logged_user()->isMemberOfOwnerCompany()) {
+ return $this->getAllOpenTickets(); // members of owner company can view all tickets
+ } // if
+
+ if(is_null($this->open_tickets)) {
+ $this->open_tickets = ProjectTickets::getOpenProjectTickets($this, false);
+ } // if
+ return $this->open_tickets;
+ } // getOpenTickets
+
+ /**
+ * This function will return all closed tickets in project and it will not exclude private
+ * tickets if logged user is not member of owner company
+ *
+ * @param void
+ * @return array
+ */
+ function getAllClosedTickets() {
+ if(is_null($this->all_closed_tickets)) {
+ $this->all_closed_tickets = ProjectTickets::getClosedProjectTickets($this, true);
+ } // if
+ return $this->all_closed_tickets;
+ } // getAllClosedTickets
+
+ /**
+ * Return only the closed tickets that current user can see (if not member of owner company private
+ * tickets will be excluded)
+ *
+ * @param void
+ * @return array
+ */
+ function getClosedTickets() {
+ if(logged_user()->isMemberOfOwnerCompany()) {
+ return $this->getAllClosedTickets(); // members of owner company can view all tickets
+ } // if
+
+ if(is_null($this->closed_tickets)) {
+ $this->closed_tickets = ProjectTickets::getClosedProjectTickets($this, false);
+ } // if
+ return $this->closed_tickets;
+ } // getClosedTickets
+
+ // ---------------------------------------------------
// Tags
// ---------------------------------------------------
@@ -903,6 +1072,27 @@
} // getUsersTasks
// ---------------------------------------------------
+ // User tickets
+ // ---------------------------------------------------
+
+ /**
+ * Return array of task that are assigned to specific user or his company
+ *
+ * @param User $user
+ * @return array
+ */
+ function getUsersTickets(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` = ?) OR `created_by_id`= ?) AND `closed_on` = ?', array($this->getId(), $user->getId(), $user->getCompanyId(), 0, $user->getCompanyId(), 0, 0, $user->getId(), EMPTY_DATETIME));
+ if(!$user->isMemberOfOwnerCompany()) {
+ $conditions .= DB::prepareString(' AND `is_private` = ?', array(0));
+ } // if
+ return ProjectTickets::findAll(array(
+ 'conditions' => $conditions,
+ 'order' => '`created_on`'
+ )); // findAll
+ } // getUsersTickets
+
+ // ---------------------------------------------------
// Files
// ---------------------------------------------------
@@ -1129,6 +1319,16 @@
return get_url('milestone', 'index', array('active_project' => $this->getId()));
} // getMilestonesUrl
+ /**
+ * Return project trac index page URL
+ *
+ * @param void
+ * @return string
+ */
+ function getTracUrl() {
+ return get_url('trac', 'index', array('active_project' => $this->getId()));
+ } // getTracUrl
+
/**
* Return project forms index page URL
*
diff -urN projectpier-0.8.0.3/application/models/ticket_changes/TicketChange.class.php projectpier-0.8.0.3-trackerpatch/application/models/ticket_changes/TicketChange.class.php
--- projectpier-0.8.0.3/application/models/ticket_changes/TicketChange.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/ticket_changes/TicketChange.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,41 @@
+ticket)) $this->ticket = ProjectTickets::findById($this->getTicketId());
+ return $this->ticket;
+ } // getTicket
+
+ /**
+ * Return if data needs translation
+ *
+ * @param void
+ * @return ProjectTicket
+ */
+ function dataNeedsTranslation() {
+ return ($this->getType() == 'priority') || ($this->getType() == 'type') || ($this->getType() == 'status') || ($this->getType() == 'private');
+ } // dataNeedsTranslation
+
+ } // TicketChanges
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/ticket_changes/TicketChanges.class.php projectpier-0.8.0.3-trackerpatch/application/models/ticket_changes/TicketChanges.class.php
--- projectpier-0.8.0.3/application/models/ticket_changes/TicketChanges.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/ticket_changes/TicketChanges.class.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,26 @@
+ array('`ticket_id` = ?', $ticket->getId()),
+ 'order' => '`created_on`'
+ )); // array
+ } // getChangesByTicket
+
+ } // TicketChanges
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/ticket_changes/base/BaseTicketChange.class.php projectpier-0.8.0.3-trackerpatch/application/models/ticket_changes/base/BaseTicketChange.class.php
--- projectpier-0.8.0.3/application/models/ticket_changes/base/BaseTicketChange.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/ticket_changes/base/BaseTicketChange.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,161 @@
+getColumnValue('ticket_id');
+ } // getTicketId()
+
+ /**
+ * Set value of 'ticket_id' field
+ *
+ * @access public
+ * @param integer $value
+ * @return boolean
+ */
+ function setTicketId($value) {
+ return $this->setColumnValue('ticket_id', $value);
+ } // setTicketId()
+
+ /**
+ * Return value of 'type' field
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getType() {
+ return $this->getColumnValue('type');
+ } // getType()
+
+ /**
+ * Set value of 'type' field
+ *
+ * @access public
+ * @param string $value
+ * @return boolean
+ */
+ function setType($value) {
+ return $this->setColumnValue('type', $value);
+ } // setType()
+
+ /**
+ * Return value of 'from_data' field
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getFromData() {
+ return $this->getColumnValue('from_data');
+ } // getFromData()
+
+ /**
+ * Set value of 'from_data' field
+ *
+ * @access public
+ * @param string $value
+ * @return boolean
+ */
+ function setFromData($value) {
+ return $this->setColumnValue('from_data', $value);
+ } // setFromData()
+
+ /**
+ * Return value of 'to_data' field
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getToData() {
+ return $this->getColumnValue('to_data');
+ } // getToData()
+
+ /**
+ * Set value of 'to_data' field
+ *
+ * @access public
+ * @param string $value
+ * @return boolean
+ */
+ function setToData($value) {
+ return $this->setColumnValue('to_data', $value);
+ } // setToData()
+
+ /**
+ * 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 manager instance
+ *
+ * @access protected
+ * @param void
+ * @return TicketChanges
+ */
+ function manager() {
+ if(!($this->manager instanceof TicketChanges)) $this->manager = TicketChanges::instance();
+ return $this->manager;
+ } // manager
+
+ } // BaseTicketChange
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/ticket_changes/base/BaseTicketChanges.class.php projectpier-0.8.0.3-trackerpatch/application/models/ticket_changes/base/BaseTicketChanges.class.php
--- projectpier-0.8.0.3/application/models/ticket_changes/base/BaseTicketChanges.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/ticket_changes/base/BaseTicketChanges.class.php Wed Aug 6 22:00:17 2008
@@ -0,0 +1,220 @@
+ Column type map
+ *
+ * @var array
+ * @static
+ */
+ static private $columns = array('id' => DATA_TYPE_INTEGER, 'ticket_id' => DATA_TYPE_INTEGER, 'type' => DATA_TYPE_STRING, 'from_data' => DATA_TYPE_STRING, 'to_data' => DATA_TYPE_STRING, 'created_on' => DATA_TYPE_DATETIME, 'created_by_id' => DATA_TYPE_INTEGER);
+
+ /**
+ * Construct
+ *
+ * @return BaseTicketChanges
+ */
+ function __construct() {
+ parent::__construct('TicketChange', 'ticket_changes', 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 TicketChanges objects
+ * @throws DBQueryError
+ */
+ function find($arguments = null) {
+ if(isset($this) && instance_of($this, 'TicketChanges')) {
+ return parent::find($arguments);
+ } else {
+ return TicketChanges::instance()->find($arguments);
+ } // if
+ } // find
+
+ /**
+ * Find all records
+ *
+ * @access public
+ * @param array $arguments
+ * @return one or TicketChanges objects
+ */
+ function findAll($arguments = null) {
+ if(isset($this) && instance_of($this, 'TicketChanges')) {
+ return parent::findAll($arguments);
+ } else {
+ return TicketChanges::instance()->findAll($arguments);
+ } // if
+ } // findAll
+
+ /**
+ * Find one specific record
+ *
+ * @access public
+ * @param array $arguments
+ * @return TicketChange
+ */
+ function findOne($arguments = null) {
+ if(isset($this) && instance_of($this, 'TicketChanges')) {
+ return parent::findOne($arguments);
+ } else {
+ return TicketChanges::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 TicketChange
+ */
+ function findById($id, $force_reload = false) {
+ if(isset($this) && instance_of($this, 'TicketChanges')) {
+ return parent::findById($id, $force_reload);
+ } else {
+ return TicketChanges::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, 'TicketChanges')) {
+ return parent::count($condition);
+ } else {
+ return TicketChanges::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, 'TicketChanges')) {
+ return parent::delete($condition);
+ } else {
+ return TicketChanges::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, 'TicketChanges')) {
+ return parent::paginate($arguments, $items_per_page, $current_page);
+ } else {
+ return TicketChanges::instance()->paginate($arguments, $items_per_page, $current_page);
+ } // if
+ } // paginate
+
+ /**
+ * Return manager instance
+ *
+ * @return TicketChanges
+ */
+ function instance() {
+ static $instance;
+ if(!instance_of($instance, 'TicketChanges')) {
+ $instance = new TicketChanges();
+ } // if
+ return $instance;
+ } // instance
+
+ } // TicketChanges
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/ticket_subscriptions/TicketSubscription.class.php projectpier-0.8.0.3-trackerpatch/application/models/ticket_subscriptions/TicketSubscription.class.php
--- projectpier-0.8.0.3/application/models/ticket_subscriptions/TicketSubscription.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/ticket_subscriptions/TicketSubscription.class.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,49 @@
+user)) $this->user = Users::findById($this->getUserId());
+ return $this->user;
+ } // getUser
+
+ /**
+ * Return ticket object
+ *
+ * @param void
+ * @return ProjectTicket
+ */
+ function getTicket() {
+ if(is_null($this->ticket)) $this->ticket = ProjectTickets::findById($this->getTicketId());
+ return $this->ticket;
+ } // getTicket
+
+ } // TicketSubscription
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/ticket_subscriptions/TicketSubscriptions.class.php projectpier-0.8.0.3-trackerpatch/application/models/ticket_subscriptions/TicketSubscriptions.class.php
--- projectpier-0.8.0.3/application/models/ticket_subscriptions/TicketSubscriptions.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/ticket_subscriptions/TicketSubscriptions.class.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,73 @@
+ '`ticket_id` = ' . DB::escape($ticket->getId())
+ )); // findAll
+ if(is_array($subscriptions)) {
+ foreach($subscriptions as $subscription) {
+ $user = $subscription->getUser();
+ if($user instanceof User) $users[] = $user;
+ } // foreach
+ } // if
+ return count($users) ? $users : null;
+ } // getUsersByTicket
+
+ /**
+ * Return array of tickets that $user is subscribed to
+ *
+ * @param User $user
+ * @return array
+ */
+ static function getTicketsByUser(User $user) {
+ $tickets = array();
+ $subscriptions = TicketSubscriptions::findAll(array(
+ 'conditions' => '`user_id` = ' . DB::escape($user->getId())
+ )); // findAll
+ if(is_array($subscriptions)) {
+ foreach($subscriptions as $subscription) {
+ $ticket = $subscription->getTicket();
+ if($tickets instanceof ProjectTicket) $tickets[] = $ticket;
+ } // foreach
+ } // if
+ return count($tickets) ? $tickets : null;
+ } // getTicketsByUser
+
+ /**
+ * Clear subscriptions by ticket
+ *
+ * @param ProjectTicket $ticket
+ * @return boolean
+ */
+ static function clearByTicket(ProjectTicket $ticket) {
+ return TicketSubscriptions::delete('`ticket_id` = ' . DB::escape($ticket->getId()));
+ } // clearByTicket
+
+ /**
+ * Clear subscriptions by user
+ *
+ * @param User $user
+ * @return boolean
+ */
+ static function clearByUser(User $user) {
+ return TicketSubscriptions::delete('`user_id` = ' . DB::escape($user->getId()));
+ } // clearByUser
+
+ } // TicketSubscriptions
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/ticket_subscriptions/base/BaseTicketSubscription.class.php projectpier-0.8.0.3-trackerpatch/application/models/ticket_subscriptions/base/BaseTicketSubscription.class.php
--- projectpier-0.8.0.3/application/models/ticket_subscriptions/base/BaseTicketSubscription.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/ticket_subscriptions/base/BaseTicketSubscription.class.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,73 @@
+getColumnValue('ticket_id');
+ } // getTicketId()
+
+ /**
+ * Set value of 'ticket_id' field
+ *
+ * @access public
+ * @param integer $value
+ * @return boolean
+ */
+ function setTicketId($value) {
+ return $this->setColumnValue('ticket_id', $value);
+ } // setTicketId()
+
+ /**
+ * Return value of 'user_id' field
+ *
+ * @access public
+ * @param void
+ * @return integer
+ */
+ function getUserId() {
+ return $this->getColumnValue('user_id');
+ } // getUserId()
+
+ /**
+ * Set value of 'user_id' field
+ *
+ * @access public
+ * @param integer $value
+ * @return boolean
+ */
+ function setUserId($value) {
+ return $this->setColumnValue('user_id', $value);
+ } // setUserId()
+
+
+ /**
+ * Return manager instance
+ *
+ * @access protected
+ * @param void
+ * @return TicketSubscriptions
+ */
+ function manager() {
+ if(!($this->manager instanceof TicketSubscriptions)) $this->manager = TicketSubscriptions::instance();
+ return $this->manager;
+ } // manager
+
+ } // BaseTicketSubscription
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/models/ticket_subscriptions/base/BaseTicketSubscriptions.class.php projectpier-0.8.0.3-trackerpatch/application/models/ticket_subscriptions/base/BaseTicketSubscriptions.class.php
--- projectpier-0.8.0.3/application/models/ticket_subscriptions/base/BaseTicketSubscriptions.class.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/models/ticket_subscriptions/base/BaseTicketSubscriptions.class.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,223 @@
+ Column type map
+ *
+ * @var array
+ * @static
+ */
+ static private $columns = array('ticket_id' => DATA_TYPE_INTEGER, 'user_id' => DATA_TYPE_INTEGER);
+
+ /**
+ * Construct
+ *
+ * @return BaseTicketSubscriptions
+ */
+ function __construct() {
+ parent::__construct('TicketSubscription', 'ticket_subscriptions', 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 array (
+ 0 => 'ticket_id',
+ 1 => 'user_id',
+);
+ } // getPkColumns
+
+ /**
+ * Return name of first auto_incremenent column if it exists
+ *
+ * @access public
+ * @param void
+ * @return string
+ */
+ function getAutoIncrementColumn() {
+ return NULL;
+ } // 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 TicketSubscriptions objects
+ * @throws DBQueryError
+ */
+ function find($arguments = null) {
+ if(isset($this) && instance_of($this, 'TicketSubscriptions')) {
+ return parent::find($arguments);
+ } else {
+ return TicketSubscriptions::instance()->find($arguments);
+ } // if
+ } // find
+
+ /**
+ * Find all records
+ *
+ * @access public
+ * @param array $arguments
+ * @return one or TicketSubscriptions objects
+ */
+ function findAll($arguments = null) {
+ if(isset($this) && instance_of($this, 'TicketSubscriptions')) {
+ return parent::findAll($arguments);
+ } else {
+ return TicketSubscriptions::instance()->findAll($arguments);
+ } // if
+ } // findAll
+
+ /**
+ * Find one specific record
+ *
+ * @access public
+ * @param array $arguments
+ * @return TicketSubscription
+ */
+ function findOne($arguments = null) {
+ if(isset($this) && instance_of($this, 'TicketSubscriptions')) {
+ return parent::findOne($arguments);
+ } else {
+ return TicketSubscriptions::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 TicketSubscription
+ */
+ function findById($id, $force_reload = false) {
+ if(isset($this) && instance_of($this, 'TicketSubscriptions')) {
+ return parent::findById($id, $force_reload);
+ } else {
+ return TicketSubscriptions::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, 'TicketSubscriptions')) {
+ return parent::count($condition);
+ } else {
+ return TicketSubscriptions::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, 'TicketSubscriptions')) {
+ return parent::delete($condition);
+ } else {
+ return TicketSubscriptions::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, 'TicketSubscriptions')) {
+ return parent::paginate($arguments, $items_per_page, $current_page);
+ } else {
+ return TicketSubscriptions::instance()->paginate($arguments, $items_per_page, $current_page);
+ } // if
+ } // paginate
+
+ /**
+ * Return manager instance
+ *
+ * @return TicketSubscriptions
+ */
+ function instance() {
+ static $instance;
+ if(!instance_of($instance, 'TicketSubscriptions')) {
+ $instance = new TicketSubscriptions();
+ } // if
+ return $instance;
+ } // instance
+
+ } // TicketSubscriptions
+
+?>
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/application/user_box.php projectpier-0.8.0.3-trackerpatch/application/views/application/user_box.php
--- projectpier-0.8.0.3/application/views/application/user_box.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/application/views/application/user_box.php Wed Aug 6 22:00:18 2008
@@ -21,6 +21,7 @@
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/trac/add_category.php projectpier-0.8.0.3-trackerpatch/application/views/trac/add_category.php
--- projectpier-0.8.0.3/application/views/trac/add_category.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/views/trac/add_category.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,47 @@
+isNew() ? lang('add tracCategory') : lang('edit tracCategory'));
+ project_tabbed_navigation(PROJECT_TAB_TICKETS);
+ project_crumbs(array(
+ array(lang('tickets'), get_url('trac')),
+ array(lang('tracCategories'), get_url('trac','categories')),
+ array($category->isNew() ? lang('add tracCategory') : lang('edit tracCategory'))
+ ));
+ $canEdit = $category->isNew() || $category->canEdit(logged_user());
+ add_stylesheet_to_page('project/tickets.css');
+?>
+
+isNew()) { ?>
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/trac/categories.php projectpier-0.8.0.3-trackerpatch/application/views/trac/categories.php
--- projectpier-0.8.0.3/application/views/trac/categories.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/views/trac/categories.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,32 @@
+
+
+
+
+
+ | Category |
+ Description |
+
+
+
+ | getName() ?> |
+ getShortDescription() ?> |
+
+
+
+
+
+
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/trac/edit.php projectpier-0.8.0.3-trackerpatch/application/views/trac/edit.php
--- projectpier-0.8.0.3/application/views/trac/edit.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/views/trac/edit.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,148 @@
+canEdit(logged_user());
+
+ // Set page title and set crumbs to index
+ $title = $canEdit ? 'edit tracTicket' : 'view tracTicket';
+ set_page_title(lang($title));
+ project_tabbed_navigation(PROJECT_TAB_TICKETS);
+ $crumbs = array(array(lang('tickets'), get_url('trac')));
+ if ($ticket->isClosed()) {
+ $crumbs[] = array(lang('closed tracTickets'), ProjectTickets::getIndexUrl(true));
+ }
+ $crumbs[] = array(lang($title));
+ project_crumbs($crumbs);
+
+ if ($ticket->canChangeStatus(logged_user())) {
+ if ($ticket->isClosed()) {
+ add_page_action(lang('open tracTicket'), $ticket->getOpenUrl());
+ } else {
+ add_page_action(lang('close tracTicket'), $ticket->getCloseUrl());
+ }
+ }
+ add_stylesheet_to_page('project/tickets.css');
+?>
+isPrivate()) { ?>
+
+
+getId()); ?>
+: getStatus()); ?>
+
+
+
+
+ canEdit(logged_user())) ?>
+
+
+
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+ | getType()) ?> |
+dataNeedsTranslation()) { ?>
+ getFromData()) ?> |
+ getToData()) ?> |
+
+ getFromData() ?> |
+ getToData() ?> |
+
+ getCreatedByDisplayName() ?> |
+ getCreatedOn()) ?> |
+
+
+
+
+
+
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/trac/edit_sidebar.php projectpier-0.8.0.3-trackerpatch/application/views/trac/edit_sidebar.php
--- projectpier-0.8.0.3/application/views/trac/edit_sidebar.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/views/trac/edit_sidebar.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,44 @@
+
+
+canUpdateOptions(logged_user())) { ?>
+
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/trac/index.php projectpier-0.8.0.3-trackerpatch/application/views/trac/index.php
--- projectpier-0.8.0.3/application/views/trac/index.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/views/trac/index.php Wed Aug 6 22:00:18 2008
@@ -0,0 +1,30 @@
+ '#PAGE#');
+ if ($closed) $options_pagination['closed'] = true;
+?>
+
+
+
+assign('tickets', $tickets);
+ $this->includeTemplate(get_template_path('view_tickets', 'trac'));
+?>
+
+
+
+
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/trac/index_sidebar.php projectpier-0.8.0.3-trackerpatch/application/views/trac/index_sidebar.php
--- projectpier-0.8.0.3/application/views/trac/index_sidebar.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/views/trac/index_sidebar.php Wed Aug 6 22:00:19 2008
@@ -0,0 +1,10 @@
+includeTemplate(get_template_path('trac_sidebar', 'trac')) ?>
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/trac/trac_sidebar.php projectpier-0.8.0.3-trackerpatch/application/views/trac/trac_sidebar.php
--- projectpier-0.8.0.3/application/views/trac/trac_sidebar.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/views/trac/trac_sidebar.php Wed Aug 6 22:00:19 2008
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/application/views/trac/view_tickets.php projectpier-0.8.0.3-trackerpatch/application/views/trac/view_tickets.php
--- projectpier-0.8.0.3/application/views/trac/view_tickets.php Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/application/views/trac/view_tickets.php Wed Aug 6 22:00:19 2008
@@ -0,0 +1,28 @@
+
+
+ |
+ |
+ |
+ |
+ |
+ |
+
+
+
+ | getId() ?> |
+ getSummary() ?> |
+ getType()) ?> |
+
+getCategory()) { ?>
+ getCategory()->getName()) ?>
+
+ |
+ getCreatedBy()->getDisplayName() ?> |
+
+getAssignedTo()) { ?>
+ getAssignedTo()->getObjectName()) ?>
+
+ |
+
+
+
\ No newline at end of file
diff -urN projectpier-0.8.0.3/language/en_us/actions.php projectpier-0.8.0.3-trackerpatch/language/en_us/actions.php
--- projectpier-0.8.0.3/language/en_us/actions.php Sun Feb 17 15:12:58 2008
+++ projectpier-0.8.0.3-trackerpatch/language/en_us/actions.php Wed Aug 6 22:00:19 2008
@@ -59,6 +59,20 @@
'mark task as completed' => 'Mark task as completed',
'mark task as open' => 'Mark task as open',
+ // Bug Trac
+ 'open tracTickets' => 'Open tickets',
+ 'closed tracTickets' => 'Closed tickets',
+ 'add tracTicket' => 'Add ticket',
+ 'edit tracTicket' => 'Edit ticket',
+ 'view tracTicket' => 'View ticket',
+ 'open tracTicket' => 'Open ticket',
+ 'close tracTicket' => 'Close ticket',
+ 'delete tracTicket' => 'Delete ticket',
+ 'add tracCategory' => 'Add category',
+ 'edit tracCategory' => 'Edit category',
+ 'tracCategories' => 'Trac categories',
+ 'update ticket options' => 'Update options',
+
// Milestone
'add milestone' => 'Add milestone',
'edit milestone' => 'Edit milestone',
diff -urN projectpier-0.8.0.3/language/en_us/emails.php projectpier-0.8.0.3-trackerpatch/language/en_us/emails.php
--- projectpier-0.8.0.3/language/en_us/emails.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/language/en_us/emails.php Wed Aug 6 22:00:19 2008
@@ -5,6 +5,7 @@
// Titles
'new message' => 'New message',
'new comment' => 'New comment',
+ 'new ticket' => 'New ticket',
'your account created' => 'Your account has been created',
'your password' => 'Your password',
'milestone assigned to you' => 'Milestone has been assigned to you',
@@ -20,6 +21,13 @@
'new comment posted' => 'New comment on "%s" has been posted',
'view new comment' => 'View that comment',
+
+ 'new ticket posted' => 'New ticket "%s" has been posted in "%s" project',
+ 'ticket edited' => 'Ticket "%s" has been edited in "%s" project',
+ 'ticket closed' => 'Ticket "%s" has been closed in "%s" project',
+ 'ticket opened' => 'Ticket "%s" has been opened in "%s" project',
+ 'attached files to ticket' => 'Some files have been attached to ticket "%s" in "%s" project',
+ 'view new ticket' => 'View that ticket',
'user created your account' => '%s created new account for you',
'visit and login' => 'Visit %s and login with',
diff -urN projectpier-0.8.0.3/language/en_us/errors.php projectpier-0.8.0.3-trackerpatch/language/en_us/errors.php
--- projectpier-0.8.0.3/language/en_us/errors.php Sun Feb 10 12:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/language/en_us/errors.php Wed Aug 6 22:00:19 2008
@@ -69,6 +69,13 @@
// Add task
'task text required' => 'Task text is required',
+ // Add category
+ 'category name required' => 'Category name value is required',
+
+ // Add ticket
+ 'ticket summary required' => 'Summary value is required',
+ 'ticket description required' => 'Description value is required',
+
// Add project form
'form name required' => 'Form name is required',
'form name unique' => 'Form name must be unique',
diff -urN projectpier-0.8.0.3/language/en_us/general.php projectpier-0.8.0.3-trackerpatch/language/en_us/general.php
--- projectpier-0.8.0.3/language/en_us/general.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/language/en_us/general.php Wed Aug 6 22:00:19 2008
@@ -101,6 +101,7 @@
'changelog' => 'Changelog',
'hint' => 'Hint',
'order' => 'Order',
+ 'private' => 'Private',
'project calendar' => '%s calendar',
'user calendar' => '%s\'s calendar',
diff -urN projectpier-0.8.0.3/language/en_us/messages.php projectpier-0.8.0.3-trackerpatch/language/en_us/messages.php
--- projectpier-0.8.0.3/language/en_us/messages.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/language/en_us/messages.php Wed Aug 6 22:30:29 2008
@@ -16,6 +16,7 @@
'no comments associated with object' => 'There are no comments posted for this object',
'no messages in project' => 'There are no messages in this project',
'no subscribers' => 'There are no users subscribed to this message',
+ 'no ticket subscribers' => 'There are no users subscribed to this ticket',
'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',
@@ -67,6 +68,12 @@
'no files to attach' => 'Please select files that need to be attached',
'no administration tools' => 'There are no registered administration tools in the database',
'administration tool dnx' => 'Administration tool "%s" does not exists',
+ 'ticket dnx' => 'Requested ticket does not exist',
+ 'no tickets in project' => 'There are no tickets in this project',
+ 'no my tickets' => 'There are no tickets assigned to you',
+ 'no changes in ticket' => 'There are no changes in this ticket',
+ 'category dnx' => 'Requested category does not exist',
+ 'no categories in project' => 'There are no categories in this project',
'about to delete' => 'You are about to delete',
// Success
@@ -99,6 +106,15 @@
'success open task' => 'Selected task has been reopened',
'success n tasks updated' => '%s tasks updated',
+ 'success add ticket' => 'Ticket \'%s\' has been added successfully',
+ 'success edit ticket' => 'Ticket \'%s\' has been updated successfully',
+ 'success deleted ticket' => 'Ticket \'%s\' and all of its comments has been deleted successfully',
+ 'success close ticket' => 'Selected ticket has been closed',
+ 'success open ticket' => 'Selected ticket has been reopened',
+ 'success add category' => 'Category \'%s\' has been added successfully',
+ 'success edit category' => 'Category \'%s\' has been updated successfully',
+ 'success deleted category' => 'Category \'%s\' and all of its comments has been deleted successfully',
+
'success add client' => 'Client company %s has been added',
'success edit client' => 'Client company %s has been updated',
'success delete client' => 'Client company %s has been deleted',
@@ -127,6 +143,9 @@
'success subscribe to message' => 'You have been successfully subscribed to this message',
'success unsubscribe to message' => 'You have been successfully unsubscribed from this message',
+ 'success subscribe to ticket' => 'You have been successfully subscribed to this ticket',
+ 'success unsubscribe to ticket' => 'You have been successfully unsubscribed from this ticket',
+
'success add project form' => 'Form \'%s\' has been added',
'success edit project form' => 'Form \'%s\' has been updated',
'success delete project form' => 'Form \'%s\' has been deleted',
@@ -159,10 +178,13 @@
'error delete owner company' => 'Owner company can\'t be deleted',
'error delete message' => 'Failed to delete selected message',
'error update message options' => 'Failed to update message options',
+ 'error update ticket options' => 'Failed to update ticket options',
'error delete comment' => 'Failed to delete selected comment',
'error delete milestone' => 'Failed to delete selected milestone',
'error complete task' => 'Failed to complete selected task',
'error open task' => 'Failed to reopen selected task',
+ 'error close ticket' => 'Failed to close selected ticket',
+ 'error open ticket' => 'Failed to reopen selected ticket',
'error upload file' => 'Failed to upload file',
'error delete project' => 'Failed to delete selected project',
'error complete project' => 'Failed to complete selected project',
@@ -183,6 +205,8 @@
'error delete company logo' => 'Failed to delete company logo',
'error subscribe to message' => 'Failed to subscribe to selected message',
'error unsubscribe to message' => 'Failed to unsubscribe from selected message',
+ 'error subscribe to ticket' => 'Failed to subscribe to selected ticket',
+ 'error unsubscribe to ticket' => 'Failed to unsubscribe from selected ticket',
'error add project form' => 'Failed to add project form',
'error submit project form' => 'Failed to submit project form',
'error delete folder' => 'Failed to delete selected folder',
@@ -190,6 +214,8 @@
'error delete file revision' => 'Failed to delete file revision',
'error delete task list' => 'Failed to delete selected task list',
'error delete task' => 'Failed to delete selected task',
+ 'error delete ticket' => 'Failed to delete selected ticket',
+ 'error delete category' => 'Failed to delete selected category',
'error check for upgrade' => 'Failed to check for a new version',
'error attach file' => 'Failed to attach file(s)',
'error detach file' => 'Failed to detach file(s)',
@@ -208,6 +234,8 @@
'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?',
+ 'confirm delete ticket' => 'Are you sure that you want to delete this ticket?',
+ 'confirm delete category' => 'Are you sure that you want to delete this category?',
'confirm delete project' => 'Are you sure that you want to delete this project and all related data (messages, tasks, milestones, files...)?',
'confirm complete project' => 'Are you sure that you want to mark this project as finished? All project actions will be locked',
'confirm open project' => 'Are you sure that you want to mark this project as open? This will unlock all project actions',
@@ -222,6 +250,7 @@
'confirm delete company logo' => 'Are you sure that you want to delete this logo?',
'confirm subscribe' => 'Are you sure that you want to subscribe to this message? You will receive an email everytime someone (except you) posts a comment on this message?',
'confirm unsubscribe' => 'Are you sure that you want to unsubscribe?',
+ 'confirm subscribe ticket' => 'Are you sure that you want to subscribe to this ticket? You will receive an email everytime someone (except you) makes a change or posts a comment on this ticket',
'confirm delete project form' => 'Are you sure that you want to delete this form?',
'confirm delete folder' => 'Are you sure that you want to delete this folder?',
'confirm delete file' => 'Are you sure that you want to delete this file?',
@@ -258,6 +287,15 @@
'log delete projecttasks' => '\'%s\' deleted',
'log close projecttasks' => '\'%s\' closed',
'log open projecttasks' => '\'%s\' opened',
+
+ 'log add categories' => '\'%s\' added',
+ 'log edit categories' => '\'%s\' updated',
+ 'log delete categories' => '\'%s\' deleted',
+ 'log add projecttickets' => '\'%s\' added',
+ 'log edit projecttickets' => '\'%s\' updated',
+ 'log delete projecttickets' => '\'%s\' deleted',
+ 'log close projecttickets' => '\'%s\' closed',
+ 'log open projecttickets' => '\'%s\' opened',
'log add projectforms' => '\'%s\' added',
'log edit projectforms' => '\'%s\' updated',
diff -urN projectpier-0.8.0.3/language/en_us/objects.php projectpier-0.8.0.3-trackerpatch/language/en_us/objects.php
--- projectpier-0.8.0.3/language/en_us/objects.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/language/en_us/objects.php Wed Aug 6 22:00:19 2008
@@ -24,6 +24,8 @@
'tasks' => 'Tasks',
'task list' => 'Task list',
'task lists' => 'Task lists',
+ 'ticket' => 'Ticket',
+ 'tickets' => 'Tickets',
'tag' => 'Tag',
'tags' => 'Tags',
'attachment' => 'Attachment',
@@ -73,6 +75,7 @@
'private task list' => 'Private task lists',
'private comment' => 'Private comment',
'private file' => 'Private file',
+ 'private ticket' => 'Private ticket',
); // array
diff -urN projectpier-0.8.0.3/language/en_us/project_interface.php projectpier-0.8.0.3-trackerpatch/language/en_us/project_interface.php
--- projectpier-0.8.0.3/language/en_us/project_interface.php Sun Feb 10 11:45:08 2008
+++ projectpier-0.8.0.3-trackerpatch/language/en_us/project_interface.php Wed Aug 6 22:00:19 2008
@@ -58,6 +58,7 @@
'collapse additional text' => 'Collapse',
'email notification' => 'Email notification',
'email notification desc' => 'Notify selected people about this message via email',
+ 'email notification ticket desc' => 'Notify selected people about this ticket via email',
'attach existing file' => 'Attach existing file (from Files section)',
'upload and attach' => 'Upload new file and attach it to message',
@@ -65,12 +66,15 @@
'subscribers desc' => 'Subscribers will receive an email notification whenever someone (except themselves) posts a comment on this message',
'admins can post comments on locked objects desc' => 'Comments are locked, but you as administrator still have the permissions to post comments. Note that if you expect replies from your clients and non-admin users you need to unlock comments for this object (set "Enable comments" option to "Yes").',
+ 'subscribers ticket desc' => 'Subscribers will receive an email notification whenever someone (except themselves) makes a change or posts a comment on this ticket',
+
'all permissions' => 'All',
'can manage messages' => 'Manage messages',
'can manage tasks' => 'Manage tasks',
'can manage milestones' => 'Manage milestones',
'can upload files' => 'Upload files',
'can manage files' => 'Manage files',
+ 'can manage tickets' => 'Manage tickets',
'can assign to owners' => 'Assign tasks to members of owner company',
'can assign to other' => 'Assign tasks to members of other clients',
@@ -117,6 +121,30 @@
'admin notice comments disabled' => 'Comments are disabled for this object, but you as administrator still can comment. If you expect replies from other, non-admin users you should set value of Enable comments option to Yes.',
+ // Tickets
+ 'summary' => 'Summary',
+ 'category' => 'Category',
+ 'priority' => 'Priority',
+ 'assigned to' => 'Assigned to',
+ 'reported by' => 'Reported by',
+ 'closed' => 'Closed',
+ 'open' => 'Open',
+ 'critical' => 'Critical',
+ 'major' => 'Major',
+ 'minor' => 'Minor',
+ 'trivial' => 'Trivial',
+ 'defect' => 'Defect',
+ 'enhancement' => 'Enhancement',
+ 'feature request' => 'Feature',
+ 'legend' => 'Legend',
+ 'ticket #' => 'Ticket #%s',
+ 'updated on by' => '%s | %s | %s',
+ 'history' => 'Change history',
+ 'field' => 'Field',
+ 'old value' => 'Old value',
+ 'new value' => 'New value',
+ 'change date' => 'Change date',
+
// iCal
'icalendar' => 'iCalendar',
'icalendar subscribe' => 'iCalendar',
@@ -141,6 +169,7 @@
'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',
+ 'private ticket desc' => 'Private tickets are visible only to owner company members. Members of client companies will not be able to see them.',
); // array
diff -urN projectpier-0.8.0.3/language/en_us/site_interface.php projectpier-0.8.0.3-trackerpatch/language/en_us/site_interface.php
--- projectpier-0.8.0.3/language/en_us/site_interface.php Tue Jul 22 16:18:54 2008
+++ projectpier-0.8.0.3-trackerpatch/language/en_us/site_interface.php Wed Aug 6 22:00:19 2008
@@ -14,6 +14,9 @@
'my tasks' => 'My tasks',
'welcome back' => 'Welcome back %s',
+ // Bug Trac
+ 'my tickets' => 'My tickets',
+
'online users' => 'Online users',
'online users desc' => 'Users who were active in last 15 minutes:',
diff -urN projectpier-0.8.0.3/public/assets/themes/acClassic/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/acClassic/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/acClassic/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/acClassic/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/assets/themes/acSimple/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/acSimple/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/acSimple/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/acSimple/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/assets/themes/azul/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/azul/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/azul/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/azul/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/assets/themes/basic-aqua/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/basic-aqua/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/basic-aqua/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/basic-aqua/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/assets/themes/basic-orange/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/basic-orange/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/basic-orange/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/basic-orange/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/assets/themes/default/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/default/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/default/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/default/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/assets/themes/ebrentnelson/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/ebrentnelson/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/ebrentnelson/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/ebrentnelson/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/assets/themes/goCollab/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/goCollab/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/goCollab/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/goCollab/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/assets/themes/goCollab_Monochrome/stylesheets/project/tickets.css projectpier-0.8.0.3-trackerpatch/public/assets/themes/goCollab_Monochrome/stylesheets/project/tickets.css
--- projectpier-0.8.0.3/public/assets/themes/goCollab_Monochrome/stylesheets/project/tickets.css Thu Jan 1 03:00:00 1970
+++ projectpier-0.8.0.3-trackerpatch/public/assets/themes/goCollab_Monochrome/stylesheets/project/tickets.css Wed Aug 6 22:00:31 2008
@@ -0,0 +1,40 @@
+/** Tickets display **/
+
+#tickets .critical, #tickets_legend .critical {
+ background-color: #ffbaba;
+}
+
+#tickets .major, #tickets_legend .major {
+ background-color: #fcffb1;
+}
+
+#tickets .minor, #tickets_legend .minor {
+ background-color: #d6e7ff;
+}
+
+#tickets .trivial, #tickets_legend .trivial {
+ background-color: #ffffff;
+}
+
+#tickets_legend {
+ width: 120px;
+}
+
+#tickets_legend .legend {
+ border: 1px solid #000000;
+ padding: 2px;
+ margin-bottom: 2px;
+}
+
+/** Ticket display */
+#ticket {
+ background: #ffd;
+ border: 1px outset #996;
+ margin-top: 1em;
+ padding: .5em 1em;
+ position: relative;
+}
+
+#ticket table.properties {
+ width: 100%;
+}
diff -urN projectpier-0.8.0.3/public/install/installation/templates/sql/mysql_schema.php projectpier-0.8.0.3-trackerpatch/public/install/installation/templates/sql/mysql_schema.php
--- projectpier-0.8.0.3/public/install/installation/templates/sql/mysql_schema.php Mon Apr 28 15:06:10 2008
+++ projectpier-0.8.0.3-trackerpatch/public/install/installation/templates/sql/mysql_schema.php Wed Aug 6 22:00:31 2008
@@ -142,6 +142,14 @@
PRIMARY KEY (`message_id`,`user_id`)
) ENGINE=InnoDB ;
+CREATE TABLE `project_categories` (
+ `id` int(10) unsigned NOT NULL auto_increment,
+ `project_id` int(10) unsigned NOT NULL default '0',
+ `name` varchar(50) NOT NULL default '',
+ `description` varchar(255) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB ;
+
CREATE TABLE `project_companies` (
`project_id` int(10) unsigned NOT NULL default '0',
`company_id` smallint(5) unsigned NOT NULL default '0',
@@ -299,6 +307,30 @@
KEY `order` (`order`)
) ENGINE=InnoDB ;
+CREATE TABLE `project_tickets` (
+ `id` int(10) unsigned NOT NULL auto_increment,
+ `project_id` int(10) unsigned NOT NULL default '0',
+ `category_id` int(10) unsigned default NULL,
+ `assigned_to_company_id` smallint(5) unsigned default NULL,
+ `assigned_to_user_id` int(10) unsigned default NULL,
+ `summary` varchar(200) NOT NULL default '',
+ `type` enum('defect','enhancement','feature request') NOT NULL default 'defect',
+ `description` text ,
+ `priority` enum('critical','major','minor','trivial') NOT NULL default 'major',
+ `is_private` tinyint(1) NOT NULL default '0',
+ `closed_on` datetime NOT NULL default '0000-00-00 00:00:00',
+ `closed_by_id` int(10) default NULL,
+ `created_on` datetime NOT NULL default '0000-00-00 00:00:00',
+ `created_by_id` int(10) unsigned default NULL,
+ `updated_on` datetime NOT NULL default '0000-00-00 00:00:00',
+ `updated_by_id` int(10) default NULL,
+ `updated` enum('settings','comment','attachment','open','closed') default NULL,
+ PRIMARY KEY (`id`),
+ KEY `created_on` (`created_on`),
+ KEY `closed_on` (`closed_on`),
+ KEY `project_id` (`project_id`)
+) ENGINE=InnoDB ;
+
CREATE TABLE `project_users` (
`project_id` int(10) unsigned NOT NULL default '0',
`user_id` int(10) unsigned NOT NULL default '0',
@@ -309,6 +341,7 @@
`can_manage_milestones` tinyint(1) unsigned default '0',
`can_upload_files` tinyint(1) unsigned default '0',
`can_manage_files` tinyint(1) unsigned default '0',
+ `can_manage_tickets` tinyint(1) unsigned default '0',
`can_assign_to_owners` tinyint(1) unsigned NOT NULL default '0',
`can_assign_to_other` tinyint(1) unsigned NOT NULL default '0',
PRIMARY KEY (`project_id`,`user_id`)
@@ -354,6 +387,25 @@
KEY `project_id` (`project_id`),
KEY `tag` (`tag`),
KEY `object_id` (`rel_object_id`,`rel_object_manager`)
+) ENGINE=InnoDB ;
+
+CREATE TABLE `ticket_changes` (
+ `id` int(11) unsigned NOT NULL auto_increment,
+ `ticket_id` int(11) unsigned NOT NULL default '0',
+ `type` enum('status','priority','assigned to','summary','category','type','private','comment','attachment') NOT NULL,
+ `from_data` varchar(255) NOT NULL default '',
+ `to_data` varchar(255) NOT NULL default '',
+ `created_on` datetime NOT NULL default '0000-00-00 00:00:00',
+ `created_by_id` int(10) default NULL,
+ PRIMARY KEY (`id`),
+ KEY `created_on` (`created_on`),
+ KEY `ticket_id` (`ticket_id`)
+) ENGINE=InnoDB ;
+
+CREATE TABLE `ticket_subscriptions` (
+ `ticket_id` int(10) unsigned NOT NULL default '0',
+ `user_id` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`ticket_id`,`user_id`)
) ENGINE=InnoDB ;
CREATE TABLE `user_im_values` (