requireLogin(); $filter = $f3->get('GET.status'); // retrieve tickets $ticket_mapper = new Ticket($this->getDB()); if($filter){ $tickets = $ticket_mapper->findFiltered($filter); } else { $tickets = $ticket_mapper->findAll(); } // render $this->renderView('views/ticket/index.html', ['tickets' => $tickets] ); $f3->clear('SESSION.error'); } // view a single ticket // TODO_PROJECTS: show a link back to the related project public function view($f3){ $this->requireLogin(); $ticket_id = $f3->get('PARAMS.id'); $ticket_mapper = new Ticket($this->getDB()); $ticket = $ticket_mapper->findById($ticket_id); if(!$ticket){ $this->f3->set('SESSION.error', 'Ticket not found'); $this->f3->reroute('/tickets'); return; } $assigned_user = $ticket->getAssignedUser(); $ticket_history = $ticket->getHistory(); $map_statuses = array_column((new TicketStatus($this->getDB()))->findAll(), 'name', 'id'); $map_priorities = array_column((new TicketStatus($this->getDB()))->findAll(), 'name', 'id'); $map_users = array_column($this->getDB()->exec('SELECT id, display_name FROM users'), 'display_name', 'id'); // render $this->renderView('views/ticket/view.html', [ 'ticket' => $ticket, 'assigned_user' => $assigned_user, 'attachments' => $ticket->attachments(), 'comments' => $ticket->comments(), 'parent_tickets' => $ticket->getParentTickets(), 'child_tickets' => $ticket->getChildTickets(), 'ticket_meta' => $ticket->getMetaAssoc(), 'ticket_history' => $ticket_history, 'map' => [ 'statuses' => $map_statuses, 'priorities' => $map_priorities, 'users' => $map_users ] ]); } // show create form // TODO_PROJECTS: dropdown to associate ticket with project public function createForm($f3){ $db = $this->getDB(); $priorities = (new TicketPriority($db))->findAll(); $statuses = (new TicketStatus($db))->findAll(); $all_tags_model = new \Tag($this->getDB()); $all_tags = $all_tags_model->find([], ['order' => 'name ASC']); // get all tags // TODO: this needs moving into a model? $users = $this->getDB()->exec('SELECT id, username, display_name FROM users ORDER BY display_name ASC'); $users = array_merge([['id'=>'-1', 'display_name'=>'--']], $users); $this->requireLogin(); $this->renderView('views/ticket/create.html',[ 'priorities' => $priorities, 'statuses' => $statuses, 'users' => $users, 'all_tags' => $all_tags ]); } // handle POST // including custom forms public function create($f3){ $this->requireLogin(); $this->checkCSRF($f3, '/ticket/create'); $data = [ 'title' => $this->f3->get('POST.title'), 'created_at' => $this->f3->get('POST.created_at'), 'description' => $this->f3->get('POST.description'), 'priority_id' => $this->f3->get('POST.priority_id'), 'status_id' => $this->f3->get('POST.status_id'), 'created_by' => $this->f3->get('SESSION.user.id'), 'assigned_to' => $this->f3->get('POST.assigned_to') == '-1' ? null : $this->f3->get('POST.assigned_to') ]; $ticket_mapper = new Ticket($this->getDB()); $new_ticket_id = $ticket_mapper->createTicket($data); // custom field // $meta_keys = $this->f3->get('POST.meta_key'); // $meta_values = $this->f3->get('POST.meta_value'); // $meta_assoc = $ticket_mapper->assocMetaFromKeyValue($meta_keys, $meta_values); // $ticket_mapper->setCustomFields($meta_assoc); $new_ticket = $ticket_mapper->findById($new_ticket_id); if($new_ticket){ // TAG handling for create $posted_tags = $this->f3->get('POST.tags'); if(!empty($posted_tags) && is_array($posted_tags)){ $new_ticket->setTags($posted_tags); } } $this->f3->set('SESSION.message', 'Ticket #' . $new_ticket_id . ' created successfully.'); $this->f3->reroute('/ticket/' . $new_ticket_id); } // show edit form // including custom forms // TODO_PROJECTS: allow reasssigning or removing a project association public function editForm($f3) { $this->requireLogin(); $ticket_id = $f3->get('PARAMS.id'); $ticket_mapper = new Ticket($this->getDB()); $ticket = $ticket_mapper->findById($ticket_id); if(!$ticket){ $this->f3->set('SESSION.error', 'Ticket not found.'); $this->f3->reroute('/tickets'); } // $f3->set('js', 'markdown_preview.js'); // dropdowns $priorities = (new TicketPriority($this->getDB()))->findAll(); $statuses = (new TicketStatus($this->getDB()))->findAll(); $all_tags_model = new \Tag($this->getDB()); $all_tags = $all_tags_model->find([], ['order' => 'name ASC']); // TODO: this needs moving into a model? $users = $this->getDB()->exec('SELECT id, username, display_name FROM users ORDER BY display_name ASC'); $users = array_merge([['id'=>'-1', 'display_name'=>'--']], $users); // paradox - empty($ticket->tags) was returning true, when there were items present $current_ticket_tag_ids = []; if(count($ticket->tags) > 0){ foreach($ticket->tags as $current_tag_data){ $current_ticket_tag_ids[] = $current_tag_data['id']; } } $this->renderView('views/ticket/edit.html',[ 'ticket' => $ticket, 'ticket_meta' => $ticket->getMeta(), 'priorities' => $priorities, 'statuses' => $statuses, 'users' => $users, 'all_tags' => $all_tags, 'current_ticket_tag_ids' => $current_ticket_tag_ids ] ); return; } // process edit POST TODO: if assigned or admin public function update($f3) { $this->requireLogin(); $this->checkCSRF($f3, '/ticket/create'); $ticket_id = $f3->get('PARAMS.id'); $ticket_mapper = new Ticket($this->getDB()); $ticket = $ticket_mapper->findById($ticket_id); if(!$ticket){ $f3->set('SESSION.error', 'Ticket not found.'); $f3->reroute('/tickets'); } $data = [ 'title' => $f3->get('POST.title'), 'created_at' => $f3->get('POST.created_at'), 'description' => $f3->get('POST.description'), 'priority_id' => $f3->get('POST.priority_id'), 'status_id' => $f3->get('POST.status_id'), 'updated_by' => $f3->get('SESSION.user.id') , 'assigned_to' => $f3->get('POST.assigned_to') == -1 ? null : $f3->get('POST.assigned_to') ]; $ticket->updateTicket($data); // deal with meta data / custom fields // $meta_keys = $this->f3->get('POST.meta_key'); // $meta_values = $this->f3->get('POST.meta_value'); // $meta_assoc = $ticket->assocMetaFromKeyValue($meta_keys, $meta_values); // $ticket->setCustomFields($meta_assoc); $posted_tags = $f3->get('POST.tags'); if(is_array($posted_tags)){ $ticket->setTags($posted_tags); } elseif (empty($posted_tags)){ $ticket->setTags([]); } $f3->set('SESSION.message', 'Ticket #' . $ticket_id . ' updated successfully.') ; $f3->reroute('/ticket/' . $ticket_id); } // subtask public function addSubtask($f3){ $this->requireLogin(); $this->checkCSRF($f3, '/ticket/create'); $parent_id = (int) $f3->get('PARAMS.id'); $child_id = (int) $f3->get('POST.child_ticket_id'); $ticket_mapper = new Ticket($this->getDB()); $ticket = $ticket_mapper->findById($parent_id); if(!$ticket){ $this->f3->set('SESSION.error', 'Parent Ticket not found'); $this->f3->reroute('/tickets'); } $ticket->addChildTicket($child_id); $this->f3->reroute('/ticket/' . $parent_id); } public function delete(): void { $this->requireLogin(); $ticket_id = (int)$this->f3->get('PARAMS.id'); $ticket_mapper = new Ticket($this->getDB()); $ticket = $ticket_mapper->findById($ticket_id); if(!$ticket){ $this->f3->set('SESSION.error', 'Ticket not found'); $this->f3->reroute('/tickets'); } $ticket->softDelete(); $this->f3->reroute('/tickets'); } }