diff options
Diffstat (limited to 'controllers')
-rw-r--r-- | controllers/.htaccess | 1 | ||||
-rw-r--r-- | controllers/app.php | 16 | ||||
-rw-r--r-- | controllers/base.php | 79 | ||||
-rw-r--r-- | controllers/board.php | 185 | ||||
-rw-r--r-- | controllers/config.php | 70 | ||||
-rw-r--r-- | controllers/project.php | 162 | ||||
-rw-r--r-- | controllers/task.php | 201 | ||||
-rw-r--r-- | controllers/user.php | 198 |
8 files changed, 912 insertions, 0 deletions
diff --git a/controllers/.htaccess b/controllers/.htaccess new file mode 100644 index 00000000..14249c50 --- /dev/null +++ b/controllers/.htaccess @@ -0,0 +1 @@ +Deny from all
\ No newline at end of file diff --git a/controllers/app.php b/controllers/app.php new file mode 100644 index 00000000..981abbbe --- /dev/null +++ b/controllers/app.php @@ -0,0 +1,16 @@ +<?php + +namespace Controller; + +class App extends Base +{ + public function index() + { + if ($this->project->countByStatus(\Model\Project::ACTIVE)) { + $this->response->redirect('?controller=board'); + } + else { + $this->redirectNoProject(); + } + } +} diff --git a/controllers/base.php b/controllers/base.php new file mode 100644 index 00000000..f0ae5bd2 --- /dev/null +++ b/controllers/base.php @@ -0,0 +1,79 @@ +<?php + +namespace Controller; + +require __DIR__.'/../lib/request.php'; +require __DIR__.'/../lib/response.php'; +require __DIR__.'/../lib/session.php'; +require __DIR__.'/../lib/template.php'; +require __DIR__.'/../lib/helper.php'; +require __DIR__.'/../lib/translator.php'; +require __DIR__.'/../models/base.php'; +require __DIR__.'/../models/config.php'; +require __DIR__.'/../models/user.php'; +require __DIR__.'/../models/project.php'; +require __DIR__.'/../models/task.php'; +require __DIR__.'/../models/board.php'; + +abstract class Base +{ + protected $request; + protected $response; + protected $session; + protected $template; + protected $user; + protected $project; + protected $task; + protected $board; + protected $config; + + public function __construct() + { + $this->request = new \Request; + $this->response = new \Response; + $this->session = new \Session; + $this->template = new \Template; + $this->config = new \Model\Config; + $this->user = new \Model\User; + $this->project = new \Model\Project; + $this->task = new \Model\Task; + $this->board = new \Model\Board; + } + + public function beforeAction($controller, $action) + { + $this->session->open(); + + $public = array( + 'user' => array('login', 'check'), + 'task' => array('add'), + ); + + if (! isset($_SESSION['user']) && ! isset($public[$controller]) && ! in_array($action, $public[$controller])) { + $this->response->redirect('?controller=user&action=login'); + } + + // Load translations + $language = $this->config->get('language', 'en_US'); + if ($language !== 'en_US') \Translator\load($language); + + $this->response->csp(); + $this->response->nosniff(); + $this->response->xss(); + $this->response->hsts(); + $this->response->xframe(); + } + + public function checkPermissions() + { + if ($_SESSION['user']['is_admin'] == 0) { + $this->response->redirect('?controller=user&action=forbidden'); + } + } + + public function redirectNoProject() + { + $this->session->flash(t('There is no active project, the first step is to create a new project.')); + $this->response->redirect('?controller=project&action=create'); + } +} diff --git a/controllers/board.php b/controllers/board.php new file mode 100644 index 00000000..ec32e8a0 --- /dev/null +++ b/controllers/board.php @@ -0,0 +1,185 @@ +<?php + +namespace Controller; + +class Board extends Base +{ + // Display current board + public function index() + { + $projects = $this->project->getListByStatus(\Model\Project::ACTIVE); + + if (! count($projects)) { + $this->redirectNoProject(); + } + else if (! empty($_SESSION['user']['default_project_id']) && isset($projects[$_SESSION['user']['default_project_id']])) { + $project_id = $_SESSION['user']['default_project_id']; + $project_name = $projects[$_SESSION['user']['default_project_id']]; + } + else { + list($project_id, $project_name) = each($projects); + } + + $this->response->html($this->template->layout('board_index', array( + 'projects' => $projects, + 'current_project_id' => $project_id, + 'current_project_name' => $project_name, + 'columns' => $this->board->get($project_id), + 'menu' => 'boards', + 'title' => $project_name + ))); + } + + // Show a board + public function show() + { + $projects = $this->project->getListByStatus(\Model\Project::ACTIVE); + $project_id = $this->request->getIntegerParam('project_id'); + $project_name = $projects[$project_id]; + + $this->response->html($this->template->layout('board_index', array( + 'projects' => $projects, + 'current_project_id' => $project_id, + 'current_project_name' => $project_name, + 'columns' => $this->board->get($project_id), + 'menu' => 'boards', + 'title' => $project_name + ))); + } + + // Display a form to edit a board + public function edit() + { + $this->checkPermissions(); + + $project_id = $this->request->getIntegerParam('project_id'); + $project = $this->project->get($project_id); + $columns = $this->board->getColumnsList($project_id); + $values = array(); + + foreach ($columns as $column_id => $column_title) { + $values['title['.$column_id.']'] = $column_title; + } + + $this->response->html($this->template->layout('board_edit', array( + 'errors' => array(), + 'values' => $values + array('project_id' => $project_id), + 'columns' => $columns, + 'project' => $project, + 'menu' => 'projects', + 'title' => t('Edit board') + ))); + } + + // Validate and update a board + public function update() + { + $this->checkPermissions(); + + $project_id = $this->request->getIntegerParam('project_id'); + $project = $this->project->get($project_id); + $columns = $this->board->getColumnsList($project_id); + $data = $this->request->getValues(); + $values = array(); + + foreach ($columns as $column_id => $column_title) { + $values['title['.$column_id.']'] = isset($data['title'][$column_id]) ? $data['title'][$column_id] : ''; + } + + list($valid, $errors) = $this->board->validateModification($columns, $values); + + if ($valid) { + + if ($this->board->update($data['title'])) { + $this->session->flash(t('Board updated successfully.')); + $this->response->redirect('?controller=board&action=edit&project_id='.$project['id']); + } + else { + $this->session->flashError(t('Unable to update this board.')); + } + } + + $this->response->html($this->template->layout('board_edit', array( + 'errors' => $errors, + 'values' => $values + array('project_id' => $project_id), + 'columns' => $columns, + 'project' => $project, + 'menu' => 'projects', + 'title' => t('Edit board') + ))); + } + + // Validate and add a new column + public function add() + { + $this->checkPermissions(); + + $project_id = $this->request->getIntegerParam('project_id'); + $project = $this->project->get($project_id); + $columns = $this->board->getColumnsList($project_id); + $data = $this->request->getValues(); + $values = array(); + + foreach ($columns as $column_id => $column_title) { + $values['title['.$column_id.']'] = $column_title; + } + + list($valid, $errors) = $this->board->validateCreation($data); + + if ($valid) { + + if ($this->board->add($data)) { + $this->session->flash(t('Board updated successfully.')); + $this->response->redirect('?controller=board&action=edit&project_id='.$project['id']); + } + else { + $this->session->flashError(t('Unable to update this board.')); + } + } + + $this->response->html($this->template->layout('board_edit', array( + 'errors' => $errors, + 'values' => $values + $data, + 'columns' => $columns, + 'project' => $project, + 'menu' => 'projects', + 'title' => t('Edit board') + ))); + } + + // Confirmation dialog before removing a column + public function confirm() + { + $this->checkPermissions(); + + $this->response->html($this->template->layout('board_remove', array( + 'column' => $this->board->getColumn($this->request->getIntegerParam('column_id')), + 'menu' => 'projects', + 'title' => t('Remove a column from a board') + ))); + } + + // Remove a column + public function remove() + { + $this->checkPermissions(); + + $column = $this->board->getColumn($this->request->getIntegerParam('column_id')); + + if ($column && $this->board->removeColumn($column['id'])) { + $this->session->flash(t('Column removed successfully.')); + } else { + $this->session->flashError(t('Unable to remove this column.')); + } + + $this->response->redirect('?controller=board&action=edit&project_id='.$column['project_id']); + } + + // Save the board (Ajax request made by drag and drop) + public function save() + { + $this->response->json(array( + 'result' => $this->board->saveTasksPosition($this->request->getValues()) + )); + } +} diff --git a/controllers/config.php b/controllers/config.php new file mode 100644 index 00000000..96a6a085 --- /dev/null +++ b/controllers/config.php @@ -0,0 +1,70 @@ +<?php + +namespace Controller; + +class Config extends Base +{ + // Settings page + public function index() + { + $this->response->html($this->template->layout('config_index', array( + 'db_size' => $this->config->getDatabaseSize(), + 'user' => $_SESSION['user'], + 'projects' => $this->project->getList(), + 'languages' => $this->config->getLanguages(), + 'values' => $this->config->getAll(), + 'errors' => array(), + 'menu' => 'config', + 'title' => t('Settings') + ))); + } + + // Validate and save settings + public function save() + { + $this->checkPermissions(); + + $values = $this->request->getValues(); + list($valid, $errors) = $this->config->validateModification($values); + + if ($valid) { + + if ($this->config->save($values)) { + $this->config->reload(); + $this->session->flash(t('Settings saved successfully.')); + $this->response->redirect('?controller=config'); + } + else { + $this->session->flashError(t('Unable to save your settings.')); + } + } + + $this->response->html($this->template->layout('config_index', array( + 'db_size' => $this->config->getDatabaseSize(), + 'user' => $_SESSION['user'], + 'projects' => $this->project->getList(), + 'languages' => $this->config->getLanguages(), + 'values' => $values, + 'errors' => $errors, + 'menu' => 'config', + 'title' => t('Settings') + ))); + } + + // Download the database + public function downloadDb() + { + $this->checkPermissions(); + $this->response->forceDownload('db.sqlite.gz'); + $this->response->binary($this->config->downloadDatabase()); + } + + // Optimize the database + public function optimizeDb() + { + $this->checkPermissions(); + $this->config->optimizeDatabase(); + $this->session->flash(t('Database optimization done.')); + $this->response->redirect('?controller=config'); + } +} diff --git a/controllers/project.php b/controllers/project.php new file mode 100644 index 00000000..a384be67 --- /dev/null +++ b/controllers/project.php @@ -0,0 +1,162 @@ +<?php + +namespace Controller; + +class Project extends Base +{ + // List of projects + public function index() + { + $projects = $this->project->getAll(true); + $nb_projects = count($projects); + + $this->response->html($this->template->layout('project_index', array( + 'projects' => $projects, + 'nb_projects' => $nb_projects, + 'menu' => 'projects', + 'title' => t('Projects').' ('.$nb_projects.')' + ))); + } + + // Display a form to create a new project + public function create() + { + $this->checkPermissions(); + + $this->response->html($this->template->layout('project_new', array( + 'errors' => array(), + 'values' => array(), + 'menu' => 'projects', + 'title' => t('New project') + ))); + } + + // Validate and save a new project + public function save() + { + $this->checkPermissions(); + + $values = $this->request->getValues(); + list($valid, $errors) = $this->project->validateCreation($values); + + if ($valid) { + + if ($this->project->create($values)) { + $this->session->flash(t('Your project have been created successfully.')); + $this->response->redirect('?controller=project'); + } + else { + $this->session->flashError(t('Unable to create your project.')); + } + } + + $this->response->html($this->template->layout('project_new', array( + 'errors' => $errors, + 'values' => $values, + 'menu' => 'projects', + 'title' => t('New Project') + ))); + } + + // Display a form to edit a project + public function edit() + { + $this->checkPermissions(); + + $project = $this->project->get($this->request->getIntegerParam('project_id')); + + $this->response->html($this->template->layout('project_edit', array( + 'errors' => array(), + 'values' => $project, + 'menu' => 'projects', + 'title' => t('Edit project') + ))); + } + + // Validate and update a project + public function update() + { + $this->checkPermissions(); + + $values = $this->request->getValues() + array('is_active' => 0); + list($valid, $errors) = $this->project->validateModification($values); + + if ($valid) { + + if ($this->project->update($values)) { + $this->session->flash(t('Project updated successfully.')); + $this->response->redirect('?controller=project'); + } + else { + $this->session->flashError(t('Unable to update this project.')); + } + } + + $this->response->html($this->template->layout('project_edit', array( + 'errors' => $errors, + 'values' => $values, + 'menu' => 'projects', + 'title' => t('Edit Project') + ))); + } + + // Confirmation dialog before to remove a project + public function confirm() + { + $this->checkPermissions(); + + $this->response->html($this->template->layout('project_remove', array( + 'project' => $this->project->get($this->request->getIntegerParam('project_id')), + 'menu' => 'projects', + 'title' => t('Remove project') + ))); + } + + // Remove a project + public function remove() + { + $this->checkPermissions(); + + $project_id = $this->request->getIntegerParam('project_id'); + + if ($project_id && $this->project->remove($project_id)) { + $this->session->flash(t('Project removed successfully.')); + } else { + $this->session->flashError(t('Unable to remove this project.')); + } + + $this->response->redirect('?controller=project'); + } + + // Enable a project + public function enable() + { + $this->checkPermissions(); + + $project_id = $this->request->getIntegerParam('project_id'); + + if ($project_id && $this->project->enable($project_id)) { + $this->session->flash(t('Project activated successfully.')); + } else { + $this->session->flashError(t('Unable to activate this project.')); + } + + $this->response->redirect('?controller=project'); + } + + // Disable a project + public function disable() + { + $this->checkPermissions(); + + $project_id = $this->request->getIntegerParam('project_id'); + + if ($project_id && $this->project->disable($project_id)) { + $this->session->flash(t('Project disabled successfully.')); + } else { + $this->session->flashError(t('Unable to disable this project.')); + } + + $this->response->redirect('?controller=project'); + } +} diff --git a/controllers/task.php b/controllers/task.php new file mode 100644 index 00000000..b022f37c --- /dev/null +++ b/controllers/task.php @@ -0,0 +1,201 @@ +<?php + +namespace Controller; + +class Task extends Base +{ + // Webhook to create a task (useful for external software) + public function add() + { + $token = $this->request->getStringParam('token'); + + if ($this->config->get('webhooks_token') !== $token) { + $this->response->text('Not Authorized', 401); + } + + $values = array( + 'title' => $this->request->getStringParam('title'), + 'description' => $this->request->getStringParam('description'), + 'color_id' => $this->request->getStringParam('color_id'), + 'project_id' => $this->request->getIntegerParam('project_id'), + 'owner_id' => $this->request->getIntegerParam('owner_id'), + 'column_id' => $this->request->getIntegerParam('column_id'), + ); + + list($valid,) = $this->task->validateCreation($values); + + if ($valid && $this->task->create($values)) { + $this->response->text('OK'); + } + + $this->response->text('FAILED'); + } + + // Show a task + public function show() + { + $task = $this->task->getById($this->request->getIntegerParam('task_id'), true); + + $this->response->html($this->template->layout('task_show', array( + 'task' => $task, + 'columns_list' => $this->board->getColumnsList($task['project_id']), + 'colors_list' => $this->task->getColors(), + 'menu' => 'tasks', + 'title' => $task['title'] + ))); + } + + // Display a form to create a new task + public function create() + { + $project_id = $this->request->getIntegerParam('project_id'); + + $this->response->html($this->template->layout('task_new', array( + 'errors' => array(), + 'values' => array( + 'project_id' => $project_id, + 'column_id' => $this->request->getIntegerParam('column_id'), + 'color_id' => $this->request->getStringParam('color_id'), + 'owner_id' => $this->request->getIntegerParam('owner_id'), + 'another_task' => $this->request->getIntegerParam('another_task'), + ), + 'projects_list' => $this->project->getListByStatus(\Model\Project::ACTIVE), + 'columns_list' => $this->board->getColumnsList($project_id), + 'users_list' => $this->user->getList(), + 'colors_list' => $this->task->getColors(), + 'menu' => 'tasks', + 'title' => t('New task') + ))); + } + + // Validate and save a new task + public function save() + { + $values = $this->request->getValues(); + list($valid, $errors) = $this->task->validateCreation($values); + + if ($valid) { + + if ($this->task->create($values)) { + $this->session->flash(t('Task created successfully.')); + + if (isset($values['another_task']) && $values['another_task'] == 1) { + unset($values['title']); + unset($values['description']); + $this->response->redirect('?controller=task&action=create&'.http_build_query($values)); + } + else { + $this->response->redirect('?controller=board&action=show&project_id='.$values['project_id']); + } + } + else { + $this->session->flashError(t('Unable to create your task.')); + } + } + + $this->response->html($this->template->layout('task_new', array( + 'errors' => $errors, + 'values' => $values, + 'projects_list' => $this->project->getListByStatus(\Model\Project::ACTIVE), + 'columns_list' => $this->board->getColumnsList($values['project_id']), + 'users_list' => $this->user->getList(), + 'colors_list' => $this->task->getColors(), + 'menu' => 'tasks', + 'title' => t('New task') + ))); + } + + // Display a form to edit a task + public function edit() + { + $task = $this->task->getById($this->request->getIntegerParam('task_id')); + + $this->response->html($this->template->layout('task_edit', array( + 'errors' => array(), + 'values' => $task, + 'projects_list' => $this->project->getListByStatus(\Model\Project::ACTIVE), + 'columns_list' => $this->board->getColumnsList($task['project_id']), + 'users_list' => $this->user->getList(), + 'colors_list' => $this->task->getColors(), + 'menu' => 'tasks', + 'title' => t('Edit a task') + ))); + } + + // Validate and update a task + public function update() + { + $values = $this->request->getValues(); + list($valid, $errors) = $this->task->validateModification($values); + + if ($valid) { + + if ($this->task->update($values)) { + $this->session->flash(t('Task updated successfully.')); + $this->response->redirect('?controller=task&action=show&task_id='.$values['id']); + } + else { + $this->session->flashError(t('Unable to update your task.')); + } + } + + $this->response->html($this->template->layout('task_edit', array( + 'errors' => $errors, + 'values' => $values, + 'projects_list' => $this->project->getListByStatus(\Model\Project::ACTIVE), + 'columns_list' => $this->board->getColumnsList($task['project_id']), + 'users_list' => $this->user->getList(), + 'colors_list' => $this->task->getColors(), + 'menu' => 'tasks', + 'title' => t('Edit a task') + ))); + } + + // Hide a task + public function close() + { + $task = $this->task->getById($this->request->getIntegerParam('task_id')); + + if ($task && $this->task->close($task['id'])) { + $this->session->flash(t('Task closed successfully.')); + } else { + $this->session->flashError(t('Unable to close this task.')); + } + + $this->response->redirect('?controller=board&action=show&project_id='.$task['project_id']); + } + + // Confirmation dialog before to close a task + public function confirmClose() + { + $this->response->html($this->template->layout('task_close', array( + 'task' => $this->task->getById($this->request->getIntegerParam('task_id')), + 'menu' => 'tasks', + 'title' => t('Close a task') + ))); + } + + // Open a task + public function open() + { + $task = $this->task->getById($this->request->getIntegerParam('task_id')); + + if ($task && $this->task->close($task['id'])) { + $this->session->flash(t('Task opened successfully.')); + } else { + $this->session->flashError(t('Unable to open this task.')); + } + + $this->response->redirect('?controller=board&action=show&project_id='.$task['project_id']); + } + + // Confirmation dialog before to open a task + public function confirmOpen() + { + $this->response->html($this->template->layout('task_open', array( + 'task' => $this->task->getById($this->request->getIntegerParam('task_id')), + 'menu' => 'tasks', + 'title' => t('Open a task') + ))); + } +} diff --git a/controllers/user.php b/controllers/user.php new file mode 100644 index 00000000..0fdd9d1e --- /dev/null +++ b/controllers/user.php @@ -0,0 +1,198 @@ +<?php + +namespace Controller; + +class User extends Base +{ + // Display access forbidden page + public function forbidden() + { + $this->response->html($this->template->layout('user_forbidden', array( + 'menu' => 'users', + 'title' => t('Access Forbidden') + ))); + } + + // Logout and destroy session + public function logout() + { + $this->session->close(); + $this->response->redirect('?controller=user&action=login'); + } + + // Display the form login + public function login() + { + if (isset($_SESSION['user'])) $this->response->redirect('?controller=app'); + + $this->response->html($this->template->layout('user_login', array( + 'errors' => array(), + 'values' => array(), + 'no_layout' => true, + 'title' => t('Login') + ))); + } + + // Check credentials + public function check() + { + $values = $this->request->getValues(); + list($valid, $errors) = $this->user->validateLogin($values); + + if ($valid) $this->response->redirect('?controller=app'); + + $this->response->html($this->template->layout('user_login', array( + 'errors' => $errors, + 'values' => $values, + 'no_layout' => true, + 'title' => t('Login') + ))); + } + + // List all users + public function index() + { + $users = $this->user->getAll(); + $nb_users = count($users); + + $this->response->html( + $this->template->layout('user_index', array( + 'projects' => $this->project->getList(), + 'users' => $users, + 'nb_users' => $nb_users, + 'menu' => 'users', + 'title' => t('Users').' ('.$nb_users.')' + ))); + } + + // Display a form to create a new user + public function create() + { + $this->checkPermissions(); + + $this->response->html($this->template->layout('user_new', array( + 'projects' => $this->project->getList(), + 'errors' => array(), + 'values' => array(), + 'menu' => 'users', + 'title' => t('New user') + ))); + } + + // Validate and save a new user + public function save() + { + $this->checkPermissions(); + + $values = $this->request->getValues(); + list($valid, $errors) = $this->user->validateCreation($values); + + if ($valid) { + + if ($this->user->create($values)) { + $this->session->flash(t('User created successfully.')); + $this->response->redirect('?controller=user'); + } + else { + $this->session->flashError(t('Unable to create your user.')); + } + } + + $this->response->html($this->template->layout('user_new', array( + 'projects' => $this->project->getList(), + 'errors' => $errors, + 'values' => $values, + 'menu' => 'users', + 'title' => t('New user') + ))); + } + + // Display a form to edit a user + public function edit() + { + $user = $this->user->getById($this->request->getIntegerParam('user_id')); + + if (! $_SESSION['user']['is_admin'] && $_SESSION['user']['id'] != $user['id']) { + $this->response->redirect('?controller=user&action=forbidden'); + } + + if (! empty($user)) unset($user['password']); + + $this->response->html($this->template->layout('user_edit', array( + 'projects' => $this->project->getList(), + 'errors' => array(), + 'values' => $user, + 'menu' => 'users', + 'title' => t('Edit user') + ))); + } + + // Validate and update a user + public function update() + { + $values = $this->request->getValues(); + + if ($_SESSION['user']['is_admin'] == 1) { + $values += array('is_admin' => 0); + } + else { + + if ($_SESSION['user']['id'] != $values['id']) { + $this->response->redirect('?controller=user&action=forbidden'); + } + + if (isset($values['is_admin'])) { + unset($values['is_admin']); // Regular users can't be admin + } + } + + list($valid, $errors) = $this->user->validateModification($values); + + if ($valid) { + + if ($this->user->update($values)) { + $this->session->flash(t('User updated successfully.')); + $this->response->redirect('?controller=user'); + } + else { + $this->session->flashError(t('Unable to update your user.')); + } + } + + $this->response->html($this->template->layout('user_edit', array( + 'projects' => $this->project->getList(), + 'errors' => $errors, + 'values' => $values, + 'menu' => 'users', + 'title' => t('Edit user') + ))); + } + + // Confirmation dialog before to remove a user + public function confirm() + { + $this->checkPermissions(); + + $this->response->html($this->template->layout('user_remove', array( + 'user' => $this->user->getById($this->request->getIntegerParam('user_id')), + 'menu' => 'users', + 'title' => t('Remove user') + ))); + } + + // Remove a user + public function remove() + { + $this->checkPermissions(); + + $user_id = $this->request->getIntegerParam('user_id'); + + if ($user_id && $this->user->remove($user_id)) { + $this->session->flash(t('User removed successfully.')); + } else { + $this->session->flashError(t('Unable to remove this user.')); + } + + $this->response->redirect('?controller=user'); + } +} |