summaryrefslogtreecommitdiff
path: root/app/Controller
diff options
context:
space:
mode:
Diffstat (limited to 'app/Controller')
-rw-r--r--app/Controller/ActionController.php (renamed from app/Controller/Action.php)28
-rw-r--r--app/Controller/ActionCreationController.php (renamed from app/Controller/ActionCreation.php)23
-rw-r--r--app/Controller/ActivityController.php (renamed from app/Controller/Activity.php)8
-rw-r--r--app/Controller/AnalyticController.php (renamed from app/Controller/Analytic.php)20
-rw-r--r--app/Controller/AppController.php46
-rw-r--r--app/Controller/AuthController.php (renamed from app/Controller/Auth.php)36
-rw-r--r--app/Controller/AvatarFileController.php (renamed from app/Controller/AvatarFile.php)20
-rw-r--r--app/Controller/Base.php290
-rw-r--r--app/Controller/BaseController.php158
-rw-r--r--app/Controller/Board.php192
-rw-r--r--app/Controller/BoardAjaxController.php140
-rw-r--r--app/Controller/BoardPopover.php135
-rw-r--r--app/Controller/BoardPopoverController.php47
-rw-r--r--app/Controller/BoardTooltipController.php (renamed from app/Controller/BoardTooltip.php)22
-rw-r--r--app/Controller/BoardViewController.php65
-rw-r--r--app/Controller/CalendarController.php (renamed from app/Controller/Calendar.php)14
-rw-r--r--app/Controller/CaptchaController.php (renamed from app/Controller/Captcha.php)6
-rw-r--r--app/Controller/CategoryController.php (renamed from app/Controller/Category.php)47
-rw-r--r--app/Controller/ColumnController.php (renamed from app/Controller/Column.php)41
-rw-r--r--app/Controller/CommentController.php (renamed from app/Controller/Comment.php)43
-rw-r--r--app/Controller/ConfigController.php (renamed from app/Controller/Config.php)122
-rw-r--r--app/Controller/CurrencyController.php (renamed from app/Controller/Currency.php)25
-rw-r--r--app/Controller/CustomFilterController.php (renamed from app/Controller/Customfilter.php)45
-rw-r--r--app/Controller/DashboardController.php (renamed from app/Controller/App.php)58
-rw-r--r--app/Controller/DocumentationController.php (renamed from app/Controller/Doc.php)10
-rw-r--r--app/Controller/ExportController.php (renamed from app/Controller/Export.php)18
-rw-r--r--app/Controller/FeedController.php (renamed from app/Controller/Feed.php)17
-rw-r--r--app/Controller/FileViewerController.php (renamed from app/Controller/FileViewer.php)56
-rw-r--r--app/Controller/Gantt.php162
-rw-r--r--app/Controller/Group.php250
-rw-r--r--app/Controller/GroupAjaxController.php (renamed from app/Controller/GroupHelper.php)8
-rw-r--r--app/Controller/GroupCreationController.php49
-rw-r--r--app/Controller/GroupListController.php173
-rw-r--r--app/Controller/GroupModificationController.php53
-rw-r--r--app/Controller/ICalendarController.php (renamed from app/Controller/Ical.php)23
-rw-r--r--app/Controller/LinkController.php (renamed from app/Controller/Link.php)38
-rw-r--r--app/Controller/OAuthController.php (renamed from app/Controller/Oauth.php)14
-rw-r--r--app/Controller/PasswordResetController.php (renamed from app/Controller/PasswordReset.php)36
-rw-r--r--app/Controller/PluginController.php126
-rw-r--r--app/Controller/Project.php243
-rw-r--r--app/Controller/ProjectActionDuplicationController.php (renamed from app/Controller/ActionProject.php)14
-rw-r--r--app/Controller/ProjectCreationController.php (renamed from app/Controller/ProjectCreation.php)20
-rw-r--r--app/Controller/ProjectEditController.php (renamed from app/Controller/ProjectEdit.php)26
-rw-r--r--app/Controller/ProjectFileController.php (renamed from app/Controller/ProjectFile.php)16
-rw-r--r--app/Controller/ProjectGanttController.php57
-rw-r--r--app/Controller/ProjectListController.php41
-rw-r--r--app/Controller/ProjectOverviewController.php (renamed from app/Controller/ProjectOverview.php)12
-rw-r--r--app/Controller/ProjectPermissionController.php (renamed from app/Controller/ProjectPermission.php)43
-rw-r--r--app/Controller/ProjectStatusController.php102
-rw-r--r--app/Controller/ProjectUserOverviewController.php (renamed from app/Controller/Projectuser.php)32
-rw-r--r--app/Controller/ProjectViewController.php162
-rw-r--r--app/Controller/SearchController.php (renamed from app/Controller/Search.php)14
-rw-r--r--app/Controller/SubtaskController.php (renamed from app/Controller/Subtask.php)49
-rw-r--r--app/Controller/SubtaskConverterController.php39
-rw-r--r--app/Controller/SubtaskRestrictionController.php (renamed from app/Controller/SubtaskRestriction.php)20
-rw-r--r--app/Controller/SubtaskStatusController.php (renamed from app/Controller/SubtaskStatus.php)15
-rw-r--r--app/Controller/SwimlaneController.php (renamed from app/Controller/Swimlane.php)86
-rw-r--r--app/Controller/Task.php174
-rw-r--r--app/Controller/TaskAjaxController.php (renamed from app/Controller/TaskHelper.php)8
-rw-r--r--app/Controller/TaskBulkController.php89
-rw-r--r--app/Controller/TaskCreationController.php (renamed from app/Controller/Taskcreation.php)33
-rw-r--r--app/Controller/TaskDuplicationController.php (renamed from app/Controller/Taskduplication.php)36
-rw-r--r--app/Controller/TaskExternalLinkController.php (renamed from app/Controller/TaskExternalLink.php)45
-rw-r--r--app/Controller/TaskFileController.php (renamed from app/Controller/TaskFile.php)22
-rw-r--r--app/Controller/TaskGanttController.php62
-rw-r--r--app/Controller/TaskGanttCreationController.php71
-rw-r--r--app/Controller/TaskImport.php72
-rw-r--r--app/Controller/TaskImportController.php74
-rw-r--r--app/Controller/TaskInternalLinkController.php (renamed from app/Controller/TaskInternalLink.php)41
-rw-r--r--app/Controller/TaskListController.php (renamed from app/Controller/Listing.php)12
-rw-r--r--app/Controller/TaskModificationController.php (renamed from app/Controller/Taskmodification.php)38
-rw-r--r--app/Controller/TaskPopoverController.php100
-rw-r--r--app/Controller/TaskRecurrenceController.php (renamed from app/Controller/TaskRecurrence.php)22
-rw-r--r--app/Controller/TaskStatusController.php (renamed from app/Controller/Taskstatus.php)10
-rw-r--r--app/Controller/TaskSuppressionController.php53
-rw-r--r--app/Controller/TaskViewController.php146
-rw-r--r--app/Controller/TwoFactorController.php (renamed from app/Controller/Twofactor.php)30
-rw-r--r--app/Controller/User.php408
-rw-r--r--app/Controller/UserAjaxController.php (renamed from app/Controller/UserHelper.php)20
-rw-r--r--app/Controller/UserCreationController.php83
-rw-r--r--app/Controller/UserCredentialController.php109
-rw-r--r--app/Controller/UserImportController.php (renamed from app/Controller/UserImport.php)51
-rw-r--r--app/Controller/UserListController.php32
-rw-r--r--app/Controller/UserModificationController.php69
-rw-r--r--app/Controller/UserStatusController.php (renamed from app/Controller/UserStatus.php)16
-rw-r--r--app/Controller/UserViewController.php217
-rw-r--r--app/Controller/WebNotification.php50
-rw-r--r--app/Controller/WebNotificationController.php79
-rw-r--r--app/Controller/Webhook.php42
89 files changed, 3257 insertions, 2712 deletions
diff --git a/app/Controller/Action.php b/app/Controller/ActionController.php
index 8881e8ec..097640f6 100644
--- a/app/Controller/Action.php
+++ b/app/Controller/ActionController.php
@@ -3,12 +3,12 @@
namespace Kanboard\Controller;
/**
- * Automatic Actions
+ * Automatic Actions Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Action extends Base
+class ActionController extends BaseController
{
/**
* List of automatic actions for a given project
@@ -18,7 +18,7 @@ class Action extends Base
public function index()
{
$project = $this->getProject();
- $actions = $this->action->getAllByProject($project['id']);
+ $actions = $this->actionModel->getAllByProject($project['id']);
$this->response->html($this->helper->layout->project('action/index', array(
'values' => array('project_id' => $project['id']),
@@ -27,12 +27,12 @@ class Action extends Base
'available_actions' => $this->actionManager->getAvailableActions(),
'available_events' => $this->eventManager->getAll(),
'available_params' => $this->actionManager->getAvailableParameters($actions),
- 'columns_list' => $this->column->getList($project['id']),
- 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id']),
- 'projects_list' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()),
- 'colors_list' => $this->color->getList(),
- 'categories_list' => $this->category->getList($project['id']),
- 'links_list' => $this->link->getList(0, false),
+ 'columns_list' => $this->columnModel->getList($project['id']),
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id']),
+ 'projects_list' => $this->projectUserRoleModel->getProjectsByUser($this->userSession->getId()),
+ 'colors_list' => $this->colorModel->getList(),
+ 'categories_list' => $this->categoryModel->getList($project['id']),
+ 'links_list' => $this->linkModel->getList(0, false),
'title' => t('Automatic actions')
)));
}
@@ -47,7 +47,7 @@ class Action extends Base
$project = $this->getProject();
$this->response->html($this->helper->layout->project('action/remove', array(
- 'action' => $this->action->getById($this->request->getIntegerParam('action_id')),
+ 'action' => $this->actionModel->getById($this->request->getIntegerParam('action_id')),
'available_events' => $this->eventManager->getAll(),
'available_actions' => $this->actionManager->getAvailableActions(),
'project' => $project,
@@ -64,14 +64,14 @@ class Action extends Base
{
$this->checkCSRFParam();
$project = $this->getProject();
- $action = $this->action->getById($this->request->getIntegerParam('action_id'));
+ $action = $this->actionModel->getById($this->request->getIntegerParam('action_id'));
- if (! empty($action) && $this->action->remove($action['id'])) {
+ if (! empty($action) && $this->actionModel->remove($action['id'])) {
$this->flash->success(t('Action removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this action.'));
}
- $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ActionController', 'index', array('project_id' => $project['id'])));
}
}
diff --git a/app/Controller/ActionCreation.php b/app/Controller/ActionCreationController.php
index 24a12d92..e984f8d4 100644
--- a/app/Controller/ActionCreation.php
+++ b/app/Controller/ActionCreationController.php
@@ -3,12 +3,12 @@
namespace Kanboard\Controller;
/**
- * Action Creation
+ * Action Creation Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class ActionCreation extends Base
+class ActionCreationController extends BaseController
{
/**
* Show the form (step 1)
@@ -69,18 +69,19 @@ class ActionCreation extends Base
$this->doCreation($project, $values + array('params' => array()));
}
- $projects_list = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId());
+ $projects_list = $this->projectUserRoleModel->getActiveProjectsByUser($this->userSession->getId());
unset($projects_list[$project['id']]);
$this->response->html($this->template->render('action_creation/params', array(
'values' => $values,
'action_params' => $action_params,
- 'columns_list' => $this->column->getList($project['id']),
- 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id']),
+ 'columns_list' => $this->columnModel->getList($project['id']),
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id']),
'projects_list' => $projects_list,
- 'colors_list' => $this->color->getList(),
- 'categories_list' => $this->category->getList($project['id']),
- 'links_list' => $this->link->getList(0, false),
+ 'colors_list' => $this->colorModel->getList(),
+ 'categories_list' => $this->categoryModel->getList($project['id']),
+ 'links_list' => $this->linkModel->getList(0, false),
+ 'priorities_list' => $this->projectModel->getPriorities($project),
'project' => $project,
'available_actions' => $this->actionManager->getAvailableActions(),
'events' => $this->actionManager->getCompatibleEvents($values['action_name']),
@@ -109,13 +110,13 @@ class ActionCreation extends Base
list($valid, ) = $this->actionValidator->validateCreation($values);
if ($valid) {
- if ($this->action->create($values) !== false) {
+ if ($this->actionModel->create($values) !== false) {
$this->flash->success(t('Your automatic action have been created successfully.'));
} else {
$this->flash->failure(t('Unable to create your automatic action.'));
}
}
- $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ActionController', 'index', array('project_id' => $project['id'])));
}
}
diff --git a/app/Controller/Activity.php b/app/Controller/ActivityController.php
index 47a66e0a..9f9841af 100644
--- a/app/Controller/Activity.php
+++ b/app/Controller/ActivityController.php
@@ -3,12 +3,12 @@
namespace Kanboard\Controller;
/**
- * Activity stream
+ * Activity Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Activity extends Base
+class ActivityController extends BaseController
{
/**
* Activity page for a project
@@ -38,7 +38,7 @@ class Activity extends Base
$this->response->html($this->helper->layout->task('activity/task', array(
'title' => $task['title'],
'task' => $task,
- 'project' => $this->project->getById($task['project_id']),
+ 'project' => $this->projectModel->getById($task['project_id']),
'events' => $this->helper->projectActivity->getTaskEvents($task['id']),
)));
}
diff --git a/app/Controller/Analytic.php b/app/Controller/AnalyticController.php
index 35bc3048..cf3ba034 100644
--- a/app/Controller/Analytic.php
+++ b/app/Controller/AnalyticController.php
@@ -3,15 +3,15 @@
namespace Kanboard\Controller;
use Kanboard\Filter\TaskProjectFilter;
-use Kanboard\Model\Task as TaskModel;
+use Kanboard\Model\TaskModel;
/**
- * Project Analytic controller
+ * Project Analytic Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Analytic extends Base
+class AnalyticController extends BaseController
{
/**
* Show average Lead and Cycle time
@@ -30,8 +30,8 @@ class Analytic extends Base
),
'project' => $project,
'average' => $this->averageLeadCycleTimeAnalytic->build($project['id']),
- 'metrics' => $this->projectDailyStats->getRawMetrics($project['id'], $from, $to),
- 'date_format' => $this->config->get('application_date_format'),
+ 'metrics' => $this->projectDailyStatsModel->getRawMetrics($project['id'], $from, $to),
+ 'date_format' => $this->configModel->get('application_date_format'),
'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
'title' => t('Lead and Cycle time for "%s"', $project['name']),
)));
@@ -47,7 +47,7 @@ class Analytic extends Base
$project = $this->getProject();
$paginator = $this->paginator
- ->setUrl('analytic', 'compareHours', array('project_id' => $project['id']))
+ ->setUrl('AnalyticController', 'compareHours', array('project_id' => $project['id']))
->setMax(30)
->setOrder(TaskModel::TABLE.'.id')
->setQuery($this->taskQuery
@@ -145,7 +145,7 @@ class Analytic extends Base
$project = $this->getProject();
list($from, $to) = $this->getDates();
- $display_graph = $this->projectDailyColumnStats->countDays($project['id'], $from, $to) >= 2;
+ $display_graph = $this->projectDailyColumnStatsModel->countDays($project['id'], $from, $to) >= 2;
$this->response->html($this->helper->layout->analytic($template, array(
'values' => array(
@@ -153,9 +153,9 @@ class Analytic extends Base
'to' => $to,
),
'display_graph' => $display_graph,
- 'metrics' => $display_graph ? $this->projectDailyColumnStats->getAggregatedMetrics($project['id'], $from, $to, $column) : array(),
+ 'metrics' => $display_graph ? $this->projectDailyColumnStatsModel->getAggregatedMetrics($project['id'], $from, $to, $column) : array(),
'project' => $project,
- 'date_format' => $this->config->get('application_date_format'),
+ 'date_format' => $this->configModel->get('application_date_format'),
'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
'title' => t($title, $project['name']),
)));
diff --git a/app/Controller/AppController.php b/app/Controller/AppController.php
new file mode 100644
index 00000000..45cf39a5
--- /dev/null
+++ b/app/Controller/AppController.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Base;
+
+/**
+ * Class AppController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class AppController extends Base
+{
+ /**
+ * Forbidden page
+ *
+ * @access public
+ * @param bool $withoutLayout
+ */
+ public function accessForbidden($withoutLayout = false)
+ {
+ if ($this->request->isAjax()) {
+ $this->response->json(array('message' => 'Access Forbidden'), 403);
+ }
+
+ $this->response->html($this->helper->layout->app('app/forbidden', array(
+ 'title' => t('Access Forbidden'),
+ 'no_layout' => $withoutLayout,
+ )));
+ }
+
+ /**
+ * Page not found
+ *
+ * @access public
+ * @param boolean $withoutLayout
+ */
+ public function notFound($withoutLayout = false)
+ {
+ $this->response->html($this->helper->layout->app('app/notfound', array(
+ 'title' => t('Page not found'),
+ 'no_layout' => $withoutLayout,
+ )));
+ }
+}
diff --git a/app/Controller/Auth.php b/app/Controller/AuthController.php
index b882a720..dc46070c 100644
--- a/app/Controller/Auth.php
+++ b/app/Controller/AuthController.php
@@ -3,12 +3,12 @@
namespace Kanboard\Controller;
/**
- * Authentication controller
+ * Authentication Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Auth extends Base
+class AuthController extends BaseController
{
/**
* Display the form login
@@ -20,16 +20,16 @@ class Auth extends Base
public function login(array $values = array(), array $errors = array())
{
if ($this->userSession->isLogged()) {
- $this->response->redirect($this->helper->url->to('app', 'index'));
+ $this->response->redirect($this->helper->url->to('DashboardController', 'show'));
+ } else {
+ $this->response->html($this->helper->layout->app('auth/index', array(
+ 'captcha' => ! empty($values['username']) && $this->userLockingModel->hasCaptcha($values['username']),
+ 'errors' => $errors,
+ 'values' => $values,
+ 'no_layout' => true,
+ 'title' => t('Login')
+ )));
}
-
- $this->response->html($this->helper->layout->app('auth/index', array(
- 'captcha' => ! empty($values['username']) && $this->userLocking->hasCaptcha($values['username']),
- 'errors' => $errors,
- 'values' => $values,
- 'no_layout' => true,
- 'title' => t('Login')
- )));
}
/**
@@ -45,9 +45,9 @@ class Auth extends Base
if ($valid) {
$this->redirectAfterLogin();
+ } else {
+ $this->login($values, $errors);
}
-
- $this->login($values, $errors);
}
/**
@@ -59,9 +59,9 @@ class Auth extends Base
{
if (! DISABLE_LOGOUT) {
$this->sessionManager->close();
- $this->response->redirect($this->helper->url->to('auth', 'login'));
+ $this->response->redirect($this->helper->url->to('AuthController', 'login'));
} else {
- $this->response->redirect($this->helper->url->to('auth', 'index'));
+ $this->response->redirect($this->helper->url->to('AuthController', 'index'));
}
}
@@ -76,8 +76,8 @@ class Auth extends Base
$redirect = $this->sessionStorage->redirectAfterLogin;
unset($this->sessionStorage->redirectAfterLogin);
$this->response->redirect($redirect);
+ } else {
+ $this->response->redirect($this->helper->url->to('DashboardController', 'show'));
}
-
- $this->response->redirect($this->helper->url->to('app', 'index'));
}
}
diff --git a/app/Controller/AvatarFile.php b/app/Controller/AvatarFileController.php
index a47cca66..6879c577 100644
--- a/app/Controller/AvatarFile.php
+++ b/app/Controller/AvatarFileController.php
@@ -8,10 +8,10 @@ use Kanboard\Core\Thumbnail;
/**
* Avatar File Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class AvatarFile extends Base
+class AvatarFileController extends BaseController
{
/**
* Display avatar page
@@ -32,11 +32,11 @@ class AvatarFile extends Base
{
$user = $this->getUser();
- if (! $this->avatarFile->uploadFile($user['id'], $this->request->getFileInfo('avatar'))) {
+ if (! $this->avatarFileModel->uploadImageFile($user['id'], $this->request->getFileInfo('avatar'))) {
$this->flash->failure(t('Unable to upload the file.'));
}
- $this->response->redirect($this->helper->url->to('AvatarFile', 'show', array('user_id' => $user['id'])));
+ $this->response->redirect($this->helper->url->to('AvatarFileController', 'show', array('user_id' => $user['id'])));
}
/**
@@ -46,8 +46,9 @@ class AvatarFile extends Base
{
$this->checkCSRFParam();
$user = $this->getUser();
- $this->avatarFile->remove($user['id']);
- $this->response->redirect($this->helper->url->to('AvatarFile', 'show', array('user_id' => $user['id'])));
+ $this->avatarFileModel->remove($user['id']);
+ $this->userSession->refresh($user['id']);
+ $this->response->redirect($this->helper->url->to('AvatarFileController', 'show', array('user_id' => $user['id'])));
}
/**
@@ -57,13 +58,14 @@ class AvatarFile extends Base
{
$user_id = $this->request->getIntegerParam('user_id');
$size = $this->request->getStringParam('size', 48);
- $filename = $this->avatarFile->getFilename($user_id);
+ $filename = $this->avatarFileModel->getFilename($user_id);
$etag = md5($filename.$size);
- $this->response->cache(365 * 86400, $etag);
- $this->response->contentType('image/jpeg');
+ $this->response->withCache(365 * 86400, $etag);
+ $this->response->withContentType('image/jpeg');
if ($this->request->getHeader('If-None-Match') !== '"'.$etag.'"') {
+ $this->response->send();
$this->render($filename, $size);
} else {
$this->response->status(304);
diff --git a/app/Controller/Base.php b/app/Controller/Base.php
deleted file mode 100644
index beb56909..00000000
--- a/app/Controller/Base.php
+++ /dev/null
@@ -1,290 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-use Kanboard\Core\Security\Role;
-
-/**
- * Base controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-abstract class Base extends \Kanboard\Core\Base
-{
- /**
- * Method executed before each action
- *
- * @access public
- */
- public function beforeAction()
- {
- $this->sessionManager->open();
- $this->dispatcher->dispatch('app.bootstrap');
- $this->sendHeaders();
- $this->authenticationManager->checkCurrentSession();
-
- if (! $this->applicationAuthorization->isAllowed($this->router->getController(), $this->router->getAction(), Role::APP_PUBLIC)) {
- $this->handleAuthentication();
- $this->handlePostAuthentication();
- $this->checkApplicationAuthorization();
- $this->checkProjectAuthorization();
- }
- }
-
- /**
- * Send HTTP headers
- *
- * @access private
- */
- private function sendHeaders()
- {
- // HTTP secure headers
- $this->response->csp($this->container['cspRules']);
- $this->response->nosniff();
- $this->response->xss();
-
- // Allow the public board iframe inclusion
- if (ENABLE_XFRAME && $this->router->getAction() !== 'readonly') {
- $this->response->xframe();
- }
-
- if (ENABLE_HSTS) {
- $this->response->hsts();
- }
- }
-
- /**
- * Check authentication
- *
- * @access private
- */
- private function handleAuthentication()
- {
- if (! $this->userSession->isLogged() && ! $this->authenticationManager->preAuthentication()) {
- if ($this->request->isAjax()) {
- $this->response->text('Not Authorized', 401);
- }
-
- $this->sessionStorage->redirectAfterLogin = $this->request->getUri();
- $this->response->redirect($this->helper->url->to('auth', 'login'));
- }
- }
-
- /**
- * Handle Post-Authentication (2FA)
- *
- * @access private
- */
- private function handlePostAuthentication()
- {
- $controller = strtolower($this->router->getController());
- $action = strtolower($this->router->getAction());
- $ignore = ($controller === 'twofactor' && in_array($action, array('code', 'check'))) || ($controller === 'auth' && $action === 'logout');
-
- if ($ignore === false && $this->userSession->hasPostAuthentication() && ! $this->userSession->isPostAuthenticationValidated()) {
- if ($this->request->isAjax()) {
- $this->response->text('Not Authorized', 401);
- }
-
- $this->response->redirect($this->helper->url->to('twofactor', 'code'));
- }
- }
-
- /**
- * Check application authorization
- *
- * @access private
- */
- private function checkApplicationAuthorization()
- {
- if (! $this->helper->user->hasAccess($this->router->getController(), $this->router->getAction())) {
- $this->forbidden();
- }
- }
-
- /**
- * Check project authorization
- *
- * @access private
- */
- private function checkProjectAuthorization()
- {
- $project_id = $this->request->getIntegerParam('project_id');
- $task_id = $this->request->getIntegerParam('task_id');
-
- // Allow urls without "project_id"
- if ($task_id > 0 && $project_id === 0) {
- $project_id = $this->taskFinder->getProjectId($task_id);
- }
-
- if ($project_id > 0 && ! $this->helper->user->hasProjectAccess($this->router->getController(), $this->router->getAction(), $project_id)) {
- $this->forbidden();
- }
- }
-
- /**
- * Application not found page (404 error)
- *
- * @access protected
- * @param boolean $no_layout Display the layout or not
- */
- protected function notfound($no_layout = false)
- {
- $this->response->html($this->helper->layout->app('app/notfound', array(
- 'title' => t('Page not found'),
- 'no_layout' => $no_layout,
- )));
- }
-
- /**
- * Application forbidden page
- *
- * @access protected
- * @param boolean $no_layout Display the layout or not
- */
- protected function forbidden($no_layout = false)
- {
- if ($this->request->isAjax()) {
- $this->response->text('Access Forbidden', 403);
- }
-
- $this->response->html($this->helper->layout->app('app/forbidden', array(
- 'title' => t('Access Forbidden'),
- 'no_layout' => $no_layout,
- )));
- }
-
- /**
- * Check if the CSRF token from the URL is correct
- *
- * @access protected
- */
- protected function checkCSRFParam()
- {
- if (! $this->token->validateCSRFToken($this->request->getStringParam('csrf_token'))) {
- $this->forbidden();
- }
- }
-
- /**
- * Check webhook token
- *
- * @access protected
- */
- protected function checkWebhookToken()
- {
- if ($this->config->get('webhook_token') !== $this->request->getStringParam('token')) {
- $this->response->text('Not Authorized', 401);
- }
- }
-
- /**
- * Common method to get a task for task views
- *
- * @access protected
- * @return array
- */
- protected function getTask()
- {
- $project_id = $this->request->getIntegerParam('project_id');
- $task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
-
- if (empty($task)) {
- $this->notfound();
- }
-
- if ($project_id !== 0 && $project_id != $task['project_id']) {
- $this->forbidden();
- }
-
- return $task;
- }
-
- /**
- * Get Task or Project file
- *
- * @access protected
- */
- protected function getFile()
- {
- $task_id = $this->request->getIntegerParam('task_id');
- $file_id = $this->request->getIntegerParam('file_id');
- $model = 'projectFile';
-
- if ($task_id > 0) {
- $model = 'taskFile';
- $project_id = $this->taskFinder->getProjectId($task_id);
-
- if ($project_id !== $this->request->getIntegerParam('project_id')) {
- $this->forbidden();
- }
- }
-
- $file = $this->$model->getById($file_id);
-
- if (empty($file)) {
- $this->notfound();
- }
-
- $file['model'] = $model;
- return $file;
- }
-
- /**
- * Common method to get a project
- *
- * @access protected
- * @param integer $project_id Default project id
- * @return array
- */
- protected function getProject($project_id = 0)
- {
- $project_id = $this->request->getIntegerParam('project_id', $project_id);
- $project = $this->project->getByIdWithOwner($project_id);
-
- if (empty($project)) {
- $this->notfound();
- }
-
- return $project;
- }
-
- /**
- * Common method to get the user
- *
- * @access protected
- * @return array
- */
- protected function getUser()
- {
- $user = $this->user->getById($this->request->getIntegerParam('user_id', $this->userSession->getId()));
-
- if (empty($user)) {
- $this->notfound();
- }
-
- if (! $this->userSession->isAdmin() && $this->userSession->getId() != $user['id']) {
- $this->forbidden();
- }
-
- return $user;
- }
-
- /**
- * Get the current subtask
- *
- * @access protected
- * @return array
- */
- protected function getSubtask()
- {
- $subtask = $this->subtask->getById($this->request->getIntegerParam('subtask_id'));
-
- if (empty($subtask)) {
- $this->notfound();
- }
-
- return $subtask;
- }
-}
diff --git a/app/Controller/BaseController.php b/app/Controller/BaseController.php
new file mode 100644
index 00000000..ae2dc006
--- /dev/null
+++ b/app/Controller/BaseController.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Base;
+use Kanboard\Core\Controller\AccessForbiddenException;
+use Kanboard\Core\Controller\PageNotFoundException;
+
+/**
+ * Base Controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+abstract class BaseController extends Base
+{
+ /**
+ * Check if the CSRF token from the URL is correct
+ *
+ * @access protected
+ */
+ protected function checkCSRFParam()
+ {
+ if (! $this->token->validateCSRFToken($this->request->getStringParam('csrf_token'))) {
+ throw new AccessForbiddenException();
+ }
+ }
+
+ /**
+ * Check webhook token
+ *
+ * @access protected
+ */
+ protected function checkWebhookToken()
+ {
+ if ($this->configModel->get('webhook_token') !== $this->request->getStringParam('token')) {
+ throw AccessForbiddenException::getInstance()->withoutLayout();
+ }
+ }
+
+ /**
+ * Common method to get a task for task views
+ *
+ * @access protected
+ * @return array
+ * @throws PageNotFoundException
+ * @throws AccessForbiddenException
+ */
+ protected function getTask()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+ $task = $this->taskFinderModel->getDetails($this->request->getIntegerParam('task_id'));
+
+ if (empty($task)) {
+ throw new PageNotFoundException();
+ }
+
+ if ($project_id !== 0 && $project_id != $task['project_id']) {
+ throw new AccessForbiddenException();
+ }
+
+ return $task;
+ }
+
+ /**
+ * Get Task or Project file
+ *
+ * @access protected
+ * @return array
+ * @throws PageNotFoundException
+ * @throws AccessForbiddenException
+ */
+ protected function getFile()
+ {
+ $task_id = $this->request->getIntegerParam('task_id');
+ $file_id = $this->request->getIntegerParam('file_id');
+ $model = 'projectFile';
+
+ if ($task_id > 0) {
+ $model = 'taskFileModel';
+ $project_id = $this->taskFinderModel->getProjectId($task_id);
+
+ if ($project_id !== $this->request->getIntegerParam('project_id')) {
+ throw new AccessForbiddenException();
+ }
+ }
+
+ $file = $this->$model->getById($file_id);
+
+ if (empty($file)) {
+ throw new PageNotFoundException();
+ }
+
+ $file['model'] = $model;
+ return $file;
+ }
+
+ /**
+ * Common method to get a project
+ *
+ * @access protected
+ * @param integer $project_id Default project id
+ * @return array
+ * @throws PageNotFoundException
+ */
+ protected function getProject($project_id = 0)
+ {
+ $project_id = $this->request->getIntegerParam('project_id', $project_id);
+ $project = $this->projectModel->getByIdWithOwner($project_id);
+
+ if (empty($project)) {
+ throw new PageNotFoundException();
+ }
+
+ return $project;
+ }
+
+ /**
+ * Common method to get the user
+ *
+ * @access protected
+ * @return array
+ * @throws PageNotFoundException
+ * @throws AccessForbiddenException
+ */
+ protected function getUser()
+ {
+ $user = $this->userModel->getById($this->request->getIntegerParam('user_id', $this->userSession->getId()));
+
+ if (empty($user)) {
+ throw new PageNotFoundException();
+ }
+
+ if (! $this->userSession->isAdmin() && $this->userSession->getId() != $user['id']) {
+ throw new AccessForbiddenException();
+ }
+
+ return $user;
+ }
+
+ /**
+ * Get the current subtask
+ *
+ * @access protected
+ * @return array
+ * @throws PageNotFoundException
+ */
+ protected function getSubtask()
+ {
+ $subtask = $this->subtaskModel->getById($this->request->getIntegerParam('subtask_id'));
+
+ if (empty($subtask)) {
+ throw new PageNotFoundException();
+ }
+
+ return $subtask;
+ }
+}
diff --git a/app/Controller/Board.php b/app/Controller/Board.php
deleted file mode 100644
index 67e99b81..00000000
--- a/app/Controller/Board.php
+++ /dev/null
@@ -1,192 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-use Kanboard\Formatter\BoardFormatter;
-
-/**
- * Board controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-class Board extends Base
-{
- /**
- * Display the public version of a board
- * Access checked by a simple token, no user login, read only, auto-refresh
- *
- * @access public
- */
- public function readonly()
- {
- $token = $this->request->getStringParam('token');
- $project = $this->project->getByToken($token);
-
- // Token verification
- if (empty($project)) {
- $this->forbidden(true);
- }
-
- // Display the board with a specific layout
- $this->response->html($this->helper->layout->app('board/view_public', array(
- 'project' => $project,
- 'swimlanes' => $this->board->getBoard($project['id']),
- 'title' => $project['name'],
- 'description' => $project['description'],
- 'no_layout' => true,
- 'not_editable' => true,
- 'board_public_refresh_interval' => $this->config->get('board_public_refresh_interval'),
- 'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'),
- 'board_highlight_period' => $this->config->get('board_highlight_period'),
- )));
- }
-
- /**
- * Show a board for a given project
- *
- * @access public
- */
- public function show()
- {
- $project = $this->getProject();
- $search = $this->helper->projectHeader->getSearchQuery($project);
-
- $this->response->html($this->helper->layout->app('board/view_private', array(
- 'project' => $project,
- 'title' => $project['name'],
- 'description' => $this->helper->projectHeader->getDescription($project),
- 'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'),
- 'board_highlight_period' => $this->config->get('board_highlight_period'),
- 'swimlanes' => $this->taskLexer
- ->build($search)
- ->format(BoardFormatter::getInstance($this->container)->setProjectId($project['id']))
- )));
- }
-
- /**
- * Save the board (Ajax request made by the drag and drop)
- *
- * @access public
- */
- public function save()
- {
- $project_id = $this->request->getIntegerParam('project_id');
-
- if (! $project_id || ! $this->request->isAjax()) {
- return $this->response->status(403);
- }
-
- $values = $this->request->getJson();
-
- $result =$this->taskPosition->movePosition(
- $project_id,
- $values['task_id'],
- $values['column_id'],
- $values['position'],
- $values['swimlane_id']
- );
-
- if (! $result) {
- return $this->response->status(400);
- }
-
- $this->response->html($this->renderBoard($project_id), 201);
- }
-
- /**
- * Check if the board have been changed
- *
- * @access public
- */
- public function check()
- {
- $project_id = $this->request->getIntegerParam('project_id');
- $timestamp = $this->request->getIntegerParam('timestamp');
-
- if (! $project_id || ! $this->request->isAjax()) {
- return $this->response->status(403);
- }
-
- if (! $this->project->isModifiedSince($project_id, $timestamp)) {
- return $this->response->status(304);
- }
-
- return $this->response->html($this->renderBoard($project_id));
- }
-
- /**
- * Reload the board with new filters
- *
- * @access public
- */
- public function reload()
- {
- $project_id = $this->request->getIntegerParam('project_id');
-
- if (! $project_id || ! $this->request->isAjax()) {
- return $this->response->status(403);
- }
-
- $values = $this->request->getJson();
- $this->userSession->setFilters($project_id, empty($values['search']) ? '' : $values['search']);
-
- $this->response->html($this->renderBoard($project_id));
- }
-
- /**
- * Enable collapsed mode
- *
- * @access public
- */
- public function collapse()
- {
- $this->changeDisplayMode(true);
- }
-
- /**
- * Enable expanded mode
- *
- * @access public
- */
- public function expand()
- {
- $this->changeDisplayMode(false);
- }
-
- /**
- * Change display mode
- *
- * @access private
- * @param boolean $mode
- */
- private function changeDisplayMode($mode)
- {
- $project_id = $this->request->getIntegerParam('project_id');
- $this->userSession->setBoardDisplayMode($project_id, $mode);
-
- if ($this->request->isAjax()) {
- $this->response->html($this->renderBoard($project_id));
- } else {
- $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project_id)));
- }
- }
-
- /**
- * Render board
- *
- * @access private
- * @param integer $project_id
- */
- private function renderBoard($project_id)
- {
- return $this->template->render('board/table_container', array(
- 'project' => $this->project->getById($project_id),
- 'board_private_refresh_interval' => $this->config->get('board_private_refresh_interval'),
- 'board_highlight_period' => $this->config->get('board_highlight_period'),
- 'swimlanes' => $this->taskLexer
- ->build($this->userSession->getFilters($project_id))
- ->format(BoardFormatter::getInstance($this->container)->setProjectId($project_id))
- ));
- }
-}
diff --git a/app/Controller/BoardAjaxController.php b/app/Controller/BoardAjaxController.php
new file mode 100644
index 00000000..24914671
--- /dev/null
+++ b/app/Controller/BoardAjaxController.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Controller\AccessForbiddenException;
+use Kanboard\Formatter\BoardFormatter;
+
+/**
+ * Class BoardAjaxController
+ *
+ * @package Kanboard\Controller
+ * @author Fredric Guillot
+ */
+class BoardAjaxController extends BaseController
+{
+ /**
+ * Save new task positions (Ajax request made by the drag and drop)
+ *
+ * @access public
+ */
+ public function save()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+
+ if (! $project_id || ! $this->request->isAjax()) {
+ throw new AccessForbiddenException();
+ }
+
+ $values = $this->request->getJson();
+
+ $result =$this->taskPositionModel->movePosition(
+ $project_id,
+ $values['task_id'],
+ $values['column_id'],
+ $values['position'],
+ $values['swimlane_id']
+ );
+
+ if (! $result) {
+ $this->response->status(400);
+ } else {
+ $this->response->html($this->renderBoard($project_id), 201);
+ }
+ }
+
+ /**
+ * Check if the board have been changed
+ *
+ * @access public
+ */
+ public function check()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+ $timestamp = $this->request->getIntegerParam('timestamp');
+
+ if (! $project_id || ! $this->request->isAjax()) {
+ throw new AccessForbiddenException();
+ } elseif (! $this->projectModel->isModifiedSince($project_id, $timestamp)) {
+ $this->response->status(304);
+ } else {
+ $this->response->html($this->renderBoard($project_id));
+ }
+ }
+
+ /**
+ * Reload the board with new filters
+ *
+ * @access public
+ */
+ public function reload()
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+
+ if (! $project_id || ! $this->request->isAjax()) {
+ throw new AccessForbiddenException();
+ }
+
+ $values = $this->request->getJson();
+ $this->userSession->setFilters($project_id, empty($values['search']) ? '' : $values['search']);
+
+ $this->response->html($this->renderBoard($project_id));
+ }
+
+ /**
+ * Enable collapsed mode
+ *
+ * @access public
+ */
+ public function collapse()
+ {
+ $this->changeDisplayMode(true);
+ }
+
+ /**
+ * Enable expanded mode
+ *
+ * @access public
+ */
+ public function expand()
+ {
+ $this->changeDisplayMode(false);
+ }
+
+ /**
+ * Change display mode
+ *
+ * @access private
+ * @param boolean $mode
+ */
+ private function changeDisplayMode($mode)
+ {
+ $project_id = $this->request->getIntegerParam('project_id');
+ $this->userSession->setBoardDisplayMode($project_id, $mode);
+
+ if ($this->request->isAjax()) {
+ $this->response->html($this->renderBoard($project_id));
+ } else {
+ $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project_id)));
+ }
+ }
+
+ /**
+ * Render board
+ *
+ * @access protected
+ * @param integer $project_id
+ * @return string
+ */
+ protected function renderBoard($project_id)
+ {
+ return $this->template->render('board/table_container', array(
+ 'project' => $this->projectModel->getById($project_id),
+ 'board_private_refresh_interval' => $this->configModel->get('board_private_refresh_interval'),
+ 'board_highlight_period' => $this->configModel->get('board_highlight_period'),
+ 'swimlanes' => $this->taskLexer
+ ->build($this->userSession->getFilters($project_id))
+ ->format(BoardFormatter::getInstance($this->container)->setProjectId($project_id))
+ ));
+ }
+}
diff --git a/app/Controller/BoardPopover.php b/app/Controller/BoardPopover.php
deleted file mode 100644
index 63dab302..00000000
--- a/app/Controller/BoardPopover.php
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-/**
- * Board Popover
- *
- * @package controller
- * @author Frederic Guillot
- */
-class BoardPopover extends Base
-{
- /**
- * Change a task assignee directly from the board
- *
- * @access public
- */
- public function changeAssignee()
- {
- $task = $this->getTask();
- $project = $this->project->getById($task['project_id']);
-
- $this->response->html($this->template->render('board/popover_assignee', array(
- 'values' => $task,
- 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id']),
- 'project' => $project,
- )));
- }
-
- /**
- * Validate an assignee modification
- *
- * @access public
- */
- public function updateAssignee()
- {
- $values = $this->request->getValues();
-
- list($valid, ) = $this->taskValidator->validateAssigneeModification($values);
-
- if ($valid && $this->taskModification->update($values)) {
- $this->flash->success(t('Task updated successfully.'));
- } else {
- $this->flash->failure(t('Unable to update your task.'));
- }
-
- $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id'])));
- }
-
- /**
- * Change a task category directly from the board
- *
- * @access public
- */
- public function changeCategory()
- {
- $task = $this->getTask();
- $project = $this->project->getById($task['project_id']);
-
- $this->response->html($this->template->render('board/popover_category', array(
- 'values' => $task,
- 'categories_list' => $this->category->getList($project['id']),
- 'project' => $project,
- )));
- }
-
- /**
- * Validate a category modification
- *
- * @access public
- */
- public function updateCategory()
- {
- $values = $this->request->getValues();
-
- list($valid, ) = $this->taskValidator->validateCategoryModification($values);
-
- if ($valid && $this->taskModification->update($values)) {
- $this->flash->success(t('Task updated successfully.'));
- } else {
- $this->flash->failure(t('Unable to update your task.'));
- }
-
- $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id'])));
- }
-
- /**
- * Screenshot popover
- *
- * @access public
- */
- public function screenshot()
- {
- $task = $this->getTask();
-
- $this->response->html($this->template->render('task_file/screenshot', array(
- 'task' => $task,
- )));
- }
-
- /**
- * Confirmation before to close all column tasks
- *
- * @access public
- */
- public function confirmCloseColumnTasks()
- {
- $project = $this->getProject();
- $column_id = $this->request->getIntegerParam('column_id');
- $swimlane_id = $this->request->getIntegerParam('swimlane_id');
-
- $this->response->html($this->template->render('board/popover_close_all_tasks_column', array(
- 'project' => $project,
- 'nb_tasks' => $this->taskFinder->countByColumnAndSwimlaneId($project['id'], $column_id, $swimlane_id),
- 'column' => $this->column->getColumnTitleById($column_id),
- 'swimlane' => $this->swimlane->getNameById($swimlane_id) ?: t($project['default_swimlane']),
- 'values' => array('column_id' => $column_id, 'swimlane_id' => $swimlane_id),
- )));
- }
-
- /**
- * Close all column tasks
- *
- * @access public
- */
- public function closeColumnTasks()
- {
- $project = $this->getProject();
- $values = $this->request->getValues();
-
- $this->taskStatus->closeTasksBySwimlaneAndColumn($values['swimlane_id'], $values['column_id']);
- $this->flash->success(t('All tasks of the column "%s" and the swimlane "%s" have been closed successfully.', $this->column->getColumnTitleById($values['column_id']), $this->swimlane->getNameById($values['swimlane_id']) ?: t($project['default_swimlane'])));
- $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id'])));
- }
-}
diff --git a/app/Controller/BoardPopoverController.php b/app/Controller/BoardPopoverController.php
new file mode 100644
index 00000000..a0f5ae12
--- /dev/null
+++ b/app/Controller/BoardPopoverController.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Board Popover Controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class BoardPopoverController extends BaseController
+{
+ /**
+ * Confirmation before to close all column tasks
+ *
+ * @access public
+ */
+ public function confirmCloseColumnTasks()
+ {
+ $project = $this->getProject();
+ $column_id = $this->request->getIntegerParam('column_id');
+ $swimlane_id = $this->request->getIntegerParam('swimlane_id');
+
+ $this->response->html($this->template->render('board_popover/close_all_tasks_column', array(
+ 'project' => $project,
+ 'nb_tasks' => $this->taskFinderModel->countByColumnAndSwimlaneId($project['id'], $column_id, $swimlane_id),
+ 'column' => $this->columnModel->getColumnTitleById($column_id),
+ 'swimlane' => $this->swimlaneModel->getNameById($swimlane_id) ?: t($project['default_swimlane']),
+ 'values' => array('column_id' => $column_id, 'swimlane_id' => $swimlane_id),
+ )));
+ }
+
+ /**
+ * Close all column tasks
+ *
+ * @access public
+ */
+ public function closeColumnTasks()
+ {
+ $project = $this->getProject();
+ $values = $this->request->getValues();
+
+ $this->taskStatusModel->closeTasksBySwimlaneAndColumn($values['swimlane_id'], $values['column_id']);
+ $this->flash->success(t('All tasks of the column "%s" and the swimlane "%s" have been closed successfully.', $this->columnModel->getColumnTitleById($values['column_id']), $this->swimlaneModel->getNameById($values['swimlane_id']) ?: t($project['default_swimlane'])));
+ $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id'])));
+ }
+}
diff --git a/app/Controller/BoardTooltip.php b/app/Controller/BoardTooltipController.php
index c7819bc1..2a947027 100644
--- a/app/Controller/BoardTooltip.php
+++ b/app/Controller/BoardTooltipController.php
@@ -5,10 +5,10 @@ namespace Kanboard\Controller;
/**
* Board Tooltip
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class BoardTooltip extends Base
+class BoardTooltipController extends BaseController
{
/**
* Get links on mouseover
@@ -19,7 +19,7 @@ class BoardTooltip extends Base
{
$task = $this->getTask();
$this->response->html($this->template->render('board/tooltip_tasklinks', array(
- 'links' => $this->taskLink->getAllGroupedByLabel($task['id']),
+ 'links' => $this->taskLinkModel->getAllGroupedByLabel($task['id']),
'task' => $task,
)));
}
@@ -33,7 +33,7 @@ class BoardTooltip extends Base
{
$task = $this->getTask();
$this->response->html($this->template->render('board/tooltip_external_links', array(
- 'links' => $this->taskExternalLink->getAll($task['id']),
+ 'links' => $this->taskExternalLinkModel->getAll($task['id']),
'task' => $task,
)));
}
@@ -47,7 +47,7 @@ class BoardTooltip extends Base
{
$task = $this->getTask();
$this->response->html($this->template->render('board/tooltip_subtasks', array(
- 'subtasks' => $this->subtask->getAll($task['id']),
+ 'subtasks' => $this->subtaskModel->getAll($task['id']),
'task' => $task,
)));
}
@@ -62,7 +62,7 @@ class BoardTooltip extends Base
$task = $this->getTask();
$this->response->html($this->template->render('board/tooltip_files', array(
- 'files' => $this->taskFile->getAll($task['id']),
+ 'files' => $this->taskFileModel->getAll($task['id']),
'task' => $task,
)));
}
@@ -78,7 +78,7 @@ class BoardTooltip extends Base
$this->response->html($this->template->render('board/tooltip_comments', array(
'task' => $task,
- 'comments' => $this->comment->getAll($task['id'], $this->userSession->getCommentSorting())
+ 'comments' => $this->commentModel->getAll($task['id'], $this->userSession->getCommentSorting())
)));
}
@@ -107,9 +107,9 @@ class BoardTooltip extends Base
$this->response->html($this->template->render('task_recurrence/info', array(
'task' => $task,
- 'recurrence_trigger_list' => $this->task->getRecurrenceTriggerList(),
- 'recurrence_timeframe_list' => $this->task->getRecurrenceTimeframeList(),
- 'recurrence_basedate_list' => $this->task->getRecurrenceBasedateList(),
+ 'recurrence_trigger_list' => $this->taskModel->getRecurrenceTriggerList(),
+ 'recurrence_timeframe_list' => $this->taskModel->getRecurrenceTimeframeList(),
+ 'recurrence_basedate_list' => $this->taskModel->getRecurrenceBasedateList(),
)));
}
@@ -121,7 +121,7 @@ class BoardTooltip extends Base
public function swimlane()
{
$this->getProject();
- $swimlane = $this->swimlane->getById($this->request->getIntegerParam('swimlane_id'));
+ $swimlane = $this->swimlaneModel->getById($this->request->getIntegerParam('swimlane_id'));
$this->response->html($this->template->render('board/tooltip_description', array('task' => $swimlane)));
}
}
diff --git a/app/Controller/BoardViewController.php b/app/Controller/BoardViewController.php
new file mode 100644
index 00000000..496fa995
--- /dev/null
+++ b/app/Controller/BoardViewController.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Controller\AccessForbiddenException;
+use Kanboard\Formatter\BoardFormatter;
+
+/**
+ * Board controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class BoardViewController extends BaseController
+{
+ /**
+ * Display the public version of a board
+ * Access checked by a simple token, no user login, read only, auto-refresh
+ *
+ * @access public
+ */
+ public function readonly()
+ {
+ $token = $this->request->getStringParam('token');
+ $project = $this->projectModel->getByToken($token);
+
+ if (empty($project)) {
+ throw AccessForbiddenException::getInstance()->withoutLayout();
+ }
+
+ $this->response->html($this->helper->layout->app('board/view_public', array(
+ 'project' => $project,
+ 'swimlanes' => $this->boardModel->getBoard($project['id']),
+ 'title' => $project['name'],
+ 'description' => $project['description'],
+ 'no_layout' => true,
+ 'not_editable' => true,
+ 'board_public_refresh_interval' => $this->configModel->get('board_public_refresh_interval'),
+ 'board_private_refresh_interval' => $this->configModel->get('board_private_refresh_interval'),
+ 'board_highlight_period' => $this->configModel->get('board_highlight_period'),
+ )));
+ }
+
+ /**
+ * Show a board for a given project
+ *
+ * @access public
+ */
+ public function show()
+ {
+ $project = $this->getProject();
+ $search = $this->helper->projectHeader->getSearchQuery($project);
+
+ $this->response->html($this->helper->layout->app('board/view_private', array(
+ 'project' => $project,
+ 'title' => $project['name'],
+ 'description' => $this->helper->projectHeader->getDescription($project),
+ 'board_private_refresh_interval' => $this->configModel->get('board_private_refresh_interval'),
+ 'board_highlight_period' => $this->configModel->get('board_highlight_period'),
+ 'swimlanes' => $this->taskLexer
+ ->build($search)
+ ->format(BoardFormatter::getInstance($this->container)->setProjectId($project['id']))
+ )));
+ }
+}
diff --git a/app/Controller/Calendar.php b/app/Controller/CalendarController.php
index 2517286d..e5114f02 100644
--- a/app/Controller/Calendar.php
+++ b/app/Controller/CalendarController.php
@@ -5,16 +5,16 @@ namespace Kanboard\Controller;
use Kanboard\Filter\TaskAssigneeFilter;
use Kanboard\Filter\TaskProjectFilter;
use Kanboard\Filter\TaskStatusFilter;
-use Kanboard\Model\Task as TaskModel;
+use Kanboard\Model\TaskModel;
/**
- * Project Calendar controller
+ * Calendar Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
* @author Timo Litzbarski
*/
-class Calendar extends Base
+class CalendarController extends BaseController
{
/**
* Show calendar view for projects
@@ -29,7 +29,7 @@ class Calendar extends Base
'project' => $project,
'title' => $project['name'],
'description' => $this->helper->projectHeader->getDescription($project),
- 'check_interval' => $this->config->get('board_private_refresh_interval'),
+ 'check_interval' => $this->configModel->get('board_private_refresh_interval'),
)));
}
@@ -75,7 +75,7 @@ class Calendar extends Base
$events = $this->helper->calendar->getTaskDateDueEvents(clone($queryBuilder), $start, $end);
$events = array_merge($events, $this->helper->calendar->getTaskEvents(clone($queryBuilder), $start, $end));
- if ($this->config->get('calendar_user_subtasks_time_tracking') == 1) {
+ if ($this->configModel->get('calendar_user_subtasks_time_tracking') == 1) {
$events = array_merge($events, $this->helper->calendar->getSubtaskTimeTrackingEvents($user_id, $start, $end));
}
@@ -98,7 +98,7 @@ class Calendar extends Base
if ($this->request->isAjax() && $this->request->isPost()) {
$values = $this->request->getJson();
- $this->taskModification->update(array(
+ $this->taskModificationModel->update(array(
'id' => $values['task_id'],
'date_due' => substr($values['date_due'], 0, 10),
));
diff --git a/app/Controller/Captcha.php b/app/Controller/CaptchaController.php
index fcf081ea..43b2f823 100644
--- a/app/Controller/Captcha.php
+++ b/app/Controller/CaptchaController.php
@@ -7,10 +7,10 @@ use Gregwar\Captcha\CaptchaBuilder;
/**
* Captcha Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Captcha extends Base
+class CaptchaController extends BaseController
{
/**
* Display captcha image
@@ -19,7 +19,7 @@ class Captcha extends Base
*/
public function image()
{
- $this->response->contentType('image/jpeg');
+ $this->response->withContentType('image/jpeg')->send();
$builder = new CaptchaBuilder;
$builder->build();
diff --git a/app/Controller/Category.php b/app/Controller/CategoryController.php
index 258a3b78..dd6e1c35 100644
--- a/app/Controller/Category.php
+++ b/app/Controller/CategoryController.php
@@ -2,28 +2,29 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\PageNotFoundException;
+
/**
- * Category management
+ * Category Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Category extends Base
+class CategoryController extends BaseController
{
/**
* Get the category (common method between actions)
*
* @access private
- * @param integer $project_id
* @return array
+ * @throws PageNotFoundException
*/
- private function getCategory($project_id)
+ private function getCategory()
{
- $category = $this->category->getById($this->request->getIntegerParam('category_id'));
+ $category = $this->categoryModel->getById($this->request->getIntegerParam('category_id'));
if (empty($category)) {
- $this->flash->failure(t('Category not found.'));
- $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project_id)));
+ throw new PageNotFoundException();
}
return $category;
@@ -33,13 +34,16 @@ class Category extends Base
* List of categories for a given project
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws PageNotFoundException
*/
public function index(array $values = array(), array $errors = array())
{
$project = $this->getProject();
$this->response->html($this->helper->layout->project('category/index', array(
- 'categories' => $this->category->getList($project['id'], false),
+ 'categories' => $this->categoryModel->getList($project['id'], false),
'values' => $values + array('project_id' => $project['id']),
'errors' => $errors,
'project' => $project,
@@ -60,26 +64,29 @@ class Category extends Base
list($valid, $errors) = $this->categoryValidator->validateCreation($values);
if ($valid) {
- if ($this->category->create($values)) {
+ if ($this->categoryModel->create($values) !== false) {
$this->flash->success(t('Your category have been created successfully.'));
- $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
+ return $this->response->redirect($this->helper->url->to('CategoryController', 'index', array('project_id' => $project['id'])));
} else {
$this->flash->failure(t('Unable to create your category.'));
}
}
- $this->index($values, $errors);
+ return $this->index($values, $errors);
}
/**
* Edit a category (display the form)
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws PageNotFoundException
*/
public function edit(array $values = array(), array $errors = array())
{
$project = $this->getProject();
- $category = $this->getCategory($project['id']);
+ $category = $this->getCategory();
$this->response->html($this->helper->layout->project('category/edit', array(
'values' => empty($values) ? $category : $values,
@@ -102,15 +109,15 @@ class Category extends Base
list($valid, $errors) = $this->categoryValidator->validateModification($values);
if ($valid) {
- if ($this->category->update($values)) {
+ if ($this->categoryModel->update($values)) {
$this->flash->success(t('Your category have been updated successfully.'));
- $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
+ return $this->response->redirect($this->helper->url->to('CategoryController', 'index', array('project_id' => $project['id'])));
} else {
$this->flash->failure(t('Unable to update your category.'));
}
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
@@ -121,7 +128,7 @@ class Category extends Base
public function confirm()
{
$project = $this->getProject();
- $category = $this->getCategory($project['id']);
+ $category = $this->getCategory();
$this->response->html($this->helper->layout->project('category/remove', array(
'project' => $project,
@@ -139,14 +146,14 @@ class Category extends Base
{
$this->checkCSRFParam();
$project = $this->getProject();
- $category = $this->getCategory($project['id']);
+ $category = $this->getCategory();
- if ($this->category->remove($category['id'])) {
+ if ($this->categoryModel->remove($category['id'])) {
$this->flash->success(t('Category removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this category.'));
}
- $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('CategoryController', 'index', array('project_id' => $project['id'])));
}
}
diff --git a/app/Controller/Column.php b/app/Controller/ColumnController.php
index bbe12fe1..95fbcaaa 100644
--- a/app/Controller/Column.php
+++ b/app/Controller/ColumnController.php
@@ -2,13 +2,15 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
+
/**
- * Column controller
+ * Column Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Column extends Base
+class ColumnController extends BaseController
{
/**
* Display columns list
@@ -18,7 +20,7 @@ class Column extends Base
public function index()
{
$project = $this->getProject();
- $columns = $this->column->getAll($project['id']);
+ $columns = $this->columnModel->getAll($project['id']);
$this->response->html($this->helper->layout->project('column/index', array(
'columns' => $columns,
@@ -31,6 +33,9 @@ class Column extends Base
* Show form to create a new column
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function create(array $values = array(), array $errors = array())
{
@@ -61,15 +66,15 @@ class Column extends Base
list($valid, $errors) = $this->columnValidator->validateCreation($values);
if ($valid) {
- if ($this->column->create($project['id'], $values['title'], $values['task_limit'], $values['description'])) {
+ if ($this->columnModel->create($project['id'], $values['title'], $values['task_limit'], $values['description']) !== false) {
$this->flash->success(t('Column created successfully.'));
- return $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])), true);
+ return $this->response->redirect($this->helper->url->to('ColumnController', 'index', array('project_id' => $project['id'])), true);
} else {
$errors['title'] = array(t('Another column with the same name exists in the project'));
}
}
- $this->create($values, $errors);
+ return $this->create($values, $errors);
}
/**
@@ -82,7 +87,7 @@ class Column extends Base
public function edit(array $values = array(), array $errors = array())
{
$project = $this->getProject();
- $column = $this->column->getById($this->request->getIntegerParam('column_id'));
+ $column = $this->columnModel->getById($this->request->getIntegerParam('column_id'));
$this->response->html($this->helper->layout->project('column/edit', array(
'errors' => $errors,
@@ -106,15 +111,15 @@ class Column extends Base
list($valid, $errors) = $this->columnValidator->validateModification($values);
if ($valid) {
- if ($this->column->update($values['id'], $values['title'], $values['task_limit'], $values['description'])) {
+ if ($this->columnModel->update($values['id'], $values['title'], $values['task_limit'], $values['description'])) {
$this->flash->success(t('Board updated successfully.'));
- $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
+ return $this->response->redirect($this->helper->url->to('ColumnController', 'index', array('project_id' => $project['id'])));
} else {
$this->flash->failure(t('Unable to update this board.'));
}
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
@@ -128,11 +133,11 @@ class Column extends Base
$values = $this->request->getJson();
if (! empty($values) && isset($values['column_id']) && isset($values['position'])) {
- $result = $this->column->changePosition($project['id'], $values['column_id'], $values['position']);
- return $this->response->json(array('result' => $result));
+ $result = $this->columnModel->changePosition($project['id'], $values['column_id'], $values['position']);
+ $this->response->json(array('result' => $result));
+ } else {
+ throw new AccessForbiddenException();
}
-
- $this->forbidden();
}
/**
@@ -145,7 +150,7 @@ class Column extends Base
$project = $this->getProject();
$this->response->html($this->helper->layout->project('column/remove', array(
- 'column' => $this->column->getById($this->request->getIntegerParam('column_id')),
+ 'column' => $this->columnModel->getById($this->request->getIntegerParam('column_id')),
'project' => $project,
'title' => t('Remove a column from a board')
)));
@@ -162,12 +167,12 @@ class Column extends Base
$this->checkCSRFParam();
$column_id = $this->request->getIntegerParam('column_id');
- if ($this->column->remove($column_id)) {
+ if ($this->columnModel->remove($column_id)) {
$this->flash->success(t('Column removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this column.'));
}
- $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ColumnController', 'index', array('project_id' => $project['id'])));
}
}
diff --git a/app/Controller/Comment.php b/app/Controller/CommentController.php
index 0b39f390..2a8c258a 100644
--- a/app/Controller/Comment.php
+++ b/app/Controller/CommentController.php
@@ -2,30 +2,35 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
+use Kanboard\Core\Controller\PageNotFoundException;
+
/**
- * Comment controller
+ * Comment Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Comment extends Base
+class CommentController extends BaseController
{
/**
* Get the current comment
*
* @access private
* @return array
+ * @throws PageNotFoundException
+ * @throws AccessForbiddenException
*/
private function getComment()
{
- $comment = $this->comment->getById($this->request->getIntegerParam('comment_id'));
+ $comment = $this->commentModel->getById($this->request->getIntegerParam('comment_id'));
if (empty($comment)) {
- return $this->notfound();
+ throw new PageNotFoundException();
}
if (! $this->userSession->isAdmin() && $comment['user_id'] != $this->userSession->getId()) {
- return $this->forbidden();
+ throw new AccessForbiddenException();
}
return $comment;
@@ -35,6 +40,10 @@ class Comment extends Base
* Add comment form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws AccessForbiddenException
+ * @throws PageNotFoundException
*/
public function create(array $values = array(), array $errors = array())
{
@@ -67,22 +76,26 @@ class Comment extends Base
list($valid, $errors) = $this->commentValidator->validateCreation($values);
if ($valid) {
- if ($this->comment->create($values)) {
+ if ($this->commentModel->create($values) !== false) {
$this->flash->success(t('Comment added successfully.'));
} else {
$this->flash->failure(t('Unable to create your comment.'));
}
- return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'), true);
}
- $this->create($values, $errors);
+ return $this->create($values, $errors);
}
/**
* Edit a comment
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws AccessForbiddenException
+ * @throws PageNotFoundException
*/
public function edit(array $values = array(), array $errors = array())
{
@@ -112,16 +125,16 @@ class Comment extends Base
list($valid, $errors) = $this->commentValidator->validateModification($values);
if ($valid) {
- if ($this->comment->update($values)) {
+ if ($this->commentModel->update($values)) {
$this->flash->success(t('Comment updated successfully.'));
} else {
$this->flash->failure(t('Unable to update your comment.'));
}
- return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), false);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), false);
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
@@ -152,13 +165,13 @@ class Comment extends Base
$task = $this->getTask();
$comment = $this->getComment();
- if ($this->comment->remove($comment['id'])) {
+ if ($this->commentModel->remove($comment['id'])) {
$this->flash->success(t('Comment removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this comment.'));
}
- $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'));
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'));
}
/**
@@ -173,6 +186,6 @@ class Comment extends Base
$order = $this->userSession->getCommentSorting() === 'ASC' ? 'DESC' : 'ASC';
$this->userSession->setCommentSorting($order);
- $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'));
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'));
}
}
diff --git a/app/Controller/Config.php b/app/Controller/ConfigController.php
index a1b8c2af..8bcf4c35 100644
--- a/app/Controller/Config.php
+++ b/app/Controller/ConfigController.php
@@ -3,56 +3,14 @@
namespace Kanboard\Controller;
/**
- * Config controller
+ * Config Controller
*
- * @package controller
+ * @package Kanboard/Controller
* @author Frederic Guillot
*/
-class Config extends Base
+class ConfigController extends BaseController
{
/**
- * Common method between pages
- *
- * @access private
- * @param string $redirect Action to redirect after saving the form
- */
- private function common($redirect)
- {
- if ($this->request->isPost()) {
- $values = $this->request->getValues();
-
- switch ($redirect) {
- case 'application':
- $values += array('password_reset' => 0);
- break;
- case 'project':
- $values += array(
- 'subtask_restriction' => 0,
- 'subtask_time_tracking' => 0,
- 'cfd_include_closed_tasks' => 0,
- 'disable_private_project' => 0,
- );
- break;
- case 'integrations':
- $values += array('integration_gravatar' => 0);
- break;
- case 'calendar':
- $values += array('calendar_user_subtasks_time_tracking' => 0);
- break;
- }
-
- if ($this->config->save($values)) {
- $this->config->reload();
- $this->flash->success(t('Settings saved successfully.'));
- } else {
- $this->flash->failure(t('Unable to save your settings.'));
- }
-
- $this->response->redirect($this->helper->url->to('config', $redirect));
- }
- }
-
- /**
* Display the about page
*
* @access public
@@ -60,7 +18,7 @@ class Config extends Base
public function index()
{
$this->response->html($this->helper->layout->config('config/about', array(
- 'db_size' => $this->config->getDatabaseSize(),
+ 'db_size' => $this->configModel->getDatabaseSize(),
'db_version' => $this->db->getDriver()->getDatabaseVersion(),
'user_agent' => $this->request->getServerVariable('HTTP_USER_AGENT'),
'title' => t('Settings').' &gt; '.t('About'),
@@ -68,16 +26,42 @@ class Config extends Base
}
/**
- * Display the plugin page
+ * Save settings
*
- * @access public
*/
- public function plugins()
+ public function save()
{
- $this->response->html($this->helper->layout->config('config/plugins', array(
- 'plugins' => $this->pluginLoader->plugins,
- 'title' => t('Settings').' &gt; '.t('Plugins'),
- )));
+ $values = $this->request->getValues();
+ $redirect = $this->request->getStringParam('redirect', 'application');
+
+ switch ($redirect) {
+ case 'application':
+ $values += array('password_reset' => 0);
+ break;
+ case 'project':
+ $values += array(
+ 'subtask_restriction' => 0,
+ 'subtask_time_tracking' => 0,
+ 'cfd_include_closed_tasks' => 0,
+ 'disable_private_project' => 0,
+ );
+ break;
+ case 'integrations':
+ $values += array('integration_gravatar' => 0);
+ break;
+ case 'calendar':
+ $values += array('calendar_user_subtasks_time_tracking' => 0);
+ break;
+ }
+
+ if ($this->configModel->save($values)) {
+ $this->languageModel->loadCurrentLanguage();
+ $this->flash->success(t('Settings saved successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to save your settings.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ConfigController', $redirect));
}
/**
@@ -87,11 +71,9 @@ class Config extends Base
*/
public function application()
{
- $this->common('application');
-
$this->response->html($this->helper->layout->config('config/application', array(
- 'languages' => $this->config->getLanguages(),
- 'timezones' => $this->config->getTimezones(),
+ 'languages' => $this->languageModel->getLanguages(),
+ 'timezones' => $this->timezoneModel->getTimezones(),
'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
'datetime_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateTimeFormats()),
'time_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getTimeFormats()),
@@ -106,11 +88,9 @@ class Config extends Base
*/
public function project()
{
- $this->common('project');
-
$this->response->html($this->helper->layout->config('config/project', array(
- 'colors' => $this->color->getList(),
- 'default_columns' => implode(', ', $this->board->getDefaultColumns()),
+ 'colors' => $this->colorModel->getList(),
+ 'default_columns' => implode(', ', $this->boardModel->getDefaultColumns()),
'title' => t('Settings').' &gt; '.t('Project settings'),
)));
}
@@ -122,8 +102,6 @@ class Config extends Base
*/
public function board()
{
- $this->common('board');
-
$this->response->html($this->helper->layout->config('config/board', array(
'title' => t('Settings').' &gt; '.t('Board settings'),
)));
@@ -136,8 +114,6 @@ class Config extends Base
*/
public function calendar()
{
- $this->common('calendar');
-
$this->response->html($this->helper->layout->config('config/calendar', array(
'title' => t('Settings').' &gt; '.t('Calendar settings'),
)));
@@ -150,8 +126,6 @@ class Config extends Base
*/
public function integrations()
{
- $this->common('integrations');
-
$this->response->html($this->helper->layout->config('config/integrations', array(
'title' => t('Settings').' &gt; '.t('Integrations'),
)));
@@ -164,8 +138,6 @@ class Config extends Base
*/
public function webhook()
{
- $this->common('webhook');
-
$this->response->html($this->helper->layout->config('config/webhook', array(
'title' => t('Settings').' &gt; '.t('Webhook settings'),
)));
@@ -191,8 +163,8 @@ class Config extends Base
public function downloadDb()
{
$this->checkCSRFParam();
- $this->response->forceDownload('db.sqlite.gz');
- $this->response->binary($this->config->downloadDatabase());
+ $this->response->withFileDownload('db.sqlite.gz');
+ $this->response->binary($this->configModel->downloadDatabase());
}
/**
@@ -203,9 +175,9 @@ class Config extends Base
public function optimizeDb()
{
$this->checkCSRFParam();
- $this->config->optimizeDatabase();
+ $this->configModel->optimizeDatabase();
$this->flash->success(t('Database optimization done.'));
- $this->response->redirect($this->helper->url->to('config', 'index'));
+ $this->response->redirect($this->helper->url->to('ConfigController', 'index'));
}
/**
@@ -218,9 +190,9 @@ class Config extends Base
$type = $this->request->getStringParam('type');
$this->checkCSRFParam();
- $this->config->regenerateToken($type.'_token');
+ $this->configModel->regenerateToken($type.'_token');
$this->flash->success(t('Token regenerated.'));
- $this->response->redirect($this->helper->url->to('config', $type));
+ $this->response->redirect($this->helper->url->to('ConfigController', $type));
}
}
diff --git a/app/Controller/Currency.php b/app/Controller/CurrencyController.php
index ecaa9834..ad590035 100644
--- a/app/Controller/Currency.php
+++ b/app/Controller/CurrencyController.php
@@ -3,26 +3,28 @@
namespace Kanboard\Controller;
/**
- * Currency controller
+ * Currency Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Currency extends Base
+class CurrencyController extends BaseController
{
/**
* Display all currency rates and form
*
* @access public
+ * @param array $values
+ * @param array $errors
*/
public function index(array $values = array(), array $errors = array())
{
$this->response->html($this->helper->layout->config('currency/index', array(
- 'config_values' => array('application_currency' => $this->config->get('application_currency')),
+ 'config_values' => array('application_currency' => $this->configModel->get('application_currency')),
'values' => $values,
'errors' => $errors,
- 'rates' => $this->currency->getAll(),
- 'currencies' => $this->currency->getCurrencies(),
+ 'rates' => $this->currencyModel->getAll(),
+ 'currencies' => $this->currencyModel->getCurrencies(),
'title' => t('Settings').' &gt; '.t('Currency rates'),
)));
}
@@ -38,15 +40,15 @@ class Currency extends Base
list($valid, $errors) = $this->currencyValidator->validateCreation($values);
if ($valid) {
- if ($this->currency->create($values['currency'], $values['rate'])) {
+ if ($this->currencyModel->create($values['currency'], $values['rate'])) {
$this->flash->success(t('The currency rate have been added successfully.'));
- $this->response->redirect($this->helper->url->to('currency', 'index'));
+ return $this->response->redirect($this->helper->url->to('CurrencyController', 'index'));
} else {
$this->flash->failure(t('Unable to add this currency rate.'));
}
}
- $this->index($values, $errors);
+ return $this->index($values, $errors);
}
/**
@@ -58,13 +60,12 @@ class Currency extends Base
{
$values = $this->request->getValues();
- if ($this->config->save($values)) {
- $this->config->reload();
+ if ($this->configModel->save($values)) {
$this->flash->success(t('Settings saved successfully.'));
} else {
$this->flash->failure(t('Unable to save your settings.'));
}
- $this->response->redirect($this->helper->url->to('currency', 'index'));
+ $this->response->redirect($this->helper->url->to('CurrencyController', 'index'));
}
}
diff --git a/app/Controller/Customfilter.php b/app/Controller/CustomFilterController.php
index 41da0b11..e5f674cd 100644
--- a/app/Controller/Customfilter.php
+++ b/app/Controller/CustomFilterController.php
@@ -2,20 +2,25 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
use Kanboard\Core\Security\Role;
/**
- * Custom Filter management
+ * Custom Filter Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Timo Litzbarski
+ * @author Frederic Guillot
*/
-class Customfilter extends Base
+class CustomFilterController extends BaseController
{
/**
* Display list of filters
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function index(array $values = array(), array $errors = array())
{
@@ -25,7 +30,7 @@ class Customfilter extends Base
'values' => $values + array('project_id' => $project['id']),
'errors' => $errors,
'project' => $project,
- 'custom_filters' => $this->customFilter->getAll($project['id'], $this->userSession->getId()),
+ 'custom_filters' => $this->customFilterModel->getAll($project['id'], $this->userSession->getId()),
'title' => t('Custom filters'),
)));
}
@@ -45,15 +50,15 @@ class Customfilter extends Base
list($valid, $errors) = $this->customFilterValidator->validateCreation($values);
if ($valid) {
- if ($this->customFilter->create($values)) {
+ if ($this->customFilterModel->create($values) !== false) {
$this->flash->success(t('Your custom filter have been created successfully.'));
- $this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
+ return $this->response->redirect($this->helper->url->to('CustomFilterController', 'index', array('project_id' => $project['id'])));
} else {
$this->flash->failure(t('Unable to create your custom filter.'));
}
}
- $this->index($values, $errors);
+ return $this->index($values, $errors);
}
/**
@@ -64,7 +69,7 @@ class Customfilter extends Base
public function confirm()
{
$project = $this->getProject();
- $filter = $this->customFilter->getById($this->request->getIntegerParam('filter_id'));
+ $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
$this->response->html($this->helper->layout->project('custom_filter/remove', array(
'project' => $project,
@@ -82,28 +87,32 @@ class Customfilter extends Base
{
$this->checkCSRFParam();
$project = $this->getProject();
- $filter = $this->customFilter->getById($this->request->getIntegerParam('filter_id'));
+ $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
$this->checkPermission($project, $filter);
- if ($this->customFilter->remove($filter['id'])) {
+ if ($this->customFilterModel->remove($filter['id'])) {
$this->flash->success(t('Custom filter removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this custom filter.'));
}
- $this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('CustomFilterController', 'index', array('project_id' => $project['id'])));
}
/**
* Edit a custom filter (display the form)
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function edit(array $values = array(), array $errors = array())
{
$project = $this->getProject();
- $filter = $this->customFilter->getById($this->request->getIntegerParam('filter_id'));
+ $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
$this->checkPermission($project, $filter);
@@ -124,7 +133,7 @@ class Customfilter extends Base
public function update()
{
$project = $this->getProject();
- $filter = $this->customFilter->getById($this->request->getIntegerParam('filter_id'));
+ $filter = $this->customFilterModel->getById($this->request->getIntegerParam('filter_id'));
$this->checkPermission($project, $filter);
@@ -141,23 +150,23 @@ class Customfilter extends Base
list($valid, $errors) = $this->customFilterValidator->validateModification($values);
if ($valid) {
- if ($this->customFilter->update($values)) {
+ if ($this->customFilterModel->update($values)) {
$this->flash->success(t('Your custom filter have been updated successfully.'));
- $this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
+ return $this->response->redirect($this->helper->url->to('CustomFilterController', 'index', array('project_id' => $project['id'])));
} else {
$this->flash->failure(t('Unable to update custom filter.'));
}
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
private function checkPermission(array $project, array $filter)
{
$user_id = $this->userSession->getId();
- if ($filter['user_id'] != $user_id && ($this->projectUserRole->getUserRole($project['id'], $user_id) === Role::PROJECT_MANAGER || ! $this->userSession->isAdmin())) {
- $this->forbidden();
+ if ($filter['user_id'] != $user_id && ($this->projectUserRoleModel->getUserRole($project['id'], $user_id) === Role::PROJECT_MANAGER || ! $this->userSession->isAdmin())) {
+ throw new AccessForbiddenException();
}
}
}
diff --git a/app/Controller/App.php b/app/Controller/DashboardController.php
index 01f733ff..44874546 100644
--- a/app/Controller/App.php
+++ b/app/Controller/DashboardController.php
@@ -2,16 +2,16 @@
namespace Kanboard\Controller;
-use Kanboard\Model\Project as ProjectModel;
-use Kanboard\Model\Subtask as SubtaskModel;
+use Kanboard\Model\ProjectModel;
+use Kanboard\Model\SubtaskModel;
/**
- * Application controller
+ * Dashboard Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class App extends Base
+class DashboardController extends BaseController
{
/**
* Get project pagination
@@ -25,10 +25,10 @@ class App extends Base
private function getProjectPaginator($user_id, $action, $max)
{
return $this->paginator
- ->setUrl('app', $action, array('pagination' => 'projects', 'user_id' => $user_id))
+ ->setUrl('DashboardController', $action, array('pagination' => 'projects', 'user_id' => $user_id))
->setMax($max)
->setOrder(ProjectModel::TABLE.'.name')
- ->setQuery($this->project->getQueryColumnStats($this->projectPermission->getActiveProjectIds($user_id)))
+ ->setQuery($this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id)))
->calculateOnlyIf($this->request->getStringParam('pagination') === 'projects');
}
@@ -44,10 +44,10 @@ class App extends Base
private function getTaskPaginator($user_id, $action, $max)
{
return $this->paginator
- ->setUrl('app', $action, array('pagination' => 'tasks', 'user_id' => $user_id))
+ ->setUrl('DashboardController', $action, array('pagination' => 'tasks', 'user_id' => $user_id))
->setMax($max)
->setOrder('tasks.id')
- ->setQuery($this->taskFinder->getUserQuery($user_id))
+ ->setQuery($this->taskFinderModel->getUserQuery($user_id))
->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks');
}
@@ -63,37 +63,27 @@ class App extends Base
private function getSubtaskPaginator($user_id, $action, $max)
{
return $this->paginator
- ->setUrl('app', $action, array('pagination' => 'subtasks', 'user_id' => $user_id))
+ ->setUrl('DashboardController', $action, array('pagination' => 'subtasks', 'user_id' => $user_id))
->setMax($max)
->setOrder('tasks.id')
- ->setQuery($this->subtask->getUserQuery($user_id, array(SubTaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS)))
+ ->setQuery($this->subtaskModel->getUserQuery($user_id, array(SubTaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS)))
->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
}
/**
- * Check if the user is connected
- *
- * @access public
- */
- public function status()
- {
- $this->response->text('OK');
- }
-
- /**
* Dashboard overview
*
* @access public
*/
- public function index()
+ public function show()
{
$user = $this->getUser();
- $this->response->html($this->helper->layout->dashboard('app/overview', array(
+ $this->response->html($this->helper->layout->dashboard('dashboard/show', array(
'title' => t('Dashboard'),
- 'project_paginator' => $this->getProjectPaginator($user['id'], 'index', 10),
- 'task_paginator' => $this->getTaskPaginator($user['id'], 'index', 10),
- 'subtask_paginator' => $this->getSubtaskPaginator($user['id'], 'index', 10),
+ 'project_paginator' => $this->getProjectPaginator($user['id'], 'show', 10),
+ 'task_paginator' => $this->getTaskPaginator($user['id'], 'show', 10),
+ 'subtask_paginator' => $this->getSubtaskPaginator($user['id'], 'show', 10),
'user' => $user,
)));
}
@@ -107,7 +97,7 @@ class App extends Base
{
$user = $this->getUser();
- $this->response->html($this->helper->layout->dashboard('app/tasks', array(
+ $this->response->html($this->helper->layout->dashboard('dashboard/tasks', array(
'title' => t('My tasks'),
'paginator' => $this->getTaskPaginator($user['id'], 'tasks', 50),
'user' => $user,
@@ -123,7 +113,7 @@ class App extends Base
{
$user = $this->getUser();
- $this->response->html($this->helper->layout->dashboard('app/subtasks', array(
+ $this->response->html($this->helper->layout->dashboard('dashboard/subtasks', array(
'title' => t('My subtasks'),
'paginator' => $this->getSubtaskPaginator($user['id'], 'subtasks', 50),
'user' => $user,
@@ -139,7 +129,7 @@ class App extends Base
{
$user = $this->getUser();
- $this->response->html($this->helper->layout->dashboard('app/projects', array(
+ $this->response->html($this->helper->layout->dashboard('dashboard/projects', array(
'title' => t('My projects'),
'paginator' => $this->getProjectPaginator($user['id'], 'projects', 25),
'user' => $user,
@@ -155,9 +145,9 @@ class App extends Base
{
$user = $this->getUser();
- $this->response->html($this->helper->layout->dashboard('app/activity', array(
+ $this->response->html($this->helper->layout->dashboard('dashboard/activity', array(
'title' => t('My activity stream'),
- 'events' => $this->helper->projectActivity->getProjectsEvents($this->projectPermission->getActiveProjectIds($user['id']), 100),
+ 'events' => $this->helper->projectActivity->getProjectsEvents($this->projectPermissionModel->getActiveProjectIds($user['id']), 100),
'user' => $user,
)));
}
@@ -169,7 +159,7 @@ class App extends Base
*/
public function calendar()
{
- $this->response->html($this->helper->layout->dashboard('app/calendar', array(
+ $this->response->html($this->helper->layout->dashboard('dashboard/calendar', array(
'title' => t('My calendar'),
'user' => $this->getUser(),
)));
@@ -184,9 +174,9 @@ class App extends Base
{
$user = $this->getUser();
- $this->response->html($this->helper->layout->dashboard('app/notifications', array(
+ $this->response->html($this->helper->layout->dashboard('dashboard/notifications', array(
'title' => t('My notifications'),
- 'notifications' => $this->userUnreadNotification->getAll($user['id']),
+ 'notifications' => $this->userUnreadNotificationModel->getAll($user['id']),
'user' => $user,
)));
}
diff --git a/app/Controller/Doc.php b/app/Controller/DocumentationController.php
index 00b9e585..d86fb3c8 100644
--- a/app/Controller/Doc.php
+++ b/app/Controller/DocumentationController.php
@@ -7,10 +7,10 @@ use Parsedown;
/**
* Documentation Viewer
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Doc extends Base
+class DocumentationController extends BaseController
{
public function show()
{
@@ -20,7 +20,7 @@ class Doc extends Base
$page = 'index';
}
- if ($this->config->getCurrentLanguage() === 'fr_FR') {
+ if ($this->languageModel->getCurrentLanguage() === 'fr_FR') {
$filename = __DIR__.'/../../doc/fr/' . $page . '.markdown';
} else {
$filename = __DIR__ . '/../../doc/' . $page . '.markdown';
@@ -71,7 +71,7 @@ class Doc extends Base
*/
public function replaceMarkdownUrl(array $matches)
{
- return '('.$this->helper->url->to('doc', 'show', array('file' => str_replace('.markdown', '', $matches[1]))).')';
+ return '('.$this->helper->url->to('DocumentationController', 'show', array('file' => str_replace('.markdown', '', $matches[1]))).')';
}
/**
@@ -83,7 +83,7 @@ class Doc extends Base
*/
public function replaceImageUrl(array $matches)
{
- if ($this->config->getCurrentLanguage() === 'fr_FR') {
+ if ($this->languageModel->getCurrentLanguage() === 'fr_FR') {
return '('.$this->helper->url->base().'doc/fr/'.$matches[1].')';
}
diff --git a/app/Controller/Export.php b/app/Controller/ExportController.php
index c2ff652e..b2fe0ebd 100644
--- a/app/Controller/Export.php
+++ b/app/Controller/ExportController.php
@@ -3,17 +3,23 @@
namespace Kanboard\Controller;
/**
- * Export controller
+ * Export Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Export extends Base
+class ExportController extends BaseController
{
/**
* Common export method
*
* @access private
+ * @param string $model
+ * @param string $method
+ * @param string $filename
+ * @param string $action
+ * @param string $page_title
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
private function common($model, $method, $filename, $action, $page_title)
{
@@ -23,20 +29,20 @@ class Export extends Base
if ($from && $to) {
$data = $this->$model->$method($project['id'], $from, $to);
- $this->response->forceDownload($filename.'.csv');
+ $this->response->withFileDownload($filename.'.csv');
$this->response->csv($data);
}
$this->response->html($this->helper->layout->project('export/'.$action, array(
'values' => array(
- 'controller' => 'export',
+ 'controller' => 'ExportController',
'action' => $action,
'project_id' => $project['id'],
'from' => $from,
'to' => $to,
),
'errors' => array(),
- 'date_format' => $this->config->get('application_date_format'),
+ 'date_format' => $this->configModel->get('application_date_format'),
'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
'project' => $project,
'title' => $page_title,
diff --git a/app/Controller/Feed.php b/app/Controller/FeedController.php
index f8b3d320..cf2b1088 100644
--- a/app/Controller/Feed.php
+++ b/app/Controller/FeedController.php
@@ -2,13 +2,15 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
+
/**
* Atom/RSS Feed controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Feed extends Base
+class FeedController extends BaseController
{
/**
* RSS feed for a user
@@ -18,15 +20,15 @@ class Feed extends Base
public function user()
{
$token = $this->request->getStringParam('token');
- $user = $this->user->getByToken($token);
+ $user = $this->userModel->getByToken($token);
// Token verification
if (empty($user)) {
- $this->forbidden(true);
+ throw AccessForbiddenException::getInstance()->withoutLayout();
}
$this->response->xml($this->template->render('feed/user', array(
- 'events' => $this->helper->projectActivity->getProjectsEvents($this->projectPermission->getActiveProjectIds($user['id'])),
+ 'events' => $this->helper->projectActivity->getProjectsEvents($this->projectPermissionModel->getActiveProjectIds($user['id'])),
'user' => $user,
)));
}
@@ -39,11 +41,10 @@ class Feed extends Base
public function project()
{
$token = $this->request->getStringParam('token');
- $project = $this->project->getByToken($token);
+ $project = $this->projectModel->getByToken($token);
- // Token verification
if (empty($project)) {
- $this->forbidden(true);
+ throw AccessForbiddenException::getInstance()->withoutLayout();
}
$this->response->xml($this->template->render('feed/project', array(
diff --git a/app/Controller/FileViewer.php b/app/Controller/FileViewerController.php
index 3be4ea14..518f5b0b 100644
--- a/app/Controller/FileViewer.php
+++ b/app/Controller/FileViewerController.php
@@ -7,10 +7,10 @@ use Kanboard\Core\ObjectStorage\ObjectStorageException;
/**
* File Viewer Controller
*
- * @package controller
+ * @package Kanbaord\Controller
* @author Frederic Guillot
*/
-class FileViewer extends Base
+class FileViewerController extends BaseController
{
/**
* Get file content from object storage
@@ -24,11 +24,9 @@ class FileViewer extends Base
$content = '';
try {
-
if ($file['is_image'] == 0) {
$content = $this->objectStorage->get($file['path']);
}
-
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());
}
@@ -47,7 +45,7 @@ class FileViewer extends Base
$type = $this->helper->file->getPreviewType($file['name']);
$params = array('file_id' => $file['id'], 'project_id' => $this->request->getIntegerParam('project_id'));
- if ($file['model'] === 'taskFile') {
+ if ($file['model'] === 'taskFileModel') {
$params['task_id'] = $file['task_id'];
}
@@ -68,17 +66,19 @@ class FileViewer extends Base
{
$file = $this->getFile();
$etag = md5($file['path']);
- $this->response->contentType($this->helper->file->getImageMimeType($file['name']));
- $this->response->cache(5 * 86400, $etag);
+ $this->response->withContentType($this->helper->file->getImageMimeType($file['name']));
+ $this->response->withCache(5 * 86400, $etag);
if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
- return $this->response->status(304);
- }
+ $this->response->status(304);
+ } else {
- try {
- $this->objectStorage->output($file['path']);
- } catch (ObjectStorageException $e) {
- $this->logger->error($e->getMessage());
+ try {
+ $this->response->send();
+ $this->objectStorage->output($file['path']);
+ } catch (ObjectStorageException $e) {
+ $this->logger->error($e->getMessage());
+ }
}
}
@@ -94,23 +94,26 @@ class FileViewer extends Base
$filename = $this->$model->getThumbnailPath($file['path']);
$etag = md5($filename);
- $this->response->cache(5 * 86400, $etag);
- $this->response->contentType('image/jpeg');
+ $this->response->withCache(5 * 86400, $etag);
+ $this->response->withContentType('image/jpeg');
if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
- return $this->response->status(304);
- }
+ $this->response->status(304);
+ } else {
- try {
+ $this->response->send();
- $this->objectStorage->output($filename);
- } catch (ObjectStorageException $e) {
- $this->logger->error($e->getMessage());
+ try {
+
+ $this->objectStorage->output($filename);
+ } catch (ObjectStorageException $e) {
+ $this->logger->error($e->getMessage());
- // Try to generate thumbnail on the fly for images uploaded before Kanboard < 1.0.19
- $data = $this->objectStorage->get($file['path']);
- $this->$model->generateThumbnailFromData($file['path'], $data);
- $this->objectStorage->output($this->$model->getThumbnailPath($file['path']));
+ // Try to generate thumbnail on the fly for images uploaded before Kanboard < 1.0.19
+ $data = $this->objectStorage->get($file['path']);
+ $this->$model->generateThumbnailFromData($file['path'], $data);
+ $this->objectStorage->output($this->$model->getThumbnailPath($file['path']));
+ }
}
}
@@ -123,7 +126,8 @@ class FileViewer extends Base
{
try {
$file = $this->getFile();
- $this->response->forceDownload($file['name']);
+ $this->response->withFileDownload($file['name']);
+ $this->response->send();
$this->objectStorage->output($file['path']);
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());
diff --git a/app/Controller/Gantt.php b/app/Controller/Gantt.php
deleted file mode 100644
index 5e9ad55e..00000000
--- a/app/Controller/Gantt.php
+++ /dev/null
@@ -1,162 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-use Kanboard\Filter\ProjectIdsFilter;
-use Kanboard\Filter\ProjectStatusFilter;
-use Kanboard\Filter\ProjectTypeFilter;
-use Kanboard\Filter\TaskProjectFilter;
-use Kanboard\Formatter\ProjectGanttFormatter;
-use Kanboard\Formatter\TaskGanttFormatter;
-use Kanboard\Model\Task as TaskModel;
-use Kanboard\Model\Project as ProjectModel;
-
-/**
- * Gantt controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-class Gantt extends Base
-{
- /**
- * Show Gantt chart for all projects
- */
- public function projects()
- {
- $project_ids = $this->projectPermission->getActiveProjectIds($this->userSession->getId());
- $filter = $this->projectQuery
- ->withFilter(new ProjectTypeFilter(ProjectModel::TYPE_TEAM))
- ->withFilter(new ProjectStatusFilter(ProjectModel::ACTIVE))
- ->withFilter(new ProjectIdsFilter($project_ids));
-
- $filter->getQuery()->asc(ProjectModel::TABLE.'.start_date');
-
- $this->response->html($this->helper->layout->app('gantt/projects', array(
- 'projects' => $filter->format(new ProjectGanttFormatter($this->container)),
- 'title' => t('Gantt chart for all projects'),
- )));
- }
-
- /**
- * Save new project start date and end date
- */
- public function saveProjectDate()
- {
- $values = $this->request->getJson();
-
- $result = $this->project->update(array(
- 'id' => $values['id'],
- 'start_date' => $this->dateParser->getIsoDate(strtotime($values['start'])),
- 'end_date' => $this->dateParser->getIsoDate(strtotime($values['end'])),
- ));
-
- if (! $result) {
- $this->response->json(array('message' => 'Unable to save project'), 400);
- }
-
- $this->response->json(array('message' => 'OK'), 201);
- }
-
- /**
- * Show Gantt chart for one project
- */
- public function project()
- {
- $project = $this->getProject();
- $search = $this->helper->projectHeader->getSearchQuery($project);
- $sorting = $this->request->getStringParam('sorting', 'board');
- $filter = $this->taskLexer->build($search)->withFilter(new TaskProjectFilter($project['id']));
-
- if ($sorting === 'date') {
- $filter->getQuery()->asc(TaskModel::TABLE.'.date_started')->asc(TaskModel::TABLE.'.date_creation');
- } else {
- $filter->getQuery()->asc('column_position')->asc(TaskModel::TABLE.'.position');
- }
-
- $this->response->html($this->helper->layout->app('gantt/project', array(
- 'project' => $project,
- 'title' => $project['name'],
- 'description' => $this->helper->projectHeader->getDescription($project),
- 'sorting' => $sorting,
- 'tasks' => $filter->format(new TaskGanttFormatter($this->container)),
- )));
- }
-
- /**
- * Save new task start date and due date
- */
- public function saveTaskDate()
- {
- $this->getProject();
- $values = $this->request->getJson();
-
- $result = $this->taskModification->update(array(
- 'id' => $values['id'],
- 'date_started' => strtotime($values['start']),
- 'date_due' => strtotime($values['end']),
- ));
-
- if (! $result) {
- $this->response->json(array('message' => 'Unable to save task'), 400);
- }
-
- $this->response->json(array('message' => 'OK'), 201);
- }
-
- /**
- * Simplified form to create a new task
- *
- * @access public
- */
- public function task(array $values = array(), array $errors = array())
- {
- $project = $this->getProject();
-
- $values = $values + array(
- 'project_id' => $project['id'],
- 'column_id' => $this->column->getFirstColumnId($project['id']),
- 'position' => 1
- );
-
- $values = $this->hook->merge('controller:task:form:default', $values, array('default_values' => $values));
- $values = $this->hook->merge('controller:gantt:task:form:default', $values, array('default_values' => $values));
-
- $this->response->html($this->template->render('gantt/task_creation', array(
- 'project' => $project,
- 'errors' => $errors,
- 'values' => $values,
- 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id'], true, false, true),
- 'colors_list' => $this->color->getList(),
- 'categories_list' => $this->category->getList($project['id']),
- 'swimlanes_list' => $this->swimlane->getList($project['id'], false, true),
- 'title' => $project['name'].' &gt; '.t('New task')
- )));
- }
-
- /**
- * Validate and save a new task
- *
- * @access public
- */
- public function saveTask()
- {
- $project = $this->getProject();
- $values = $this->request->getValues();
-
- list($valid, $errors) = $this->taskValidator->validateCreation($values);
-
- if ($valid) {
- $task_id = $this->taskCreation->create($values);
-
- if ($task_id !== false) {
- $this->flash->success(t('Task created successfully.'));
- $this->response->redirect($this->helper->url->to('gantt', 'project', array('project_id' => $project['id'])));
- } else {
- $this->flash->failure(t('Unable to create your task.'));
- }
- }
-
- $this->task($values, $errors);
- }
-}
diff --git a/app/Controller/Group.php b/app/Controller/Group.php
deleted file mode 100644
index fa47f428..00000000
--- a/app/Controller/Group.php
+++ /dev/null
@@ -1,250 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-/**
- * Group Controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-class Group extends Base
-{
- /**
- * List all groups
- *
- * @access public
- */
- public function index()
- {
- $paginator = $this->paginator
- ->setUrl('group', 'index')
- ->setMax(30)
- ->setOrder('name')
- ->setQuery($this->group->getQuery())
- ->calculate();
-
- $this->response->html($this->helper->layout->app('group/index', array(
- 'title' => t('Groups').' ('.$paginator->getTotal().')',
- 'paginator' => $paginator,
- )));
- }
-
- /**
- * List all users
- *
- * @access public
- */
- public function users()
- {
- $group_id = $this->request->getIntegerParam('group_id');
- $group = $this->group->getById($group_id);
-
- $paginator = $this->paginator
- ->setUrl('group', 'users', array('group_id' => $group_id))
- ->setMax(30)
- ->setOrder('username')
- ->setQuery($this->groupMember->getQuery($group_id))
- ->calculate();
-
- $this->response->html($this->helper->layout->app('group/users', array(
- 'title' => t('Members of %s', $group['name']).' ('.$paginator->getTotal().')',
- 'paginator' => $paginator,
- 'group' => $group,
- )));
- }
-
- /**
- * Display a form to create a new group
- *
- * @access public
- */
- public function create(array $values = array(), array $errors = array())
- {
- $this->response->html($this->helper->layout->app('group/create', array(
- 'errors' => $errors,
- 'values' => $values,
- 'title' => t('New group')
- )));
- }
-
- /**
- * Validate and save a new group
- *
- * @access public
- */
- public function save()
- {
- $values = $this->request->getValues();
- list($valid, $errors) = $this->groupValidator->validateCreation($values);
-
- if ($valid) {
- if ($this->group->create($values['name']) !== false) {
- $this->flash->success(t('Group created successfully.'));
- $this->response->redirect($this->helper->url->to('group', 'index'));
- } else {
- $this->flash->failure(t('Unable to create your group.'));
- }
- }
-
- $this->create($values, $errors);
- }
-
- /**
- * Display a form to update a group
- *
- * @access public
- */
- public function edit(array $values = array(), array $errors = array())
- {
- if (empty($values)) {
- $values = $this->group->getById($this->request->getIntegerParam('group_id'));
- }
-
- $this->response->html($this->helper->layout->app('group/edit', array(
- 'errors' => $errors,
- 'values' => $values,
- 'title' => t('Edit group')
- )));
- }
-
- /**
- * Validate and save a group
- *
- * @access public
- */
- public function update()
- {
- $values = $this->request->getValues();
- list($valid, $errors) = $this->groupValidator->validateModification($values);
-
- if ($valid) {
- if ($this->group->update($values) !== false) {
- $this->flash->success(t('Group updated successfully.'));
- $this->response->redirect($this->helper->url->to('group', 'index'));
- } else {
- $this->flash->failure(t('Unable to update your group.'));
- }
- }
-
- $this->edit($values, $errors);
- }
-
- /**
- * Form to associate a user to a group
- *
- * @access public
- */
- public function associate(array $values = array(), array $errors = array())
- {
- $group_id = $this->request->getIntegerParam('group_id');
- $group = $this->group->getbyId($group_id);
-
- if (empty($values)) {
- $values['group_id'] = $group_id;
- }
-
- $this->response->html($this->helper->layout->app('group/associate', array(
- 'users' => $this->user->prepareList($this->groupMember->getNotMembers($group_id)),
- 'group' => $group,
- 'errors' => $errors,
- 'values' => $values,
- 'title' => t('Add group member to "%s"', $group['name']),
- )));
- }
-
- /**
- * Add user to a group
- *
- * @access public
- */
- public function addUser()
- {
- $values = $this->request->getValues();
-
- if (isset($values['group_id']) && isset($values['user_id'])) {
- if ($this->groupMember->addUser($values['group_id'], $values['user_id'])) {
- $this->flash->success(t('Group member added successfully.'));
- $this->response->redirect($this->helper->url->to('group', 'users', array('group_id' => $values['group_id'])));
- } else {
- $this->flash->failure(t('Unable to add group member.'));
- }
- }
-
- $this->associate($values);
- }
-
- /**
- * Confirmation dialog to remove a user from a group
- *
- * @access public
- */
- public function dissociate()
- {
- $group_id = $this->request->getIntegerParam('group_id');
- $user_id = $this->request->getIntegerParam('user_id');
- $group = $this->group->getById($group_id);
- $user = $this->user->getById($user_id);
-
- $this->response->html($this->helper->layout->app('group/dissociate', array(
- 'group' => $group,
- 'user' => $user,
- 'title' => t('Remove user from group "%s"', $group['name']),
- )));
- }
-
- /**
- * Remove a user from a group
- *
- * @access public
- */
- public function removeUser()
- {
- $this->checkCSRFParam();
- $group_id = $this->request->getIntegerParam('group_id');
- $user_id = $this->request->getIntegerParam('user_id');
-
- if ($this->groupMember->removeUser($group_id, $user_id)) {
- $this->flash->success(t('User removed successfully from this group.'));
- } else {
- $this->flash->failure(t('Unable to remove this user from the group.'));
- }
-
- $this->response->redirect($this->helper->url->to('group', 'users', array('group_id' => $group_id)));
- }
-
- /**
- * Confirmation dialog to remove a group
- *
- * @access public
- */
- public function confirm()
- {
- $group_id = $this->request->getIntegerParam('group_id');
- $group = $this->group->getById($group_id);
-
- $this->response->html($this->helper->layout->app('group/remove', array(
- 'group' => $group,
- 'title' => t('Remove group'),
- )));
- }
-
- /**
- * Remove a group
- *
- * @access public
- */
- public function remove()
- {
- $this->checkCSRFParam();
- $group_id = $this->request->getIntegerParam('group_id');
-
- if ($this->group->remove($group_id)) {
- $this->flash->success(t('Group removed successfully.'));
- } else {
- $this->flash->failure(t('Unable to remove this group.'));
- }
-
- $this->response->redirect($this->helper->url->to('group', 'index'));
- }
-}
diff --git a/app/Controller/GroupHelper.php b/app/Controller/GroupAjaxController.php
index 429614c2..496e9ef2 100644
--- a/app/Controller/GroupHelper.php
+++ b/app/Controller/GroupAjaxController.php
@@ -5,12 +5,12 @@ namespace Kanboard\Controller;
use Kanboard\Formatter\GroupAutoCompleteFormatter;
/**
- * Group Helper
+ * Group Ajax Controller
*
- * @package controller
- * @author Frederic Guillot
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
*/
-class GroupHelper extends Base
+class GroupAjaxController extends BaseController
{
/**
* Group auto-completion (Ajax)
diff --git a/app/Controller/GroupCreationController.php b/app/Controller/GroupCreationController.php
new file mode 100644
index 00000000..b297b19f
--- /dev/null
+++ b/app/Controller/GroupCreationController.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class GroupCreationController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class GroupCreationController extends BaseController
+{
+ /**
+ * Display a form to create a new group
+ *
+ * @access public
+ * @param array $values
+ * @param array $errors
+ */
+ public function show(array $values = array(), array $errors = array())
+ {
+ $this->response->html($this->template->render('group_creation/show', array(
+ 'errors' => $errors,
+ 'values' => $values,
+ )));
+ }
+
+ /**
+ * Validate and save a new group
+ *
+ * @access public
+ */
+ public function save()
+ {
+ $values = $this->request->getValues();
+ list($valid, $errors) = $this->groupValidator->validateCreation($values);
+
+ if ($valid) {
+ if ($this->groupModel->create($values['name']) !== false) {
+ $this->flash->success(t('Group created successfully.'));
+ return $this->response->redirect($this->helper->url->to('GroupListController', 'index'), true);
+ } else {
+ $this->flash->failure(t('Unable to create your group.'));
+ }
+ }
+
+ return $this->show($values, $errors);
+ }
+}
diff --git a/app/Controller/GroupListController.php b/app/Controller/GroupListController.php
new file mode 100644
index 00000000..4486bbff
--- /dev/null
+++ b/app/Controller/GroupListController.php
@@ -0,0 +1,173 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Group Controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class GroupListController extends BaseController
+{
+ /**
+ * List all groups
+ *
+ * @access public
+ */
+ public function index()
+ {
+ $paginator = $this->paginator
+ ->setUrl('GroupListController', 'index')
+ ->setMax(30)
+ ->setOrder('name')
+ ->setQuery($this->groupModel->getQuery())
+ ->calculate();
+
+ $this->response->html($this->helper->layout->app('group/index', array(
+ 'title' => t('Groups').' ('.$paginator->getTotal().')',
+ 'paginator' => $paginator,
+ )));
+ }
+
+ /**
+ * List all users
+ *
+ * @access public
+ */
+ public function users()
+ {
+ $group_id = $this->request->getIntegerParam('group_id');
+ $group = $this->groupModel->getById($group_id);
+
+ $paginator = $this->paginator
+ ->setUrl('GroupListController', 'users', array('group_id' => $group_id))
+ ->setMax(30)
+ ->setOrder('username')
+ ->setQuery($this->groupMemberModel->getQuery($group_id))
+ ->calculate();
+
+ $this->response->html($this->helper->layout->app('group/users', array(
+ 'title' => t('Members of %s', $group['name']).' ('.$paginator->getTotal().')',
+ 'paginator' => $paginator,
+ 'group' => $group,
+ )));
+ }
+
+ /**
+ * Form to associate a user to a group
+ *
+ * @access public
+ * @param array $values
+ * @param array $errors
+ */
+ public function associate(array $values = array(), array $errors = array())
+ {
+ $group_id = $this->request->getIntegerParam('group_id');
+ $group = $this->groupModel->getById($group_id);
+
+ if (empty($values)) {
+ $values['group_id'] = $group_id;
+ }
+
+ $this->response->html($this->template->render('group/associate', array(
+ 'users' => $this->userModel->prepareList($this->groupMemberModel->getNotMembers($group_id)),
+ 'group' => $group,
+ 'errors' => $errors,
+ 'values' => $values,
+ )));
+ }
+
+ /**
+ * Add user to a group
+ *
+ * @access public
+ */
+ public function addUser()
+ {
+ $values = $this->request->getValues();
+
+ if (isset($values['group_id']) && isset($values['user_id'])) {
+ if ($this->groupMemberModel->addUser($values['group_id'], $values['user_id'])) {
+ $this->flash->success(t('Group member added successfully.'));
+ return $this->response->redirect($this->helper->url->to('GroupListController', 'users', array('group_id' => $values['group_id'])), true);
+ } else {
+ $this->flash->failure(t('Unable to add group member.'));
+ }
+ }
+
+ return $this->associate($values);
+ }
+
+ /**
+ * Confirmation dialog to remove a user from a group
+ *
+ * @access public
+ */
+ public function dissociate()
+ {
+ $group_id = $this->request->getIntegerParam('group_id');
+ $user_id = $this->request->getIntegerParam('user_id');
+ $group = $this->groupModel->getById($group_id);
+ $user = $this->userModel->getById($user_id);
+
+ $this->response->html($this->template->render('group/dissociate', array(
+ 'group' => $group,
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Remove a user from a group
+ *
+ * @access public
+ */
+ public function removeUser()
+ {
+ $this->checkCSRFParam();
+ $group_id = $this->request->getIntegerParam('group_id');
+ $user_id = $this->request->getIntegerParam('user_id');
+
+ if ($this->groupMemberModel->removeUser($group_id, $user_id)) {
+ $this->flash->success(t('User removed successfully from this group.'));
+ } else {
+ $this->flash->failure(t('Unable to remove this user from the group.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('GroupListController', 'users', array('group_id' => $group_id)), true);
+ }
+
+ /**
+ * Confirmation dialog to remove a group
+ *
+ * @access public
+ */
+ public function confirm()
+ {
+ $group_id = $this->request->getIntegerParam('group_id');
+ $group = $this->groupModel->getById($group_id);
+
+ $this->response->html($this->template->render('group/remove', array(
+ 'group' => $group,
+ )));
+ }
+
+ /**
+ * Remove a group
+ *
+ * @access public
+ */
+ public function remove()
+ {
+ $this->checkCSRFParam();
+ $group_id = $this->request->getIntegerParam('group_id');
+
+ if ($this->groupModel->remove($group_id)) {
+ $this->flash->success(t('Group removed successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to remove this group.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('GroupListController', 'index'), true);
+ }
+}
diff --git a/app/Controller/GroupModificationController.php b/app/Controller/GroupModificationController.php
new file mode 100644
index 00000000..bd181b74
--- /dev/null
+++ b/app/Controller/GroupModificationController.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class GroupModificationController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class GroupModificationController extends BaseController
+{
+ /**
+ * Display a form to update a group
+ *
+ * @access public
+ * @param array $values
+ * @param array $errors
+ */
+ public function show(array $values = array(), array $errors = array())
+ {
+ if (empty($values)) {
+ $values = $this->groupModel->getById($this->request->getIntegerParam('group_id'));
+ }
+
+ $this->response->html($this->template->render('group_modification/show', array(
+ 'errors' => $errors,
+ 'values' => $values,
+ )));
+ }
+
+ /**
+ * Validate and save a group
+ *
+ * @access public
+ */
+ public function save()
+ {
+ $values = $this->request->getValues();
+ list($valid, $errors) = $this->groupValidator->validateModification($values);
+
+ if ($valid) {
+ if ($this->groupModel->update($values) !== false) {
+ $this->flash->success(t('Group updated successfully.'));
+ return $this->response->redirect($this->helper->url->to('GroupListController', 'index'), true);
+ } else {
+ $this->flash->failure(t('Unable to update your group.'));
+ }
+ }
+
+ return $this->show($values, $errors);
+ }
+}
diff --git a/app/Controller/Ical.php b/app/Controller/ICalendarController.php
index 8fe97b46..e354c6f1 100644
--- a/app/Controller/Ical.php
+++ b/app/Controller/ICalendarController.php
@@ -2,21 +2,22 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
use Kanboard\Core\Filter\QueryBuilder;
use Kanboard\Filter\TaskAssigneeFilter;
use Kanboard\Filter\TaskProjectFilter;
use Kanboard\Filter\TaskStatusFilter;
use Kanboard\Formatter\TaskICalFormatter;
-use Kanboard\Model\Task as TaskModel;
+use Kanboard\Model\TaskModel;
use Eluceo\iCal\Component\Calendar as iCalendar;
/**
- * iCalendar controller
+ * iCalendar Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Ical extends Base
+class ICalendarController extends BaseController
{
/**
* Get user iCalendar
@@ -26,17 +27,17 @@ class Ical extends Base
public function user()
{
$token = $this->request->getStringParam('token');
- $user = $this->user->getByToken($token);
+ $user = $this->userModel->getByToken($token);
// Token verification
if (empty($user)) {
- $this->forbidden(true);
+ throw AccessForbiddenException::getInstance()->withoutLayout();
}
// Common filter
$queryBuilder = new QueryBuilder();
$queryBuilder
- ->withQuery($this->taskFinder->getICalQuery())
+ ->withQuery($this->taskFinderModel->getICalQuery())
->withFilter(new TaskStatusFilter(TaskModel::STATUS_OPEN))
->withFilter(new TaskAssigneeFilter($user['id']));
@@ -57,17 +58,17 @@ class Ical extends Base
public function project()
{
$token = $this->request->getStringParam('token');
- $project = $this->project->getByToken($token);
+ $project = $this->projectModel->getByToken($token);
// Token verification
if (empty($project)) {
- $this->forbidden(true);
+ throw AccessForbiddenException::getInstance()->withoutLayout();
}
// Common filter
$queryBuilder = new QueryBuilder();
$queryBuilder
- ->withQuery($this->taskFinder->getICalQuery())
+ ->withQuery($this->taskFinderModel->getICalQuery())
->withFilter(new TaskStatusFilter(TaskModel::STATUS_OPEN))
->withFilter(new TaskProjectFilter($project['id']));
@@ -84,6 +85,8 @@ class Ical extends Base
* Common method to render iCal events
*
* @access private
+ * @param QueryBuilder $queryBuilder
+ * @param iCalendar $calendar
*/
private function renderCalendar(QueryBuilder $queryBuilder, iCalendar $calendar)
{
diff --git a/app/Controller/Link.php b/app/Controller/LinkController.php
index ec7ab1af..477b25a4 100644
--- a/app/Controller/Link.php
+++ b/app/Controller/LinkController.php
@@ -2,27 +2,30 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\PageNotFoundException;
+
/**
- * Link controller
+ * Link Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Olivier Maridat
* @author Frederic Guillot
*/
-class Link extends Base
+class LinkController extends BaseController
{
/**
* Get the current link
*
* @access private
* @return array
+ * @throws PageNotFoundException
*/
private function getLink()
{
- $link = $this->link->getById($this->request->getIntegerParam('link_id'));
+ $link = $this->linkModel->getById($this->request->getIntegerParam('link_id'));
if (empty($link)) {
- $this->notfound();
+ throw new PageNotFoundException();
}
return $link;
@@ -32,11 +35,13 @@ class Link extends Base
* List of links
*
* @access public
+ * @param array $values
+ * @param array $errors
*/
public function index(array $values = array(), array $errors = array())
{
$this->response->html($this->helper->layout->config('link/index', array(
- 'links' => $this->link->getMergedList(),
+ 'links' => $this->linkModel->getMergedList(),
'values' => $values,
'errors' => $errors,
'title' => t('Settings').' &gt; '.t('Task\'s links'),
@@ -54,21 +59,24 @@ class Link extends Base
list($valid, $errors) = $this->linkValidator->validateCreation($values);
if ($valid) {
- if ($this->link->create($values['label'], $values['opposite_label']) !== false) {
+ if ($this->linkModel->create($values['label'], $values['opposite_label']) !== false) {
$this->flash->success(t('Link added successfully.'));
- $this->response->redirect($this->helper->url->to('link', 'index'));
+ return $this->response->redirect($this->helper->url->to('LinkController', 'index'));
} else {
$this->flash->failure(t('Unable to create your link.'));
}
}
- $this->index($values, $errors);
+ return $this->index($values, $errors);
}
/**
* Edit form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws PageNotFoundException
*/
public function edit(array $values = array(), array $errors = array())
{
@@ -78,7 +86,7 @@ class Link extends Base
$this->response->html($this->helper->layout->config('link/edit', array(
'values' => $values ?: $link,
'errors' => $errors,
- 'labels' => $this->link->getList($link['id']),
+ 'labels' => $this->linkModel->getList($link['id']),
'link' => $link,
'title' => t('Link modification')
)));
@@ -95,15 +103,15 @@ class Link extends Base
list($valid, $errors) = $this->linkValidator->validateModification($values);
if ($valid) {
- if ($this->link->update($values)) {
+ if ($this->linkModel->update($values)) {
$this->flash->success(t('Link updated successfully.'));
- $this->response->redirect($this->helper->url->to('link', 'index'));
+ return $this->response->redirect($this->helper->url->to('LinkController', 'index'));
} else {
$this->flash->failure(t('Unable to update your link.'));
}
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
@@ -131,12 +139,12 @@ class Link extends Base
$this->checkCSRFParam();
$link = $this->getLink();
- if ($this->link->remove($link['id'])) {
+ if ($this->linkModel->remove($link['id'])) {
$this->flash->success(t('Link removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this link.'));
}
- $this->response->redirect($this->helper->url->to('link', 'index'));
+ $this->response->redirect($this->helper->url->to('LinkController', 'index'));
}
}
diff --git a/app/Controller/Oauth.php b/app/Controller/OAuthController.php
index 12b91144..7663ddcc 100644
--- a/app/Controller/Oauth.php
+++ b/app/Controller/OAuthController.php
@@ -5,12 +5,12 @@ namespace Kanboard\Controller;
use Kanboard\Core\Security\OAuthAuthenticationProviderInterface;
/**
- * OAuth controller
+ * OAuth Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Oauth extends Base
+class OAuthController extends BaseController
{
/**
* Redirect to the provider if no code received
@@ -49,7 +49,7 @@ class Oauth extends Base
$this->link($provider);
} else {
$this->flash->failure(t('The OAuth2 state parameter is invalid'));
- $this->response->redirect($this->helper->url->to('user', 'external', array('user_id' => $this->userSession->getId())));
+ $this->response->redirect($this->helper->url->to('UserViewController', 'external', array('user_id' => $this->userSession->getId())));
}
} else {
if ($hasValidState) {
@@ -75,7 +75,7 @@ class Oauth extends Base
$this->flash->success(t('Your external account is linked to your profile successfully.'));
}
- $this->response->redirect($this->helper->url->to('user', 'external', array('user_id' => $this->userSession->getId())));
+ $this->response->redirect($this->helper->url->to('UserViewController', 'external', array('user_id' => $this->userSession->getId())));
}
/**
@@ -94,7 +94,7 @@ class Oauth extends Base
$this->flash->failure(t('Unable to unlink your external account.'));
}
- $this->response->redirect($this->helper->url->to('user', 'external', array('user_id' => $this->userSession->getId())));
+ $this->response->redirect($this->helper->url->to('UserViewController', 'external', array('user_id' => $this->userSession->getId())));
}
/**
@@ -106,7 +106,7 @@ class Oauth extends Base
protected function authenticate($providerName)
{
if ($this->authenticationManager->oauthAuthentication($providerName)) {
- $this->response->redirect($this->helper->url->to('app', 'index'));
+ $this->response->redirect($this->helper->url->to('DashboardController', 'show'));
} else {
$this->authenticationFailure(t('External authentication failed'));
}
diff --git a/app/Controller/PasswordReset.php b/app/Controller/PasswordResetController.php
index f6a0eb8e..18b4be80 100644
--- a/app/Controller/PasswordReset.php
+++ b/app/Controller/PasswordResetController.php
@@ -2,13 +2,15 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
+
/**
* Password Reset Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class PasswordReset extends Base
+class PasswordResetController extends BaseController
{
/**
* Show the form to reset the password
@@ -36,10 +38,10 @@ class PasswordReset extends Base
if ($valid) {
$this->sendEmail($values['username']);
- $this->response->redirect($this->helper->url->to('auth', 'login'));
+ $this->response->redirect($this->helper->url->to('AuthController', 'login'));
+ } else {
+ $this->create($values, $errors);
}
-
- $this->create($values, $errors);
}
/**
@@ -50,7 +52,7 @@ class PasswordReset extends Base
$this->checkActivation();
$token = $this->request->getStringParam('token');
- $user_id = $this->passwordReset->getUserIdByToken($token);
+ $user_id = $this->passwordResetModel->getUserIdByToken($token);
if ($user_id !== false) {
$this->response->html($this->helper->layout->app('password_reset/change', array(
@@ -59,9 +61,9 @@ class PasswordReset extends Base
'values' => $values,
'no_layout' => true,
)));
+ } else {
+ $this->response->redirect($this->helper->url->to('AuthController', 'login'));
}
-
- $this->response->redirect($this->helper->url->to('auth', 'login'));
}
/**
@@ -76,17 +78,17 @@ class PasswordReset extends Base
list($valid, $errors) = $this->passwordResetValidator->validateModification($values);
if ($valid) {
- $user_id = $this->passwordReset->getUserIdByToken($token);
+ $user_id = $this->passwordResetModel->getUserIdByToken($token);
if ($user_id !== false) {
- $this->user->update(array('id' => $user_id, 'password' => $values['password']));
- $this->passwordReset->disable($user_id);
+ $this->userModel->update(array('id' => $user_id, 'password' => $values['password']));
+ $this->passwordResetModel->disable($user_id);
}
- $this->response->redirect($this->helper->url->to('auth', 'login'));
+ return $this->response->redirect($this->helper->url->to('AuthController', 'login'));
}
- $this->change($values, $errors);
+ return $this->change($values, $errors);
}
/**
@@ -94,10 +96,10 @@ class PasswordReset extends Base
*/
private function sendEmail($username)
{
- $token = $this->passwordReset->create($username);
+ $token = $this->passwordResetModel->create($username);
if ($token !== false) {
- $user = $this->user->getByUsername($username);
+ $user = $this->userModel->getByUsername($username);
$this->emailClient->send(
$user['email'],
@@ -113,8 +115,8 @@ class PasswordReset extends Base
*/
private function checkActivation()
{
- if ($this->config->get('password_reset', 0) == 0) {
- $this->response->redirect($this->helper->url->to('auth', 'login'));
+ if ($this->configModel->get('password_reset', 0) == 0) {
+ throw AccessForbiddenException::getInstance()->withoutLayout();
}
}
}
diff --git a/app/Controller/PluginController.php b/app/Controller/PluginController.php
new file mode 100644
index 00000000..7b9d64d9
--- /dev/null
+++ b/app/Controller/PluginController.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Plugin\Directory;
+use Kanboard\Core\Plugin\Installer;
+use Kanboard\Core\Plugin\PluginInstallerException;
+
+/**
+ * Class PluginController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class PluginController extends BaseController
+{
+ /**
+ * Display the plugin page
+ *
+ * @access public
+ */
+ public function show()
+ {
+ $this->response->html($this->helper->layout->plugin('plugin/show', array(
+ 'plugins' => $this->pluginLoader->getPlugins(),
+ 'title' => t('Installed Plugins'),
+ 'is_configured' => Installer::isConfigured(),
+ )));
+ }
+
+ /**
+ * Display list of available plugins
+ */
+ public function directory()
+ {
+ $installedPlugins = array();
+
+ foreach ($this->pluginLoader->getPlugins() as $plugin) {
+ $installedPlugins[$plugin->getPluginName()] = $plugin->getPluginVersion();
+ }
+
+ $this->response->html($this->helper->layout->plugin('plugin/directory', array(
+ 'installed_plugins' => $installedPlugins,
+ 'available_plugins' => Directory::getInstance($this->container)->getAvailablePlugins(),
+ 'title' => t('Plugin Directory'),
+ 'is_configured' => Installer::isConfigured(),
+ )));
+ }
+
+ /**
+ * Install plugin from URL
+ *
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ */
+ public function install()
+ {
+ $this->checkCSRFParam();
+ $pluginArchiveUrl = urldecode($this->request->getStringParam('archive_url'));
+
+ try {
+ $installer = new Installer($this->container);
+ $installer->install($pluginArchiveUrl);
+ $this->flash->success(t('Plugin installed successfully.'));
+ } catch (PluginInstallerException $e) {
+ $this->flash->failure($e->getMessage());
+ }
+
+ $this->response->redirect($this->helper->url->to('PluginController', 'show'));
+ }
+
+ /**
+ * Update plugin from URL
+ *
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ */
+ public function update()
+ {
+ $this->checkCSRFParam();
+ $pluginArchiveUrl = urldecode($this->request->getStringParam('archive_url'));
+
+ try {
+ $installer = new Installer($this->container);
+ $installer->update($pluginArchiveUrl);
+ $this->flash->success(t('Plugin updated successfully.'));
+ } catch (PluginInstallerException $e) {
+ $this->flash->failure($e->getMessage());
+ }
+
+ $this->response->redirect($this->helper->url->to('PluginController', 'show'));
+ }
+
+ /**
+ * Confirmation before to remove the plugin
+ */
+ public function confirm()
+ {
+ $pluginId = $this->request->getStringParam('pluginId');
+ $plugins = $this->pluginLoader->getPlugins();
+
+ $this->response->html($this->template->render('plugin/remove', array(
+ 'plugin_id' => $pluginId,
+ 'plugin' => $plugins[$pluginId],
+ )));
+ }
+
+ /**
+ * Remove a plugin
+ *
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ */
+ public function uninstall()
+ {
+ $this->checkCSRFParam();
+ $pluginId = $this->request->getStringParam('pluginId');
+
+ try {
+ $installer = new Installer($this->container);
+ $installer->uninstall($pluginId);
+ $this->flash->success(t('Plugin removed successfully.'));
+ } catch (PluginInstallerException $e) {
+ $this->flash->failure($e->getMessage());
+ }
+
+ $this->response->redirect($this->helper->url->to('PluginController', 'show'));
+ }
+}
diff --git a/app/Controller/Project.php b/app/Controller/Project.php
deleted file mode 100644
index cdfbd94a..00000000
--- a/app/Controller/Project.php
+++ /dev/null
@@ -1,243 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-/**
- * Project controller (Settings + creation/edition)
- *
- * @package controller
- * @author Frederic Guillot
- */
-class Project extends Base
-{
- /**
- * List of projects
- *
- * @access public
- */
- public function index()
- {
- if ($this->userSession->isAdmin()) {
- $project_ids = $this->project->getAllIds();
- } else {
- $project_ids = $this->projectPermission->getActiveProjectIds($this->userSession->getId());
- }
-
- $nb_projects = count($project_ids);
-
- $paginator = $this->paginator
- ->setUrl('project', 'index')
- ->setMax(20)
- ->setOrder('name')
- ->setQuery($this->project->getQueryColumnStats($project_ids))
- ->calculate();
-
- $this->response->html($this->helper->layout->app('project/index', array(
- 'paginator' => $paginator,
- 'nb_projects' => $nb_projects,
- 'title' => t('Projects').' ('.$nb_projects.')'
- )));
- }
-
- /**
- * Show the project information page
- *
- * @access public
- */
- public function show()
- {
- $project = $this->getProject();
-
- $this->response->html($this->helper->layout->project('project/show', array(
- 'project' => $project,
- 'stats' => $this->project->getTaskStats($project['id']),
- 'title' => $project['name'],
- )));
- }
-
- /**
- * Public access management
- *
- * @access public
- */
- public function share()
- {
- $project = $this->getProject();
- $switch = $this->request->getStringParam('switch');
-
- if ($switch === 'enable' || $switch === 'disable') {
- $this->checkCSRFParam();
-
- if ($this->project->{$switch.'PublicAccess'}($project['id'])) {
- $this->flash->success(t('Project updated successfully.'));
- } else {
- $this->flash->failure(t('Unable to update this project.'));
- }
-
- $this->response->redirect($this->helper->url->to('project', 'share', array('project_id' => $project['id'])));
- }
-
- $this->response->html($this->helper->layout->project('project/share', array(
- 'project' => $project,
- 'title' => t('Public access'),
- )));
- }
-
- /**
- * Integrations page
- *
- * @access public
- */
- public function integrations()
- {
- $project = $this->getProject();
-
- if ($this->request->isPost()) {
- $this->projectMetadata->save($project['id'], $this->request->getValues());
- $this->flash->success(t('Project updated successfully.'));
- $this->response->redirect($this->helper->url->to('project', 'integrations', array('project_id' => $project['id'])));
- }
-
- $this->response->html($this->helper->layout->project('project/integrations', array(
- 'project' => $project,
- 'title' => t('Integrations'),
- 'webhook_token' => $this->config->get('webhook_token'),
- 'values' => $this->projectMetadata->getAll($project['id']),
- 'errors' => array(),
- )));
- }
-
- /**
- * Display project notifications
- *
- * @access public
- */
- public function notifications()
- {
- $project = $this->getProject();
-
- if ($this->request->isPost()) {
- $values = $this->request->getValues();
- $this->projectNotification->saveSettings($project['id'], $values);
- $this->flash->success(t('Project updated successfully.'));
- $this->response->redirect($this->helper->url->to('project', 'notifications', array('project_id' => $project['id'])));
- }
-
- $this->response->html($this->helper->layout->project('project/notifications', array(
- 'notifications' => $this->projectNotification->readSettings($project['id']),
- 'types' => $this->projectNotificationType->getTypes(),
- 'project' => $project,
- 'title' => t('Notifications'),
- )));
- }
-
- /**
- * Remove a project
- *
- * @access public
- */
- public function remove()
- {
- $project = $this->getProject();
-
- if ($this->request->getStringParam('remove') === 'yes') {
- $this->checkCSRFParam();
-
- if ($this->project->remove($project['id'])) {
- $this->flash->success(t('Project removed successfully.'));
- } else {
- $this->flash->failure(t('Unable to remove this project.'));
- }
-
- $this->response->redirect($this->helper->url->to('project', 'index'));
- }
-
- $this->response->html($this->helper->layout->project('project/remove', array(
- 'project' => $project,
- 'title' => t('Remove project')
- )));
- }
-
- /**
- * Duplicate a project
- *
- * @author Antonio Rabelo
- * @author Michael Lüpkes
- * @access public
- */
- public function duplicate()
- {
- $project = $this->getProject();
-
- if ($this->request->getStringParam('duplicate') === 'yes') {
- $project_id = $this->projectDuplication->duplicate($project['id'], array_keys($this->request->getValues()), $this->userSession->getId());
-
- if ($project_id !== false) {
- $this->flash->success(t('Project cloned successfully.'));
- } else {
- $this->flash->failure(t('Unable to clone this project.'));
- }
-
- $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id)));
- }
-
- $this->response->html($this->helper->layout->project('project/duplicate', array(
- 'project' => $project,
- 'title' => t('Clone this project')
- )));
- }
-
- /**
- * Disable a project
- *
- * @access public
- */
- public function disable()
- {
- $project = $this->getProject();
-
- if ($this->request->getStringParam('disable') === 'yes') {
- $this->checkCSRFParam();
-
- if ($this->project->disable($project['id'])) {
- $this->flash->success(t('Project disabled successfully.'));
- } else {
- $this->flash->failure(t('Unable to disable this project.'));
- }
-
- $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id'])));
- }
-
- $this->response->html($this->helper->layout->project('project/disable', array(
- 'project' => $project,
- 'title' => t('Project activation')
- )));
- }
-
- /**
- * Enable a project
- *
- * @access public
- */
- public function enable()
- {
- $project = $this->getProject();
-
- if ($this->request->getStringParam('enable') === 'yes') {
- $this->checkCSRFParam();
-
- if ($this->project->enable($project['id'])) {
- $this->flash->success(t('Project activated successfully.'));
- } else {
- $this->flash->failure(t('Unable to activate this project.'));
- }
-
- $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id'])));
- }
-
- $this->response->html($this->helper->layout->project('project/enable', array(
- 'project' => $project,
- 'title' => t('Project activation')
- )));
- }
-}
diff --git a/app/Controller/ActionProject.php b/app/Controller/ProjectActionDuplicationController.php
index e5063f73..a4993cca 100644
--- a/app/Controller/ActionProject.php
+++ b/app/Controller/ProjectActionDuplicationController.php
@@ -5,18 +5,18 @@ namespace Kanboard\Controller;
/**
* Duplicate automatic action from another project
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class ActionProject extends Base
+class ProjectActionDuplicationController extends BaseController
{
- public function project()
+ public function show()
{
$project = $this->getProject();
- $projects = $this->projectUserRole->getProjectsByUser($this->userSession->getId());
+ $projects = $this->projectUserRoleModel->getProjectsByUser($this->userSession->getId());
unset($projects[$project['id']]);
- $this->response->html($this->template->render('action_project/project', array(
+ $this->response->html($this->template->render('project_action_duplication/show', array(
'project' => $project,
'projects_list' => $projects,
)));
@@ -27,12 +27,12 @@ class ActionProject extends Base
$project = $this->getProject();
$src_project_id = $this->request->getValue('src_project_id');
- if ($this->action->duplicate($src_project_id, $project['id'])) {
+ if ($this->actionModel->duplicate($src_project_id, $project['id'])) {
$this->flash->success(t('Actions duplicated successfully.'));
} else {
$this->flash->failure(t('Unable to duplicate actions.'));
}
- $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ActionController', 'index', array('project_id' => $project['id'])));
}
}
diff --git a/app/Controller/ProjectCreation.php b/app/Controller/ProjectCreationController.php
index 88f41fcd..c471cfdd 100644
--- a/app/Controller/ProjectCreation.php
+++ b/app/Controller/ProjectCreationController.php
@@ -5,20 +5,22 @@ namespace Kanboard\Controller;
/**
* Project Creation Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class ProjectCreation extends Base
+class ProjectCreationController extends BaseController
{
/**
* Display a form to create a new project
*
* @access public
+ * @param array $values
+ * @param array $errors
*/
public function create(array $values = array(), array $errors = array())
{
$is_private = isset($values['is_private']) && $values['is_private'] == 1;
- $projects_list = array(0 => t('Do not duplicate anything')) + $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId());
+ $projects_list = array(0 => t('Do not duplicate anything')) + $this->projectUserRoleModel->getActiveProjectsByUser($this->userSession->getId());
$this->response->html($this->helper->layout->app('project_creation/create', array(
'values' => $values,
@@ -33,6 +35,8 @@ class ProjectCreation extends Base
* Display a form to create a private project
*
* @access public
+ * @param array $values
+ * @param array $errors
*/
public function createPrivate(array $values = array(), array $errors = array())
{
@@ -55,13 +59,13 @@ class ProjectCreation extends Base
if ($project_id > 0) {
$this->flash->success(t('Your project have been created successfully.'));
- return $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id)));
+ return $this->response->redirect($this->helper->url->to('ProjectViewController', 'show', array('project_id' => $project_id)));
}
$this->flash->failure(t('Unable to create your project.'));
}
- $this->create($values, $errors);
+ return $this->create($values, $errors);
}
/**
@@ -94,7 +98,7 @@ class ProjectCreation extends Base
'is_private' => $values['is_private'],
);
- return $this->project->create($project, $this->userSession->getId(), true);
+ return $this->projectModel->create($project, $this->userSession->getId(), true);
}
/**
@@ -108,13 +112,13 @@ class ProjectCreation extends Base
{
$selection = array();
- foreach ($this->projectDuplication->getOptionalSelection() as $item) {
+ foreach ($this->projectDuplicationModel->getOptionalSelection() as $item) {
if (isset($values[$item]) && $values[$item] == 1) {
$selection[] = $item;
}
}
- return $this->projectDuplication->duplicate(
+ return $this->projectDuplicationModel->duplicate(
$values['src_project_id'],
$selection,
$this->userSession->getId(),
diff --git a/app/Controller/ProjectEdit.php b/app/Controller/ProjectEditController.php
index 94be0206..228d681c 100644
--- a/app/Controller/ProjectEdit.php
+++ b/app/Controller/ProjectEditController.php
@@ -5,15 +5,17 @@ namespace Kanboard\Controller;
/**
* Project Edit Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class ProjectEdit extends Base
+class ProjectEditController extends BaseController
{
/**
* General edition (most common operations)
*
* @access public
+ * @param array $values
+ * @param array $errors
*/
public function edit(array $values = array(), array $errors = array())
{
@@ -24,6 +26,8 @@ class ProjectEdit extends Base
* Change start and end dates
*
* @access public
+ * @param array $values
+ * @param array $errors
*/
public function dates(array $values = array(), array $errors = array())
{
@@ -34,6 +38,8 @@ class ProjectEdit extends Base
* Change project description
*
* @access public
+ * @param array $values
+ * @param array $errors
*/
public function description(array $values = array(), array $errors = array())
{
@@ -44,6 +50,8 @@ class ProjectEdit extends Base
* Change task priority
*
* @access public
+ * @param array $values
+ * @param array $errors
*/
public function priority(array $values = array(), array $errors = array())
{
@@ -65,15 +73,15 @@ class ProjectEdit extends Base
list($valid, $errors) = $this->projectValidator->validateModification($values);
if ($valid) {
- if ($this->project->update($values)) {
+ if ($this->projectModel->update($values)) {
$this->flash->success(t('Project updated successfully.'));
- $this->response->redirect($this->helper->url->to('ProjectEdit', $redirect, array('project_id' => $project['id'])), true);
+ return $this->response->redirect($this->helper->url->to('ProjectEditController', $redirect, array('project_id' => $project['id'])), true);
} else {
$this->flash->failure(t('Unable to update this project.'));
}
}
- $this->$redirect($values, $errors);
+ return $this->$redirect($values, $errors);
}
/**
@@ -89,11 +97,11 @@ class ProjectEdit extends Base
{
if ($redirect === 'edit') {
if (isset($values['is_private'])) {
- if (! $this->helper->user->hasProjectAccess('ProjectCreation', 'create', $project['id'])) {
+ if (! $this->helper->user->hasProjectAccess('ProjectCreationController', 'create', $project['id'])) {
unset($values['is_private']);
}
} elseif ($project['is_private'] == 1 && ! isset($values['is_private'])) {
- if ($this->helper->user->hasProjectAccess('ProjectCreation', 'create', $project['id'])) {
+ if ($this->helper->user->hasProjectAccess('ProjectCreationController', 'create', $project['id'])) {
$values += array('is_private' => 0);
}
}
@@ -103,7 +111,7 @@ class ProjectEdit extends Base
}
/**
- * Common metthod to render different views
+ * Common method to render different views
*
* @access private
* @param string $template
@@ -115,7 +123,7 @@ class ProjectEdit extends Base
$project = $this->getProject();
$this->response->html($this->helper->layout->project($template, array(
- 'owners' => $this->projectUserRole->getAssignableUsersList($project['id'], true),
+ 'owners' => $this->projectUserRoleModel->getAssignableUsersList($project['id'], true),
'values' => empty($values) ? $project : $values,
'errors' => $errors,
'project' => $project,
diff --git a/app/Controller/ProjectFile.php b/app/Controller/ProjectFileController.php
index 96764a92..cbe48679 100644
--- a/app/Controller/ProjectFile.php
+++ b/app/Controller/ProjectFileController.php
@@ -5,10 +5,10 @@ namespace Kanboard\Controller;
/**
* Project File Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class ProjectFile extends Base
+class ProjectFileController extends BaseController
{
/**
* File upload form
@@ -34,11 +34,11 @@ class ProjectFile extends Base
{
$project = $this->getProject();
- if (! $this->projectFile->uploadFiles($project['id'], $this->request->getFileInfo('files'))) {
+ if (! $this->projectFileModel->uploadFiles($project['id'], $this->request->getFileInfo('files'))) {
$this->flash->failure(t('Unable to upload the file.'));
}
- $this->response->redirect($this->helper->url->to('ProjectOverview', 'show', array('project_id' => $project['id'])), true);
+ $this->response->redirect($this->helper->url->to('ProjectOverviewController', 'show', array('project_id' => $project['id'])), true);
}
/**
@@ -50,15 +50,15 @@ class ProjectFile extends Base
{
$this->checkCSRFParam();
$project = $this->getProject();
- $file = $this->projectFile->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->projectFileModel->getById($this->request->getIntegerParam('file_id'));
- if ($this->projectFile->remove($file['id'])) {
+ if ($this->projectFileModel->remove($file['id'])) {
$this->flash->success(t('File removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this file.'));
}
- $this->response->redirect($this->helper->url->to('ProjectOverview', 'show', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ProjectOverviewController', 'show', array('project_id' => $project['id'])));
}
/**
@@ -69,7 +69,7 @@ class ProjectFile extends Base
public function confirm()
{
$project = $this->getProject();
- $file = $this->projectFile->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->projectFileModel->getById($this->request->getIntegerParam('file_id'));
$this->response->html($this->template->render('project_file/remove', array(
'project' => $project,
diff --git a/app/Controller/ProjectGanttController.php b/app/Controller/ProjectGanttController.php
new file mode 100644
index 00000000..a70d9eee
--- /dev/null
+++ b/app/Controller/ProjectGanttController.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Filter\ProjectIdsFilter;
+use Kanboard\Filter\ProjectStatusFilter;
+use Kanboard\Filter\ProjectTypeFilter;
+use Kanboard\Formatter\ProjectGanttFormatter;
+use Kanboard\Model\ProjectModel;
+
+/**
+ * Projects Gantt Controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class ProjectGanttController extends BaseController
+{
+ /**
+ * Show Gantt chart for all projects
+ */
+ public function show()
+ {
+ $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId());
+ $filter = $this->projectQuery
+ ->withFilter(new ProjectTypeFilter(ProjectModel::TYPE_TEAM))
+ ->withFilter(new ProjectStatusFilter(ProjectModel::ACTIVE))
+ ->withFilter(new ProjectIdsFilter($project_ids));
+
+ $filter->getQuery()->asc(ProjectModel::TABLE.'.start_date');
+
+ $this->response->html($this->helper->layout->app('project_gantt/show', array(
+ 'projects' => $filter->format(new ProjectGanttFormatter($this->container)),
+ 'title' => t('Gantt chart for all projects'),
+ )));
+ }
+
+ /**
+ * Save new project start date and end date
+ */
+ public function save()
+ {
+ $values = $this->request->getJson();
+
+ $result = $this->projectModel->update(array(
+ 'id' => $values['id'],
+ 'start_date' => $this->dateParser->getIsoDate(strtotime($values['start'])),
+ 'end_date' => $this->dateParser->getIsoDate(strtotime($values['end'])),
+ ));
+
+ if (! $result) {
+ $this->response->json(array('message' => 'Unable to save project'), 400);
+ } else {
+ $this->response->json(array('message' => 'OK'), 201);
+ }
+ }
+}
diff --git a/app/Controller/ProjectListController.php b/app/Controller/ProjectListController.php
new file mode 100644
index 00000000..e1172400
--- /dev/null
+++ b/app/Controller/ProjectListController.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class ProjectListController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class ProjectListController extends BaseController
+{
+ /**
+ * List of projects
+ *
+ * @access public
+ */
+ public function show()
+ {
+ if ($this->userSession->isAdmin()) {
+ $project_ids = $this->projectModel->getAllIds();
+ } else {
+ $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId());
+ }
+
+ $nb_projects = count($project_ids);
+
+ $paginator = $this->paginator
+ ->setUrl('ProjectListController', 'show')
+ ->setMax(20)
+ ->setOrder('name')
+ ->setQuery($this->projectModel->getQueryColumnStats($project_ids))
+ ->calculate();
+
+ $this->response->html($this->helper->layout->app('project_list/show', array(
+ 'paginator' => $paginator,
+ 'nb_projects' => $nb_projects,
+ 'title' => t('Projects').' ('.$nb_projects.')'
+ )));
+ }
+}
diff --git a/app/Controller/ProjectOverview.php b/app/Controller/ProjectOverviewController.php
index b2bb33d6..abdff657 100644
--- a/app/Controller/ProjectOverview.php
+++ b/app/Controller/ProjectOverviewController.php
@@ -5,10 +5,10 @@ namespace Kanboard\Controller;
/**
* Project Overview Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class ProjectOverview extends Base
+class ProjectOverviewController extends BaseController
{
/**
* Show project overview
@@ -16,17 +16,17 @@ class ProjectOverview extends Base
public function show()
{
$project = $this->getProject();
- $this->project->getColumnStats($project);
+ $this->projectModel->getColumnStats($project);
$this->response->html($this->helper->layout->app('project_overview/show', array(
'project' => $project,
'title' => $project['name'],
'description' => $this->helper->projectHeader->getDescription($project),
- 'users' => $this->projectUserRole->getAllUsersGroupedByRole($project['id']),
+ 'users' => $this->projectUserRoleModel->getAllUsersGroupedByRole($project['id']),
'roles' => $this->role->getProjectRoles(),
'events' => $this->helper->projectActivity->getProjectEvents($project['id'], 10),
- 'images' => $this->projectFile->getAllImages($project['id']),
- 'files' => $this->projectFile->getAllDocuments($project['id']),
+ 'images' => $this->projectFileModel->getAllImages($project['id']),
+ 'files' => $this->projectFileModel->getAllDocuments($project['id']),
)));
}
}
diff --git a/app/Controller/ProjectPermission.php b/app/Controller/ProjectPermissionController.php
index e203c0db..f3ca6ed9 100644
--- a/app/Controller/ProjectPermission.php
+++ b/app/Controller/ProjectPermissionController.php
@@ -2,15 +2,16 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
use Kanboard\Core\Security\Role;
/**
- * Project Permission
+ * Project Permission Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class ProjectPermission extends Base
+class ProjectPermissionController extends BaseController
{
/**
* Permissions are only available for team projects
@@ -18,13 +19,14 @@ class ProjectPermission extends Base
* @access protected
* @param integer $project_id Default project id
* @return array
+ * @throws AccessForbiddenException
*/
protected function getProject($project_id = 0)
{
$project = parent::getProject($project_id);
if ($project['is_private'] == 1) {
- $this->forbidden();
+ throw new AccessForbiddenException();
}
return $project;
@@ -34,6 +36,9 @@ class ProjectPermission extends Base
* Show all permissions
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws AccessForbiddenException
*/
public function index(array $values = array(), array $errors = array())
{
@@ -45,8 +50,8 @@ class ProjectPermission extends Base
$this->response->html($this->helper->layout->project('project_permission/index', array(
'project' => $project,
- 'users' => $this->projectUserRole->getUsers($project['id']),
- 'groups' => $this->projectGroupRole->getGroups($project['id']),
+ 'users' => $this->projectUserRoleModel->getUsers($project['id']),
+ 'groups' => $this->projectGroupRoleModel->getGroups($project['id']),
'roles' => $this->role->getProjectRoles(),
'values' => $values,
'errors' => $errors,
@@ -64,13 +69,13 @@ class ProjectPermission extends Base
$project = $this->getProject();
$values = $this->request->getValues() + array('is_everybody_allowed' => 0);
- if ($this->project->update($values)) {
+ if ($this->projectModel->update($values)) {
$this->flash->success(t('Project updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this project.'));
}
- $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ProjectPermissionController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -85,13 +90,13 @@ class ProjectPermission extends Base
if (empty($values['user_id'])) {
$this->flash->failure(t('User not found.'));
- } elseif ($this->projectUserRole->addUser($values['project_id'], $values['user_id'], $values['role'])) {
+ } elseif ($this->projectUserRoleModel->addUser($values['project_id'], $values['user_id'], $values['role'])) {
$this->flash->success(t('Project updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this project.'));
}
- $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ProjectPermissionController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -105,13 +110,13 @@ class ProjectPermission extends Base
$project = $this->getProject();
$user_id = $this->request->getIntegerParam('user_id');
- if ($this->projectUserRole->removeUser($project['id'], $user_id)) {
+ if ($this->projectUserRoleModel->removeUser($project['id'], $user_id)) {
$this->flash->success(t('Project updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this project.'));
}
- $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ProjectPermissionController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -124,7 +129,7 @@ class ProjectPermission extends Base
$project = $this->getProject();
$values = $this->request->getJson();
- if (! empty($project) && ! empty($values) && $this->projectUserRole->changeUserRole($project['id'], $values['id'], $values['role'])) {
+ if (! empty($project) && ! empty($values) && $this->projectUserRoleModel->changeUserRole($project['id'], $values['id'], $values['role'])) {
$this->response->json(array('status' => 'ok'));
} else {
$this->response->json(array('status' => 'error'));
@@ -142,16 +147,16 @@ class ProjectPermission extends Base
$values = $this->request->getValues();
if (empty($values['group_id']) && ! empty($values['external_id'])) {
- $values['group_id'] = $this->group->create($values['name'], $values['external_id']);
+ $values['group_id'] = $this->groupModel->create($values['name'], $values['external_id']);
}
- if ($this->projectGroupRole->addGroup($project['id'], $values['group_id'], $values['role'])) {
+ if ($this->projectGroupRoleModel->addGroup($project['id'], $values['group_id'], $values['role'])) {
$this->flash->success(t('Project updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this project.'));
}
- $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ProjectPermissionController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -165,13 +170,13 @@ class ProjectPermission extends Base
$project = $this->getProject();
$group_id = $this->request->getIntegerParam('group_id');
- if ($this->projectGroupRole->removeGroup($project['id'], $group_id)) {
+ if ($this->projectGroupRoleModel->removeGroup($project['id'], $group_id)) {
$this->flash->success(t('Project updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this project.'));
}
- $this->response->redirect($this->helper->url->to('ProjectPermission', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('ProjectPermissionController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -184,7 +189,7 @@ class ProjectPermission extends Base
$project = $this->getProject();
$values = $this->request->getJson();
- if (! empty($project) && ! empty($values) && $this->projectGroupRole->changeGroupRole($project['id'], $values['id'], $values['role'])) {
+ if (! empty($project) && ! empty($values) && $this->projectGroupRoleModel->changeGroupRole($project['id'], $values['id'], $values['role'])) {
$this->response->json(array('status' => 'ok'));
} else {
$this->response->json(array('status' => 'error'));
diff --git a/app/Controller/ProjectStatusController.php b/app/Controller/ProjectStatusController.php
new file mode 100644
index 00000000..78e77870
--- /dev/null
+++ b/app/Controller/ProjectStatusController.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class ProjectStatusController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class ProjectStatusController extends BaseController
+{
+ /**
+ * Enable a project (confirmation dialog box)
+ */
+ public function confirmEnable()
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->template->render('project_status/enable', array(
+ 'project' => $project,
+ 'title' => t('Project activation')
+ )));
+ }
+
+ /**
+ * Enable the project
+ */
+ public function enable()
+ {
+ $project = $this->getProject();
+ $this->checkCSRFParam();
+
+ if ($this->projectModel->enable($project['id'])) {
+ $this->flash->success(t('Project activated successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to activate this project.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectViewController', 'show', array('project_id' => $project['id'])), true);
+ }
+
+ /**
+ * Disable a project (confirmation dialog box)
+ */
+ public function confirmDisable()
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->template->render('project_status/disable', array(
+ 'project' => $project,
+ 'title' => t('Project activation')
+ )));
+ }
+
+ /**
+ * Disable a project
+ */
+ public function disable()
+ {
+ $project = $this->getProject();
+ $this->checkCSRFParam();
+
+ if ($this->projectModel->disable($project['id'])) {
+ $this->flash->success(t('Project disabled successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to disable this project.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectViewController', 'show', array('project_id' => $project['id'])), true);
+ }
+
+ /**
+ * Remove a project (confirmation dialog box)
+ */
+ public function confirmRemove()
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->template->render('project_status/remove', array(
+ 'project' => $project,
+ 'title' => t('Remove project')
+ )));
+ }
+
+ /**
+ * Remove a project
+ */
+ public function remove()
+ {
+ $project = $this->getProject();
+ $this->checkCSRFParam();
+
+ if ($this->projectModel->remove($project['id'])) {
+ $this->flash->success(t('Project removed successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to remove this project.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectListController', 'show'), true);
+ }
+}
diff --git a/app/Controller/Projectuser.php b/app/Controller/ProjectUserOverviewController.php
index a6d4fe4e..686de830 100644
--- a/app/Controller/Projectuser.php
+++ b/app/Controller/ProjectUserOverviewController.php
@@ -2,36 +2,36 @@
namespace Kanboard\Controller;
-use Kanboard\Model\User as UserModel;
-use Kanboard\Model\Task as TaskModel;
+use Kanboard\Model\UserModel;
+use Kanboard\Model\TaskModel;
use Kanboard\Core\Security\Role;
/**
* Project User overview
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Projectuser extends Base
+class ProjectUserOverviewController extends BaseController
{
private function common()
{
$user_id = $this->request->getIntegerParam('user_id', UserModel::EVERYBODY_ID);
if ($this->userSession->isAdmin()) {
- $project_ids = $this->project->getAllIds();
+ $project_ids = $this->projectModel->getAllIds();
} else {
- $project_ids = $this->projectPermission->getActiveProjectIds($this->userSession->getId());
+ $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId());
}
- return array($user_id, $project_ids, $this->user->getActiveUsersList(true));
+ return array($user_id, $project_ids, $this->userModel->getActiveUsersList(true));
}
private function role($role, $action, $title, $title_user)
{
list($user_id, $project_ids, $users) = $this->common();
- $query = $this->projectPermission->getQueryByRole($project_ids, $role)->callback(array($this->project, 'applyColumnStats'));
+ $query = $this->projectPermissionModel->getQueryByRole($project_ids, $role)->callback(array($this->projectModel, 'applyColumnStats'));
if ($user_id !== UserModel::EVERYBODY_ID && isset($users[$user_id])) {
$query->eq(UserModel::TABLE.'.id', $user_id);
@@ -39,13 +39,13 @@ class Projectuser extends Base
}
$paginator = $this->paginator
- ->setUrl('projectuser', $action, array('user_id' => $user_id))
+ ->setUrl('ProjectUserOverviewController', $action, array('user_id' => $user_id))
->setMax(30)
->setOrder('projects.name')
->setQuery($query)
->calculate();
- $this->response->html($this->helper->layout->projectUser('project_user/roles', array(
+ $this->response->html($this->helper->layout->projectUser('project_user_overview/roles', array(
'paginator' => $paginator,
'title' => $title,
'user_id' => $user_id,
@@ -57,7 +57,7 @@ class Projectuser extends Base
{
list($user_id, $project_ids, $users) = $this->common();
- $query = $this->taskFinder->getProjectUserOverviewQuery($project_ids, $is_active);
+ $query = $this->taskFinderModel->getProjectUserOverviewQuery($project_ids, $is_active);
if ($user_id !== UserModel::EVERYBODY_ID && isset($users[$user_id])) {
$query->eq(TaskModel::TABLE.'.owner_id', $user_id);
@@ -65,13 +65,13 @@ class Projectuser extends Base
}
$paginator = $this->paginator
- ->setUrl('projectuser', $action, array('user_id' => $user_id))
+ ->setUrl('ProjectUserOverviewController', $action, array('user_id' => $user_id))
->setMax(50)
->setOrder(TaskModel::TABLE.'.id')
->setQuery($query)
->calculate();
- $this->response->html($this->helper->layout->projectUser('project_user/tasks', array(
+ $this->response->html($this->helper->layout->projectUser('project_user_overview/tasks', array(
'paginator' => $paginator,
'title' => $title,
'user_id' => $user_id,
@@ -94,7 +94,7 @@ class Projectuser extends Base
*/
public function members()
{
- $this->role(ROLE::PROJECT_MEMBER, 'members', t('People who are project members'), 'Projects where "%s" is member');
+ $this->role(Role::PROJECT_MEMBER, 'members', t('People who are project members'), 'Projects where "%s" is member');
}
/**
@@ -122,8 +122,8 @@ class Projectuser extends Base
{
$project = $this->getProject();
- return $this->response->html($this->template->render('project_user/tooltip_users', array(
- 'users' => $this->projectUserRole->getAllUsersGroupedByRole($project['id']),
+ return $this->response->html($this->template->render('project_user_overview/tooltip_users', array(
+ 'users' => $this->projectUserRoleModel->getAllUsersGroupedByRole($project['id']),
'roles' => $this->role->getProjectRoles(),
)));
}
diff --git a/app/Controller/ProjectViewController.php b/app/Controller/ProjectViewController.php
new file mode 100644
index 00000000..92b93804
--- /dev/null
+++ b/app/Controller/ProjectViewController.php
@@ -0,0 +1,162 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class ProjectViewController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class ProjectViewController extends BaseController
+{
+ /**
+ * Show the project information page
+ *
+ * @access public
+ */
+ public function show()
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->helper->layout->project('project_view/show', array(
+ 'project' => $project,
+ 'stats' => $this->projectModel->getTaskStats($project['id']),
+ 'title' => $project['name'],
+ )));
+ }
+
+ /**
+ * Public access management
+ *
+ * @access public
+ */
+ public function share()
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->helper->layout->project('project_view/share', array(
+ 'project' => $project,
+ 'title' => t('Public access'),
+ )));
+ }
+
+ /**
+ * Change project sharing
+ *
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function updateSharing()
+ {
+ $project = $this->getProject();
+ $this->checkCSRFParam();
+ $switch = $this->request->getStringParam('switch');
+
+ if ($this->projectModel->{$switch.'PublicAccess'}($project['id'])) {
+ $this->flash->success(t('Project updated successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to update this project.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectViewController', 'share', array('project_id' => $project['id'])));
+ }
+
+ /**
+ * Integrations page
+ *
+ * @access public
+ */
+ public function integrations()
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->helper->layout->project('project_view/integrations', array(
+ 'project' => $project,
+ 'title' => t('Integrations'),
+ 'webhook_token' => $this->configModel->get('webhook_token'),
+ 'values' => $this->projectMetadataModel->getAll($project['id']),
+ 'errors' => array(),
+ )));
+ }
+
+ /**
+ * Update integrations
+ *
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function updateIntegrations()
+ {
+ $project = $this->getProject();
+
+ $this->projectMetadataModel->save($project['id'], $this->request->getValues());
+ $this->flash->success(t('Project updated successfully.'));
+ $this->response->redirect($this->helper->url->to('ProjectViewController', 'integrations', array('project_id' => $project['id'])));
+ }
+
+ /**
+ * Display project notifications
+ *
+ * @access public
+ */
+ public function notifications()
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->helper->layout->project('project_view/notifications', array(
+ 'notifications' => $this->projectNotificationModel->readSettings($project['id']),
+ 'types' => $this->projectNotificationTypeModel->getTypes(),
+ 'project' => $project,
+ 'title' => t('Notifications'),
+ )));
+ }
+
+ /**
+ * Update notifications
+ *
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function updateNotifications()
+ {
+ $project = $this->getProject();
+ $values = $this->request->getValues();
+
+ $this->projectNotificationModel->saveSettings($project['id'], $values);
+ $this->flash->success(t('Project updated successfully.'));
+ $this->response->redirect($this->helper->url->to('ProjectViewController', 'notifications', array('project_id' => $project['id'])));
+ }
+
+ /**
+ * Duplicate a project
+ *
+ * @author Antonio Rabelo
+ * @author Michael Lüpkes
+ * @access public
+ */
+ public function duplicate()
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->helper->layout->project('project_view/duplicate', array(
+ 'project' => $project,
+ 'title' => t('Clone this project')
+ )));
+ }
+
+ /**
+ * Do project duplication
+ */
+ public function doDuplication()
+ {
+ $project = $this->getProject();
+ $project_id = $this->projectDuplicationModel->duplicate($project['id'], array_keys($this->request->getValues()), $this->userSession->getId());
+
+ if ($project_id !== false) {
+ $this->flash->success(t('Project cloned successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to clone this project.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectViewController', 'show', array('project_id' => $project_id)));
+ }
+}
diff --git a/app/Controller/Search.php b/app/Controller/SearchController.php
index a42e9d3d..8557b182 100644
--- a/app/Controller/Search.php
+++ b/app/Controller/SearchController.php
@@ -5,21 +5,21 @@ namespace Kanboard\Controller;
use Kanboard\Filter\TaskProjectsFilter;
/**
- * Search controller
+ * Search Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Search extends Base
+class SearchController extends BaseController
{
public function index()
{
- $projects = $this->projectUserRole->getProjectsByUser($this->userSession->getId());
+ $projects = $this->projectUserRoleModel->getProjectsByUser($this->userSession->getId());
$search = urldecode($this->request->getStringParam('search'));
$nb_tasks = 0;
$paginator = $this->paginator
- ->setUrl('search', 'index', array('search' => $search))
+ ->setUrl('SearchController', 'index', array('search' => $search))
->setMax(30)
->setOrder('tasks.id')
->setDirection('DESC');
@@ -39,7 +39,7 @@ class Search extends Base
$this->response->html($this->helper->layout->app('search/index', array(
'values' => array(
'search' => $search,
- 'controller' => 'search',
+ 'controller' => 'SearchController',
'action' => 'index',
),
'paginator' => $paginator,
@@ -56,7 +56,7 @@ class Search extends Base
$this->response->html($this->helper->layout->app('search/activity', array(
'values' => array(
'search' => $search,
- 'controller' => 'search',
+ 'controller' => 'SearchController',
'action' => 'activity',
),
'title' => t('Search in activity stream').($nb_events > 0 ? ' ('.$nb_events.')' : ''),
diff --git a/app/Controller/Subtask.php b/app/Controller/SubtaskController.php
index dea2b08e..93dab5cd 100644
--- a/app/Controller/Subtask.php
+++ b/app/Controller/SubtaskController.php
@@ -2,18 +2,25 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
+use Kanboard\Core\Controller\PageNotFoundException;
+
/**
* Subtask controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Subtask extends Base
+class SubtaskController extends BaseController
{
/**
* Creation form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws AccessForbiddenException
+ * @throws PageNotFoundException
*/
public function create(array $values = array(), array $errors = array())
{
@@ -29,7 +36,7 @@ class Subtask extends Base
$this->response->html($this->template->render('subtask/create', array(
'values' => $values,
'errors' => $errors,
- 'users_list' => $this->projectUserRole->getAssignableUsersList($task['project_id']),
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($task['project_id']),
'task' => $task,
)));
}
@@ -47,7 +54,7 @@ class Subtask extends Base
list($valid, $errors) = $this->subtaskValidator->validateCreation($values);
if ($valid) {
- if ($this->subtask->create($values)) {
+ if ($this->subtaskModel->create($values) !== false) {
$this->flash->success(t('Sub-task added successfully.'));
} else {
$this->flash->failure(t('Unable to create your sub-task.'));
@@ -57,27 +64,31 @@ class Subtask extends Base
return $this->create(array('project_id' => $task['project_id'], 'task_id' => $task['id'], 'another_subtask' => 1));
}
- return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks'), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks'), true);
}
- $this->create($values, $errors);
+ return $this->create($values, $errors);
}
/**
* Edit form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws AccessForbiddenException
+ * @throws PageNotFoundException
*/
public function edit(array $values = array(), array $errors = array())
{
$task = $this->getTask();
- $subtask = $this->getSubTask();
+ $subtask = $this->getSubtask();
$this->response->html($this->template->render('subtask/edit', array(
'values' => empty($values) ? $subtask : $values,
'errors' => $errors,
- 'users_list' => $this->projectUserRole->getAssignableUsersList($task['project_id']),
- 'status_list' => $this->subtask->getStatusList(),
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($task['project_id']),
+ 'status_list' => $this->subtaskModel->getStatusList(),
'subtask' => $subtask,
'task' => $task,
)));
@@ -97,16 +108,16 @@ class Subtask extends Base
list($valid, $errors) = $this->subtaskValidator->validateModification($values);
if ($valid) {
- if ($this->subtask->update($values)) {
+ if ($this->subtaskModel->update($values)) {
$this->flash->success(t('Sub-task updated successfully.'));
} else {
$this->flash->failure(t('Unable to update your sub-task.'));
}
- return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
@@ -136,13 +147,13 @@ class Subtask extends Base
$task = $this->getTask();
$subtask = $this->getSubtask();
- if ($this->subtask->remove($subtask['id'])) {
+ if ($this->subtaskModel->remove($subtask['id'])) {
$this->flash->success(t('Sub-task removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this sub-task.'));
}
- $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
}
/**
@@ -156,11 +167,11 @@ class Subtask extends Base
$task_id = $this->request->getIntegerParam('task_id');
$values = $this->request->getJson();
- if (! empty($values) && $this->helper->user->hasProjectAccess('Subtask', 'movePosition', $project_id)) {
- $result = $this->subtask->changePosition($task_id, $values['subtask_id'], $values['position']);
- return $this->response->json(array('result' => $result));
+ if (! empty($values) && $this->helper->user->hasProjectAccess('SubtaskController', 'movePosition', $project_id)) {
+ $result = $this->subtaskModel->changePosition($task_id, $values['subtask_id'], $values['position']);
+ $this->response->json(array('result' => $result));
+ } else {
+ throw new AccessForbiddenException();
}
-
- $this->forbidden();
}
}
diff --git a/app/Controller/SubtaskConverterController.php b/app/Controller/SubtaskConverterController.php
new file mode 100644
index 00000000..65bcd2da
--- /dev/null
+++ b/app/Controller/SubtaskConverterController.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class SubtaskConverterController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class SubtaskConverterController extends BaseController
+{
+ public function show()
+ {
+ $task = $this->getTask();
+ $subtask = $this->getSubtask();
+
+ $this->response->html($this->template->render('subtask_converter/show', array(
+ 'subtask' => $subtask,
+ 'task' => $task,
+ )));
+ }
+
+ public function save()
+ {
+ $project = $this->getProject();
+ $subtask = $this->getSubtask();
+
+ $task_id = $this->subtaskModel->convertToTask($project['id'], $subtask['id']);
+
+ if ($task_id !== false) {
+ $this->flash->success(t('Subtask converted to task successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to convert the subtask.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $project['id'], 'task_id' => $task_id)), true);
+ }
+}
diff --git a/app/Controller/SubtaskRestriction.php b/app/Controller/SubtaskRestrictionController.php
index 56024867..084fc0d9 100644
--- a/app/Controller/SubtaskRestriction.php
+++ b/app/Controller/SubtaskRestrictionController.php
@@ -2,32 +2,32 @@
namespace Kanboard\Controller;
-use Kanboard\Model\Subtask as SubtaskModel;
+use Kanboard\Model\SubtaskModel;
/**
* Subtask Restriction
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class SubtaskRestriction extends Base
+class SubtaskRestrictionController extends BaseController
{
/**
* Show popup
*
* @access public
*/
- public function popover()
+ public function show()
{
$task = $this->getTask();
$subtask = $this->getSubtask();
- $this->response->html($this->template->render('subtask_restriction/popover', array(
+ $this->response->html($this->template->render('subtask_restriction/show', array(
'status_list' => array(
SubtaskModel::STATUS_TODO => t('Todo'),
SubtaskModel::STATUS_DONE => t('Done'),
),
- 'subtask_inprogress' => $this->subtask->getSubtaskInProgress($this->userSession->getId()),
+ 'subtask_inprogress' => $this->subtaskModel->getSubtaskInProgress($this->userSession->getId()),
'subtask' => $subtask,
'task' => $task,
)));
@@ -38,24 +38,24 @@ class SubtaskRestriction extends Base
*
* @access public
*/
- public function update()
+ public function save()
{
$task = $this->getTask();
$subtask = $this->getSubtask();
$values = $this->request->getValues();
// Change status of the previous "in progress" subtask
- $this->subtask->update(array(
+ $this->subtaskModel->update(array(
'id' => $values['id'],
'status' => $values['status'],
));
// Set the current subtask to "in progress"
- $this->subtask->update(array(
+ $this->subtaskModel->update(array(
'id' => $subtask['id'],
'status' => SubtaskModel::STATUS_INPROGRESS,
));
- $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
}
}
diff --git a/app/Controller/SubtaskStatus.php b/app/Controller/SubtaskStatusController.php
index 4fb82fc0..699951fe 100644
--- a/app/Controller/SubtaskStatus.php
+++ b/app/Controller/SubtaskStatusController.php
@@ -5,10 +5,10 @@ namespace Kanboard\Controller;
/**
* Subtask Status
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class SubtaskStatus extends Base
+class SubtaskStatusController extends BaseController
{
/**
* Change status to the next status: Toto -> In Progress -> Done
@@ -20,7 +20,7 @@ class SubtaskStatus extends Base
$task = $this->getTask();
$subtask = $this->getSubtask();
- $status = $this->subtask->toggleStatus($subtask['id']);
+ $status = $this->subtaskModel->toggleStatus($subtask['id']);
if ($this->request->getIntegerParam('refresh-table') === 0) {
$subtask['status'] = $status;
@@ -44,10 +44,10 @@ class SubtaskStatus extends Base
$timer = $this->request->getStringParam('timer');
if ($timer === 'start') {
- $this->subtaskTimeTracking->logStartTime($subtask_id, $this->userSession->getId());
+ $this->subtaskTimeTrackingModel->logStartTime($subtask_id, $this->userSession->getId());
} elseif ($timer === 'stop') {
- $this->subtaskTimeTracking->logEndTime($subtask_id, $this->userSession->getId());
- $this->subtaskTimeTracking->updateTaskTimeTracking($task['id']);
+ $this->subtaskTimeTrackingModel->logEndTime($subtask_id, $this->userSession->getId());
+ $this->subtaskTimeTrackingModel->updateTaskTimeTracking($task['id']);
}
$this->response->html($this->renderTable($task));
@@ -64,9 +64,8 @@ class SubtaskStatus extends Base
{
return $this->template->render('subtask/table', array(
'task' => $task,
- 'subtasks' => $this->subtask->getAll($task['id']),
+ 'subtasks' => $this->subtaskModel->getAll($task['id']),
'editable' => true,
- 'redirect' => 'task',
));
}
}
diff --git a/app/Controller/Swimlane.php b/app/Controller/SwimlaneController.php
index 8270a16f..c7c20ce8 100644
--- a/app/Controller/Swimlane.php
+++ b/app/Controller/SwimlaneController.php
@@ -2,30 +2,31 @@
namespace Kanboard\Controller;
-use Kanboard\Model\Swimlane as SwimlaneModel;
+use Kanboard\Core\Controller\AccessForbiddenException;
+use Kanboard\Core\Controller\PageNotFoundException;
+use Kanboard\Model\SwimlaneModel;
/**
- * Swimlanes
+ * Swimlanes Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Swimlane extends Base
+class SwimlaneController extends BaseController
{
/**
* Get the swimlane (common method between actions)
*
* @access private
- * @param integer $project_id
* @return array
+ * @throws PageNotFoundException
*/
- private function getSwimlane($project_id)
+ private function getSwimlane()
{
- $swimlane = $this->swimlane->getById($this->request->getIntegerParam('swimlane_id'));
+ $swimlane = $this->swimlaneModel->getById($this->request->getIntegerParam('swimlane_id'));
if (empty($swimlane)) {
- $this->flash->failure(t('Swimlane not found.'));
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project_id)));
+ throw new PageNotFoundException();
}
return $swimlane;
@@ -41,9 +42,9 @@ class Swimlane extends Base
$project = $this->getProject();
$this->response->html($this->helper->layout->project('swimlane/index', array(
- 'default_swimlane' => $this->swimlane->getDefault($project['id']),
- 'active_swimlanes' => $this->swimlane->getAllByStatus($project['id'], SwimlaneModel::ACTIVE),
- 'inactive_swimlanes' => $this->swimlane->getAllByStatus($project['id'], SwimlaneModel::INACTIVE),
+ 'default_swimlane' => $this->swimlaneModel->getDefault($project['id']),
+ 'active_swimlanes' => $this->swimlaneModel->getAllByStatus($project['id'], SwimlaneModel::ACTIVE),
+ 'inactive_swimlanes' => $this->swimlaneModel->getAllByStatus($project['id'], SwimlaneModel::INACTIVE),
'project' => $project,
'title' => t('Swimlanes')
)));
@@ -53,6 +54,9 @@ class Swimlane extends Base
* Create a new swimlane
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function create(array $values = array(), array $errors = array())
{
@@ -77,26 +81,29 @@ class Swimlane extends Base
list($valid, $errors) = $this->swimlaneValidator->validateCreation($values);
if ($valid) {
- if ($this->swimlane->create($values)) {
+ if ($this->swimlaneModel->create($values) !== false) {
$this->flash->success(t('Your swimlane have been created successfully.'));
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
+ return $this->response->redirect($this->helper->url->to('SwimlaneController', 'index', array('project_id' => $project['id'])));
} else {
$errors = array('name' => array(t('Another swimlane with the same name exists in the project')));
}
}
- $this->create($values, $errors);
+ return $this->create($values, $errors);
}
/**
* Edit default swimlane (display the form)
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function editDefault(array $values = array(), array $errors = array())
{
$project = $this->getProject();
- $swimlane = $this->swimlane->getDefault($project['id']);
+ $swimlane = $this->swimlaneModel->getDefault($project['id']);
$this->response->html($this->helper->layout->project('swimlane/edit_default', array(
'values' => empty($values) ? $swimlane : $values,
@@ -118,26 +125,29 @@ class Swimlane extends Base
list($valid, $errors) = $this->swimlaneValidator->validateDefaultModification($values);
if ($valid) {
- if ($this->swimlane->updateDefault($values)) {
+ if ($this->swimlaneModel->updateDefault($values)) {
$this->flash->success(t('The default swimlane have been updated successfully.'));
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])), true);
+ return $this->response->redirect($this->helper->url->to('SwimlaneController', 'index', array('project_id' => $project['id'])), true);
} else {
$this->flash->failure(t('Unable to update this swimlane.'));
}
}
- $this->editDefault($values, $errors);
+ return $this->editDefault($values, $errors);
}
/**
* Edit a swimlane (display the form)
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function edit(array $values = array(), array $errors = array())
{
$project = $this->getProject();
- $swimlane = $this->getSwimlane($project['id']);
+ $swimlane = $this->getSwimlane();
$this->response->html($this->helper->layout->project('swimlane/edit', array(
'values' => empty($values) ? $swimlane : $values,
@@ -159,15 +169,15 @@ class Swimlane extends Base
list($valid, $errors) = $this->swimlaneValidator->validateModification($values);
if ($valid) {
- if ($this->swimlane->update($values)) {
+ if ($this->swimlaneModel->update($values)) {
$this->flash->success(t('Swimlane updated successfully.'));
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
+ return $this->response->redirect($this->helper->url->to('SwimlaneController', 'index', array('project_id' => $project['id'])));
} else {
$errors = array('name' => array(t('Another swimlane with the same name exists in the project')));
}
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
@@ -178,7 +188,7 @@ class Swimlane extends Base
public function confirm()
{
$project = $this->getProject();
- $swimlane = $this->getSwimlane($project['id']);
+ $swimlane = $this->getSwimlane();
$this->response->html($this->helper->layout->project('swimlane/remove', array(
'project' => $project,
@@ -197,13 +207,13 @@ class Swimlane extends Base
$project = $this->getProject();
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
- if ($this->swimlane->remove($project['id'], $swimlane_id)) {
+ if ($this->swimlaneModel->remove($project['id'], $swimlane_id)) {
$this->flash->success(t('Swimlane removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this swimlane.'));
}
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('SwimlaneController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -217,13 +227,13 @@ class Swimlane extends Base
$project = $this->getProject();
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
- if ($this->swimlane->disable($project['id'], $swimlane_id)) {
+ if ($this->swimlaneModel->disable($project['id'], $swimlane_id)) {
$this->flash->success(t('Swimlane updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this swimlane.'));
}
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('SwimlaneController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -236,13 +246,13 @@ class Swimlane extends Base
$this->checkCSRFParam();
$project = $this->getProject();
- if ($this->swimlane->disableDefault($project['id'])) {
+ if ($this->swimlaneModel->disableDefault($project['id'])) {
$this->flash->success(t('Swimlane updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this swimlane.'));
}
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('SwimlaneController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -256,13 +266,13 @@ class Swimlane extends Base
$project = $this->getProject();
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
- if ($this->swimlane->enable($project['id'], $swimlane_id)) {
+ if ($this->swimlaneModel->enable($project['id'], $swimlane_id)) {
$this->flash->success(t('Swimlane updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this swimlane.'));
}
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('SwimlaneController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -275,13 +285,13 @@ class Swimlane extends Base
$this->checkCSRFParam();
$project = $this->getProject();
- if ($this->swimlane->enableDefault($project['id'])) {
+ if ($this->swimlaneModel->enableDefault($project['id'])) {
$this->flash->success(t('Swimlane updated successfully.'));
} else {
$this->flash->failure(t('Unable to update this swimlane.'));
}
- $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
+ $this->response->redirect($this->helper->url->to('SwimlaneController', 'index', array('project_id' => $project['id'])));
}
/**
@@ -295,10 +305,10 @@ class Swimlane extends Base
$values = $this->request->getJson();
if (! empty($values) && isset($values['swimlane_id']) && isset($values['position'])) {
- $result = $this->swimlane->changePosition($project['id'], $values['swimlane_id'], $values['position']);
- return $this->response->json(array('result' => $result));
+ $result = $this->swimlaneModel->changePosition($project['id'], $values['swimlane_id'], $values['position']);
+ $this->response->json(array('result' => $result));
+ } else {
+ throw new AccessForbiddenException();
}
-
- $this->forbidden();
}
}
diff --git a/app/Controller/Task.php b/app/Controller/Task.php
deleted file mode 100644
index 902a32d6..00000000
--- a/app/Controller/Task.php
+++ /dev/null
@@ -1,174 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-use Kanboard\Core\DateParser;
-
-/**
- * Task controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-class Task extends Base
-{
- /**
- * Public access (display a task)
- *
- * @access public
- */
- public function readonly()
- {
- $project = $this->project->getByToken($this->request->getStringParam('token'));
-
- // Token verification
- if (empty($project)) {
- return $this->forbidden(true);
- }
-
- $task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
-
- if (empty($task)) {
- return $this->notfound(true);
- }
-
- if ($task['project_id'] != $project['id']) {
- return $this->forbidden(true);
- }
-
- $this->response->html($this->helper->layout->app('task/public', array(
- 'project' => $project,
- 'comments' => $this->comment->getAll($task['id']),
- 'subtasks' => $this->subtask->getAll($task['id']),
- 'links' => $this->taskLink->getAllGroupedByLabel($task['id']),
- 'task' => $task,
- 'columns_list' => $this->column->getList($task['project_id']),
- 'colors_list' => $this->color->getList(),
- 'title' => $task['title'],
- 'no_layout' => true,
- 'auto_refresh' => true,
- 'not_editable' => true,
- )));
- }
-
- /**
- * Show a task
- *
- * @access public
- */
- public function show()
- {
- $task = $this->getTask();
- $subtasks = $this->subtask->getAll($task['id']);
-
- $values = array(
- 'id' => $task['id'],
- 'date_started' => $task['date_started'],
- 'time_estimated' => $task['time_estimated'] ?: '',
- 'time_spent' => $task['time_spent'] ?: '',
- );
-
- $values = $this->dateParser->format($values, array('date_started'), $this->config->get('application_datetime_format', DateParser::DATE_TIME_FORMAT));
-
- $this->response->html($this->helper->layout->task('task/show', array(
- 'task' => $task,
- 'project' => $this->project->getById($task['project_id']),
- 'values' => $values,
- 'files' => $this->taskFile->getAllDocuments($task['id']),
- 'images' => $this->taskFile->getAllImages($task['id']),
- 'comments' => $this->comment->getAll($task['id'], $this->userSession->getCommentSorting()),
- 'subtasks' => $subtasks,
- 'internal_links' => $this->taskLink->getAllGroupedByLabel($task['id']),
- 'external_links' => $this->taskExternalLink->getAll($task['id']),
- 'link_label_list' => $this->link->getList(0, false),
- )));
- }
-
- /**
- * Display task analytics
- *
- * @access public
- */
- public function analytics()
- {
- $task = $this->getTask();
-
- $this->response->html($this->helper->layout->task('task/analytics', array(
- 'task' => $task,
- 'project' => $this->project->getById($task['project_id']),
- 'lead_time' => $this->taskAnalytic->getLeadTime($task),
- 'cycle_time' => $this->taskAnalytic->getCycleTime($task),
- 'time_spent_columns' => $this->taskAnalytic->getTimeSpentByColumn($task),
- )));
- }
-
- /**
- * Display the time tracking details
- *
- * @access public
- */
- public function timetracking()
- {
- $task = $this->getTask();
-
- $subtask_paginator = $this->paginator
- ->setUrl('task', 'timetracking', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'pagination' => 'subtasks'))
- ->setMax(15)
- ->setOrder('start')
- ->setDirection('DESC')
- ->setQuery($this->subtaskTimeTracking->getTaskQuery($task['id']))
- ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
-
- $this->response->html($this->helper->layout->task('task/time_tracking_details', array(
- 'task' => $task,
- 'project' => $this->project->getById($task['project_id']),
- 'subtask_paginator' => $subtask_paginator,
- )));
- }
-
- /**
- * Display the task transitions
- *
- * @access public
- */
- public function transitions()
- {
- $task = $this->getTask();
-
- $this->response->html($this->helper->layout->task('task/transitions', array(
- 'task' => $task,
- 'project' => $this->project->getById($task['project_id']),
- 'transitions' => $this->transition->getAllByTask($task['id']),
- )));
- }
-
- /**
- * Remove a task
- *
- * @access public
- */
- public function remove()
- {
- $task = $this->getTask();
-
- if (! $this->taskPermission->canRemoveTask($task)) {
- $this->forbidden();
- }
-
- if ($this->request->getStringParam('confirmation') === 'yes') {
- $this->checkCSRFParam();
-
- if ($this->task->remove($task['id'])) {
- $this->flash->success(t('Task removed successfully.'));
- } else {
- $this->flash->failure(t('Unable to remove this task.'));
- }
-
- $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
- }
-
- $this->response->html($this->template->render('task/remove', array(
- 'task' => $task,
- )));
- }
-}
diff --git a/app/Controller/TaskHelper.php b/app/Controller/TaskAjaxController.php
index 6835ab2b..f9feff15 100644
--- a/app/Controller/TaskHelper.php
+++ b/app/Controller/TaskAjaxController.php
@@ -9,12 +9,12 @@ use Kanboard\Filter\TaskTitleFilter;
use Kanboard\Formatter\TaskAutoCompleteFormatter;
/**
- * Task Ajax Helper
+ * Task Ajax Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class TaskHelper extends Base
+class TaskAjaxController extends BaseController
{
/**
* Task auto-completion (Ajax)
@@ -24,7 +24,7 @@ class TaskHelper extends Base
public function autocomplete()
{
$search = $this->request->getStringParam('term');
- $project_ids = $this->projectPermission->getActiveProjectIds($this->userSession->getId());
+ $project_ids = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId());
$exclude_task_id = $this->request->getIntegerParam('exclude_task_id');
if (empty($project_ids)) {
diff --git a/app/Controller/TaskBulkController.php b/app/Controller/TaskBulkController.php
new file mode 100644
index 00000000..df7f589b
--- /dev/null
+++ b/app/Controller/TaskBulkController.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class TaskBulkController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class TaskBulkController extends BaseController
+{
+ /**
+ * Show the form
+ *
+ * @param array $values
+ * @param array $errors
+ */
+ public function show(array $values = array(), array $errors = array())
+ {
+ $project = $this->getProject();
+
+ if (empty($values)) {
+ $values = array(
+ 'swimlane_id' => $this->request->getIntegerParam('swimlane_id'),
+ 'column_id' => $this->request->getIntegerParam('column_id'),
+ 'project_id' => $project['id'],
+ );
+ }
+
+ $this->response->html($this->template->render('task_bulk/show', array(
+ 'project' => $project,
+ 'values' => $values,
+ 'errors' => $errors,
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id'], true, false, true),
+ 'colors_list' => $this->colorModel->getList(),
+ 'categories_list' => $this->categoryModel->getList($project['id']),
+ )));
+ }
+
+ /**
+ * Save all tasks in the database
+ */
+ public function save()
+ {
+ $project = $this->getProject();
+ $values = $this->request->getValues();
+ list($valid, $errors) = $this->taskValidator->validateBulkCreation($values);
+
+ if ($valid) {
+ $this->createTasks($project, $values);
+ $this->response->redirect($this->helper->url->to(
+ 'BoardViewController',
+ 'show',
+ array('project_id' => $project['id']),
+ 'swimlane-'. $values['swimlane_id']
+ ), true);
+ } else {
+ $this->show($values, $errors);
+ }
+ }
+
+ /**
+ * Create all tasks
+ *
+ * @param array $project
+ * @param array $values
+ */
+ protected function createTasks(array $project, array $values)
+ {
+ $tasks = preg_split('/\r\n|[\r\n]/', $values['tasks']);
+
+ foreach ($tasks as $title) {
+ $title = trim($title);
+
+ if (! empty($title)) {
+ $this->taskCreationModel->create(array(
+ 'title' => $title,
+ 'column_id' => $values['column_id'],
+ 'swimlane_id' => $values['swimlane_id'],
+ 'category_id' => empty($values['category_id']) ? 0 : $values['category_id'],
+ 'owner_id' => empty($values['owner_id']) ? 0 : $values['owner_id'],
+ 'color_id' => $values['color_id'],
+ 'project_id' => $project['id'],
+ ));
+ }
+ }
+ }
+}
diff --git a/app/Controller/Taskcreation.php b/app/Controller/TaskCreationController.php
index 1d8a0e29..819de96e 100644
--- a/app/Controller/Taskcreation.php
+++ b/app/Controller/TaskCreationController.php
@@ -3,28 +3,31 @@
namespace Kanboard\Controller;
/**
- * Task Creation controller
+ * Task Creation Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Taskcreation extends Base
+class TaskCreationController extends BaseController
{
/**
* Display a form to create a new task
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
- public function create(array $values = array(), array $errors = array())
+ public function show(array $values = array(), array $errors = array())
{
$project = $this->getProject();
- $swimlanes_list = $this->swimlane->getList($project['id'], false, true);
+ $swimlanes_list = $this->swimlaneModel->getList($project['id'], false, true);
if (empty($values)) {
$values = array(
'swimlane_id' => $this->request->getIntegerParam('swimlane_id', key($swimlanes_list)),
'column_id' => $this->request->getIntegerParam('column_id'),
- 'color_id' => $this->color->getDefaultColor(),
+ 'color_id' => $this->colorModel->getDefaultColor(),
'owner_id' => $this->userSession->getId(),
);
@@ -32,14 +35,14 @@ class Taskcreation extends Base
$values = $this->hook->merge('controller:task-creation:form:default', $values, array('default_values' => $values));
}
- $this->response->html($this->template->render('task_creation/form', array(
+ $this->response->html($this->template->render('task_creation/show', array(
'project' => $project,
'errors' => $errors,
'values' => $values + array('project_id' => $project['id']),
- 'columns_list' => $this->column->getList($project['id']),
- 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id'], true, false, true),
- 'colors_list' => $this->color->getList(),
- 'categories_list' => $this->category->getList($project['id']),
+ 'columns_list' => $this->columnModel->getList($project['id']),
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id'], true, false, true),
+ 'colors_list' => $this->colorModel->getList(),
+ 'categories_list' => $this->categoryModel->getList($project['id']),
'swimlanes_list' => $swimlanes_list,
'title' => $project['name'].' &gt; '.t('New task')
)));
@@ -57,19 +60,19 @@ class Taskcreation extends Base
list($valid, $errors) = $this->taskValidator->validateCreation($values);
- if ($valid && $this->taskCreation->create($values)) {
+ if ($valid && $this->taskCreationModel->create($values)) {
$this->flash->success(t('Task created successfully.'));
return $this->afterSave($project, $values);
}
$this->flash->failure(t('Unable to create your task.'));
- $this->create($values, $errors);
+ return $this->show($values, $errors);
}
private function afterSave(array $project, array &$values)
{
if (isset($values['another_task']) && $values['another_task'] == 1) {
- return $this->create(array(
+ return $this->show(array(
'owner_id' => $values['owner_id'],
'color_id' => $values['color_id'],
'category_id' => isset($values['category_id']) ? $values['category_id'] : 0,
@@ -79,6 +82,6 @@ class Taskcreation extends Base
));
}
- $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id'])));
+ return $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id'])), true);
}
}
diff --git a/app/Controller/Taskduplication.php b/app/Controller/TaskDuplicationController.php
index 8fca930d..6a475374 100644
--- a/app/Controller/Taskduplication.php
+++ b/app/Controller/TaskDuplicationController.php
@@ -5,10 +5,10 @@ namespace Kanboard\Controller;
/**
* Task Duplication controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Taskduplication extends Base
+class TaskDuplicationController extends BaseController
{
/**
* Duplicate a task
@@ -21,18 +21,18 @@ class Taskduplication extends Base
if ($this->request->getStringParam('confirmation') === 'yes') {
$this->checkCSRFParam();
- $task_id = $this->taskDuplication->duplicate($task['id']);
+ $task_id = $this->taskDuplicationModel->duplicate($task['id']);
if ($task_id > 0) {
$this->flash->success(t('Task created successfully.'));
- $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task_id)));
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task_id)));
} else {
$this->flash->failure(t('Unable to create this task.'));
- $this->response->redirect($this->helper->url->to('taskduplication', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskDuplicationController', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
}
}
- $this->response->html($this->template->render('task_duplication/duplicate', array(
+ return $this->response->html($this->template->render('task_duplication/duplicate', array(
'task' => $task,
)));
}
@@ -50,20 +50,20 @@ class Taskduplication extends Base
$values = $this->request->getValues();
list($valid, ) = $this->taskValidator->validateProjectModification($values);
- if ($valid && $this->taskDuplication->moveToProject($task['id'],
+ if ($valid && $this->taskDuplicationModel->moveToProject($task['id'],
$values['project_id'],
$values['swimlane_id'],
$values['column_id'],
$values['category_id'],
$values['owner_id'])) {
$this->flash->success(t('Task updated successfully.'));
- $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task['id'])));
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $values['project_id'], 'task_id' => $task['id'])));
}
$this->flash->failure(t('Unable to update your task.'));
}
- $this->chooseDestination($task, 'task_duplication/move');
+ return $this->chooseDestination($task, 'task_duplication/move');
}
/**
@@ -80,21 +80,21 @@ class Taskduplication extends Base
list($valid, ) = $this->taskValidator->validateProjectModification($values);
if ($valid) {
- $task_id = $this->taskDuplication->duplicateToProject(
+ $task_id = $this->taskDuplicationModel->duplicateToProject(
$task['id'], $values['project_id'], $values['swimlane_id'],
$values['column_id'], $values['category_id'], $values['owner_id']
);
if ($task_id > 0) {
$this->flash->success(t('Task created successfully.'));
- $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task_id)));
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $values['project_id'], 'task_id' => $task_id)));
}
}
$this->flash->failure(t('Unable to create your task.'));
}
- $this->chooseDestination($task, 'task_duplication/copy');
+ return $this->chooseDestination($task, 'task_duplication/copy');
}
/**
@@ -107,19 +107,19 @@ class Taskduplication extends Base
private function chooseDestination(array $task, $template)
{
$values = array();
- $projects_list = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId());
+ $projects_list = $this->projectUserRoleModel->getActiveProjectsByUser($this->userSession->getId());
unset($projects_list[$task['project_id']]);
if (! empty($projects_list)) {
$dst_project_id = $this->request->getIntegerParam('dst_project_id', key($projects_list));
- $swimlanes_list = $this->swimlane->getList($dst_project_id, false, true);
- $columns_list = $this->column->getList($dst_project_id);
- $categories_list = $this->category->getList($dst_project_id);
- $users_list = $this->projectUserRole->getAssignableUsersList($dst_project_id);
+ $swimlanes_list = $this->swimlaneModel->getList($dst_project_id, false, true);
+ $columns_list = $this->columnModel->getList($dst_project_id);
+ $categories_list = $this->categoryModel->getList($dst_project_id);
+ $users_list = $this->projectUserRoleModel->getAssignableUsersList($dst_project_id);
- $values = $this->taskDuplication->checkDestinationProjectValues($task);
+ $values = $this->taskDuplicationModel->checkDestinationProjectValues($task);
$values['project_id'] = $dst_project_id;
} else {
$swimlanes_list = array();
diff --git a/app/Controller/TaskExternalLink.php b/app/Controller/TaskExternalLinkController.php
index 0db8ec37..9c04eb00 100644
--- a/app/Controller/TaskExternalLink.php
+++ b/app/Controller/TaskExternalLinkController.php
@@ -2,20 +2,25 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\PageNotFoundException;
use Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound;
/**
* Task External Link Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class TaskExternalLink extends Base
+class TaskExternalLinkController extends BaseController
{
/**
* First creation form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws PageNotFoundException
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
*/
public function find(array $values = array(), array $errors = array())
{
@@ -36,11 +41,10 @@ class TaskExternalLink extends Base
*/
public function create()
{
- try {
-
- $task = $this->getTask();
- $values = $this->request->getValues();
+ $task = $this->getTask();
+ $values = $this->request->getValues();
+ try {
$provider = $this->externalLinkManager->setUserInput($values)->find();
$link = $provider->getLink();
@@ -72,18 +76,23 @@ class TaskExternalLink extends Base
$values = $this->request->getValues();
list($valid, $errors) = $this->externalLinkValidator->validateCreation($values);
- if ($valid && $this->taskExternalLink->create($values)) {
+ if ($valid && $this->taskExternalLinkModel->create($values) !== false) {
$this->flash->success(t('Link added successfully.'));
- return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
* Edit form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws ExternalLinkProviderNotFound
+ * @throws PageNotFoundException
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
*/
public function edit(array $values = array(), array $errors = array())
{
@@ -91,11 +100,11 @@ class TaskExternalLink extends Base
$link_id = $this->request->getIntegerParam('link_id');
if ($link_id > 0) {
- $values = $this->taskExternalLink->getById($link_id);
+ $values = $this->taskExternalLinkModel->getById($link_id);
}
if (empty($values)) {
- return $this->notfound();
+ throw new PageNotFoundException();
}
$provider = $this->externalLinkManager->getProvider($values['link_type']);
@@ -119,12 +128,12 @@ class TaskExternalLink extends Base
$values = $this->request->getValues();
list($valid, $errors) = $this->externalLinkValidator->validateModification($values);
- if ($valid && $this->taskExternalLink->update($values)) {
+ if ($valid && $this->taskExternalLinkModel->update($values)) {
$this->flash->success(t('Link updated successfully.'));
- return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
@@ -136,10 +145,10 @@ class TaskExternalLink extends Base
{
$task = $this->getTask();
$link_id = $this->request->getIntegerParam('link_id');
- $link = $this->taskExternalLink->getById($link_id);
+ $link = $this->taskExternalLinkModel->getById($link_id);
if (empty($link)) {
- return $this->notfound();
+ throw new PageNotFoundException();
}
$this->response->html($this->template->render('task_external_link/remove', array(
@@ -158,12 +167,12 @@ class TaskExternalLink extends Base
$this->checkCSRFParam();
$task = $this->getTask();
- if ($this->taskExternalLink->remove($this->request->getIntegerParam('link_id'))) {
+ if ($this->taskExternalLinkModel->remove($this->request->getIntegerParam('link_id'))) {
$this->flash->success(t('Link removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this link.'));
}
- $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
}
diff --git a/app/Controller/TaskFile.php b/app/Controller/TaskFileController.php
index 2b0152a7..77c0c026 100644
--- a/app/Controller/TaskFile.php
+++ b/app/Controller/TaskFileController.php
@@ -5,10 +5,10 @@ namespace Kanboard\Controller;
/**
* Task File Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class TaskFile extends Base
+class TaskFileController extends BaseController
{
/**
* Screenshot
@@ -19,12 +19,12 @@ class TaskFile extends Base
{
$task = $this->getTask();
- if ($this->request->isPost() && $this->taskFile->uploadScreenshot($task['id'], $this->request->getValue('screenshot')) !== false) {
+ if ($this->request->isPost() && $this->taskFileModel->uploadScreenshot($task['id'], $this->request->getValue('screenshot')) !== false) {
$this->flash->success(t('Screenshot uploaded successfully.'));
- return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
- $this->response->html($this->template->render('task_file/screenshot', array(
+ return $this->response->html($this->template->render('task_file/screenshot', array(
'task' => $task,
)));
}
@@ -53,11 +53,11 @@ class TaskFile extends Base
{
$task = $this->getTask();
- if (! $this->taskFile->uploadFiles($task['id'], $this->request->getFileInfo('files'))) {
+ if (! $this->taskFileModel->uploadFiles($task['id'], $this->request->getFileInfo('files'))) {
$this->flash->failure(t('Unable to upload the file.'));
}
- $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
/**
@@ -69,15 +69,15 @@ class TaskFile extends Base
{
$this->checkCSRFParam();
$task = $this->getTask();
- $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->taskFileModel->getById($this->request->getIntegerParam('file_id'));
- if ($file['task_id'] == $task['id'] && $this->taskFile->remove($file['id'])) {
+ if ($file['task_id'] == $task['id'] && $this->taskFileModel->remove($file['id'])) {
$this->flash->success(t('File removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this file.'));
}
- $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
/**
@@ -88,7 +88,7 @@ class TaskFile extends Base
public function confirm()
{
$task = $this->getTask();
- $file = $this->taskFile->getById($this->request->getIntegerParam('file_id'));
+ $file = $this->taskFileModel->getById($this->request->getIntegerParam('file_id'));
$this->response->html($this->template->render('task_file/remove', array(
'task' => $task,
diff --git a/app/Controller/TaskGanttController.php b/app/Controller/TaskGanttController.php
new file mode 100644
index 00000000..868368e1
--- /dev/null
+++ b/app/Controller/TaskGanttController.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Filter\TaskProjectFilter;
+use Kanboard\Formatter\TaskGanttFormatter;
+use Kanboard\Model\TaskModel;
+
+/**
+ * Tasks Gantt Controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class TaskGanttController extends BaseController
+{
+ /**
+ * Show Gantt chart for one project
+ */
+ public function show()
+ {
+ $project = $this->getProject();
+ $search = $this->helper->projectHeader->getSearchQuery($project);
+ $sorting = $this->request->getStringParam('sorting', 'board');
+ $filter = $this->taskLexer->build($search)->withFilter(new TaskProjectFilter($project['id']));
+
+ if ($sorting === 'date') {
+ $filter->getQuery()->asc(TaskModel::TABLE.'.date_started')->asc(TaskModel::TABLE.'.date_creation');
+ } else {
+ $filter->getQuery()->asc('column_position')->asc(TaskModel::TABLE.'.position');
+ }
+
+ $this->response->html($this->helper->layout->app('task_gantt/show', array(
+ 'project' => $project,
+ 'title' => $project['name'],
+ 'description' => $this->helper->projectHeader->getDescription($project),
+ 'sorting' => $sorting,
+ 'tasks' => $filter->format(new TaskGanttFormatter($this->container)),
+ )));
+ }
+
+ /**
+ * Save new task start date and due date
+ */
+ public function save()
+ {
+ $this->getProject();
+ $values = $this->request->getJson();
+
+ $result = $this->taskModificationModel->update(array(
+ 'id' => $values['id'],
+ 'date_started' => strtotime($values['start']),
+ 'date_due' => strtotime($values['end']),
+ ));
+
+ if (! $result) {
+ $this->response->json(array('message' => 'Unable to save task'), 400);
+ } else {
+ $this->response->json(array('message' => 'OK'), 201);
+ }
+ }
+}
diff --git a/app/Controller/TaskGanttCreationController.php b/app/Controller/TaskGanttCreationController.php
new file mode 100644
index 00000000..c2998a3e
--- /dev/null
+++ b/app/Controller/TaskGanttCreationController.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class TaskGanttCreationController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class TaskGanttCreationController extends BaseController
+{
+ /**
+ * Simplified form to create a new task
+ *
+ * @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function show(array $values = array(), array $errors = array())
+ {
+ $project = $this->getProject();
+
+ $values = $values + array(
+ 'project_id' => $project['id'],
+ 'column_id' => $this->columnModel->getFirstColumnId($project['id']),
+ 'position' => 1
+ );
+
+ $values = $this->hook->merge('controller:task:form:default', $values, array('default_values' => $values));
+ $values = $this->hook->merge('controller:gantt:task:form:default', $values, array('default_values' => $values));
+
+ $this->response->html($this->template->render('task_gantt_creation/show', array(
+ 'project' => $project,
+ 'errors' => $errors,
+ 'values' => $values,
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id'], true, false, true),
+ 'colors_list' => $this->colorModel->getList(),
+ 'categories_list' => $this->categoryModel->getList($project['id']),
+ 'swimlanes_list' => $this->swimlaneModel->getList($project['id'], false, true),
+ 'title' => $project['name'].' &gt; '.t('New task')
+ )));
+ }
+
+ /**
+ * Validate and save a new task
+ *
+ * @access public
+ */
+ public function save()
+ {
+ $project = $this->getProject();
+ $values = $this->request->getValues();
+
+ list($valid, $errors) = $this->taskValidator->validateCreation($values);
+
+ if ($valid) {
+ $task_id = $this->taskCreationModel->create($values);
+
+ if ($task_id !== false) {
+ $this->flash->success(t('Task created successfully.'));
+ return $this->response->redirect($this->helper->url->to('TaskGanttController', 'show', array('project_id' => $project['id'])));
+ } else {
+ $this->flash->failure(t('Unable to create your task.'));
+ }
+ }
+
+ return $this->show($values, $errors);
+ }
+}
diff --git a/app/Controller/TaskImport.php b/app/Controller/TaskImport.php
deleted file mode 100644
index 460c608c..00000000
--- a/app/Controller/TaskImport.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-use Kanboard\Core\Csv;
-
-/**
- * Task Import controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-class TaskImport extends Base
-{
- /**
- * Upload the file and ask settings
- *
- */
- public function step1(array $values = array(), array $errors = array())
- {
- $project = $this->getProject();
-
- $this->response->html($this->helper->layout->project('task_import/step1', array(
- 'project' => $project,
- 'values' => $values,
- 'errors' => $errors,
- 'max_size' => ini_get('upload_max_filesize'),
- 'delimiters' => Csv::getDelimiters(),
- 'enclosures' => Csv::getEnclosures(),
- 'title' => t('Import tasks from CSV file'),
- )));
- }
-
- /**
- * Process CSV file
- *
- */
- public function step2()
- {
- $project = $this->getProject();
- $values = $this->request->getValues();
- $filename = $this->request->getFilePath('file');
-
- if (! file_exists($filename)) {
- $this->step1($values, array('file' => array(t('Unable to read your file'))));
- }
-
- $this->taskImport->projectId = $project['id'];
-
- $csv = new Csv($values['delimiter'], $values['enclosure']);
- $csv->setColumnMapping($this->taskImport->getColumnMapping());
- $csv->read($filename, array($this->taskImport, 'import'));
-
- if ($this->taskImport->counter > 0) {
- $this->flash->success(t('%d task(s) have been imported successfully.', $this->taskImport->counter));
- } else {
- $this->flash->failure(t('Nothing have been imported!'));
- }
-
- $this->response->redirect($this->helper->url->to('taskImport', 'step1', array('project_id' => $project['id'])));
- }
-
- /**
- * Generate template
- *
- */
- public function template()
- {
- $this->response->forceDownload('tasks.csv');
- $this->response->csv(array($this->taskImport->getColumnMapping()));
- }
-}
diff --git a/app/Controller/TaskImportController.php b/app/Controller/TaskImportController.php
new file mode 100644
index 00000000..aff2d390
--- /dev/null
+++ b/app/Controller/TaskImportController.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Csv;
+
+/**
+ * Task Import controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class TaskImportController extends BaseController
+{
+ /**
+ * Upload the file and ask settings
+ *
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function show(array $values = array(), array $errors = array())
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->helper->layout->project('task_import/show', array(
+ 'project' => $project,
+ 'values' => $values,
+ 'errors' => $errors,
+ 'max_size' => ini_get('upload_max_filesize'),
+ 'delimiters' => Csv::getDelimiters(),
+ 'enclosures' => Csv::getEnclosures(),
+ 'title' => t('Import tasks from CSV file'),
+ ), 'task_import/sidebar'));
+ }
+
+ /**
+ * Process CSV file
+ */
+ public function save()
+ {
+ $project = $this->getProject();
+ $values = $this->request->getValues();
+ $filename = $this->request->getFilePath('file');
+
+ if (! file_exists($filename)) {
+ $this->show($values, array('file' => array(t('Unable to read your file'))));
+ } else {
+ $this->taskImport->projectId = $project['id'];
+
+ $csv = new Csv($values['delimiter'], $values['enclosure']);
+ $csv->setColumnMapping($this->taskImport->getColumnMapping());
+ $csv->read($filename, array($this->taskImport, 'import'));
+
+ if ($this->taskImport->counter > 0) {
+ $this->flash->success(t('%d task(s) have been imported successfully.', $this->taskImport->counter));
+ } else {
+ $this->flash->failure(t('Nothing have been imported!'));
+ }
+
+ $this->response->redirect($this->helper->url->to('TaskImportController', 'show', array('project_id' => $project['id'])));
+ }
+ }
+
+ /**
+ * Generate template
+ *
+ */
+ public function template()
+ {
+ $this->response->withFileDownload('tasks.csv');
+ $this->response->csv(array($this->taskImport->getColumnMapping()));
+ }
+}
diff --git a/app/Controller/TaskInternalLink.php b/app/Controller/TaskInternalLinkController.php
index ac5e04b7..a140f1ff 100644
--- a/app/Controller/TaskInternalLink.php
+++ b/app/Controller/TaskInternalLinkController.php
@@ -2,27 +2,30 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\PageNotFoundException;
+
/**
* TaskInternalLink Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Olivier Maridat
* @author Frederic Guillot
*/
-class TaskInternalLink extends Base
+class TaskInternalLinkController extends BaseController
{
/**
* Get the current link
*
* @access private
* @return array
+ * @throws PageNotFoundException
*/
private function getTaskLink()
{
- $link = $this->taskLink->getById($this->request->getIntegerParam('link_id'));
+ $link = $this->taskLinkModel->getById($this->request->getIntegerParam('link_id'));
if (empty($link)) {
- return $this->notfound();
+ throw new PageNotFoundException();
}
return $link;
@@ -32,6 +35,10 @@ class TaskInternalLink extends Base
* Creation form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws PageNotFoundException
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
*/
public function create(array $values = array(), array $errors = array())
{
@@ -41,7 +48,7 @@ class TaskInternalLink extends Base
'values' => $values,
'errors' => $errors,
'task' => $task,
- 'labels' => $this->link->getList(0, false),
+ 'labels' => $this->linkModel->getList(0, false),
)));
}
@@ -58,22 +65,26 @@ class TaskInternalLink extends Base
list($valid, $errors) = $this->taskLinkValidator->validateCreation($values);
if ($valid) {
- if ($this->taskLink->create($values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
+ if ($this->taskLinkModel->create($values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
$this->flash->success(t('Link added successfully.'));
- return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
$errors = array('title' => array(t('The exact same link already exists')));
$this->flash->failure(t('Unable to create your link.'));
}
- $this->create($values, $errors);
+ return $this->create($values, $errors);
}
/**
* Edit form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws PageNotFoundException
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
*/
public function edit(array $values = array(), array $errors = array())
{
@@ -81,7 +92,7 @@ class TaskInternalLink extends Base
$task_link = $this->getTaskLink();
if (empty($values)) {
- $opposite_task = $this->taskFinder->getById($task_link['opposite_task_id']);
+ $opposite_task = $this->taskFinderModel->getById($task_link['opposite_task_id']);
$values = $task_link;
$values['title'] = '#'.$opposite_task['id'].' - '.$opposite_task['title'];
}
@@ -91,7 +102,7 @@ class TaskInternalLink extends Base
'errors' => $errors,
'task_link' => $task_link,
'task' => $task,
- 'labels' => $this->link->getList(0, false)
+ 'labels' => $this->linkModel->getList(0, false)
)));
}
@@ -108,15 +119,15 @@ class TaskInternalLink extends Base
list($valid, $errors) = $this->taskLinkValidator->validateModification($values);
if ($valid) {
- if ($this->taskLink->update($values['id'], $values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
+ if ($this->taskLinkModel->update($values['id'], $values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
$this->flash->success(t('Link updated successfully.'));
- return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
}
$this->flash->failure(t('Unable to update your link.'));
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
/**
@@ -145,12 +156,12 @@ class TaskInternalLink extends Base
$this->checkCSRFParam();
$task = $this->getTask();
- if ($this->taskLink->remove($this->request->getIntegerParam('link_id'))) {
+ if ($this->taskLinkModel->remove($this->request->getIntegerParam('link_id'))) {
$this->flash->success(t('Link removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this link.'));
}
- $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
}
}
diff --git a/app/Controller/Listing.php b/app/Controller/TaskListController.php
index 2024ff03..c6d1fa92 100644
--- a/app/Controller/Listing.php
+++ b/app/Controller/TaskListController.php
@@ -3,15 +3,15 @@
namespace Kanboard\Controller;
use Kanboard\Filter\TaskProjectFilter;
-use Kanboard\Model\Task as TaskModel;
+use Kanboard\Model\TaskModel;
/**
- * List view controller
+ * Task List Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Listing extends Base
+class TaskListController extends BaseController
{
/**
* Show list view for projects
@@ -24,7 +24,7 @@ class Listing extends Base
$search = $this->helper->projectHeader->getSearchQuery($project);
$paginator = $this->paginator
- ->setUrl('listing', 'show', array('project_id' => $project['id']))
+ ->setUrl('TaskListController', 'show', array('project_id' => $project['id']))
->setMax(30)
->setOrder(TaskModel::TABLE.'.id')
->setDirection('DESC')
@@ -35,7 +35,7 @@ class Listing extends Base
)
->calculate();
- $this->response->html($this->helper->layout->app('listing/show', array(
+ $this->response->html($this->helper->layout->app('task_list/show', array(
'project' => $project,
'title' => $project['name'],
'description' => $this->helper->projectHeader->getDescription($project),
diff --git a/app/Controller/Taskmodification.php b/app/Controller/TaskModificationController.php
index 6b945f37..fc9113dd 100644
--- a/app/Controller/Taskmodification.php
+++ b/app/Controller/TaskModificationController.php
@@ -7,10 +7,10 @@ use Kanboard\Core\DateParser;
/**
* Task Modification controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Taskmodification extends Base
+class TaskModificationController extends BaseController
{
/**
* Set automatically the start date
@@ -20,14 +20,18 @@ class Taskmodification extends Base
public function start()
{
$task = $this->getTask();
- $this->taskModification->update(array('id' => $task['id'], 'date_started' => time()));
- $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
+ $this->taskModificationModel->update(array('id' => $task['id'], 'date_started' => time()));
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
}
/**
* Edit description form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function description(array $values = array(), array $errors = array())
{
@@ -57,27 +61,31 @@ class Taskmodification extends Base
list($valid, $errors) = $this->taskValidator->validateDescriptionCreation($values);
if ($valid) {
- if ($this->taskModification->update($values)) {
+ if ($this->taskModificationModel->update($values)) {
$this->flash->success(t('Task updated successfully.'));
} else {
$this->flash->failure(t('Unable to update your task.'));
}
- return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
}
- $this->description($values, $errors);
+ return $this->description($values, $errors);
}
/**
* Display a form to edit a task
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function edit(array $values = array(), array $errors = array())
{
$task = $this->getTask();
- $project = $this->project->getById($task['project_id']);
+ $project = $this->projectModel->getById($task['project_id']);
if (empty($values)) {
$values = $task;
@@ -85,17 +93,17 @@ class Taskmodification extends Base
$values = $this->hook->merge('controller:task-modification:form:default', $values, array('default_values' => $values));
}
- $values = $this->dateParser->format($values, array('date_due'), $this->config->get('application_date_format', DateParser::DATE_FORMAT));
- $values = $this->dateParser->format($values, array('date_started'), $this->config->get('application_datetime_format', DateParser::DATE_TIME_FORMAT));
+ $values = $this->dateParser->format($values, array('date_due'), $this->configModel->get('application_date_format', DateParser::DATE_FORMAT));
+ $values = $this->dateParser->format($values, array('date_started'), $this->configModel->get('application_datetime_format', DateParser::DATE_TIME_FORMAT));
$this->response->html($this->template->render('task_modification/edit_task', array(
'project' => $project,
'values' => $values,
'errors' => $errors,
'task' => $task,
- 'users_list' => $this->projectUserRole->getAssignableUsersList($task['project_id']),
- 'colors_list' => $this->color->getList(),
- 'categories_list' => $this->category->getList($task['project_id']),
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($task['project_id']),
+ 'colors_list' => $this->colorModel->getList(),
+ 'categories_list' => $this->categoryModel->getList($task['project_id']),
)));
}
@@ -111,9 +119,9 @@ class Taskmodification extends Base
list($valid, $errors) = $this->taskValidator->validateModification($values);
- if ($valid && $this->taskModification->update($values)) {
+ if ($valid && $this->taskModificationModel->update($values)) {
$this->flash->success(t('Task updated successfully.'));
- return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
} else {
$this->flash->failure(t('Unable to update your task.'));
$this->edit($values, $errors);
diff --git a/app/Controller/TaskPopoverController.php b/app/Controller/TaskPopoverController.php
new file mode 100644
index 00000000..bf4e23d5
--- /dev/null
+++ b/app/Controller/TaskPopoverController.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Task Popover
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class TaskPopoverController extends BaseController
+{
+ /**
+ * Change a task assignee directly from the board
+ *
+ * @access public
+ */
+ public function changeAssignee()
+ {
+ $task = $this->getTask();
+ $project = $this->projectModel->getById($task['project_id']);
+
+ $this->response->html($this->template->render('task_popover/change_assignee', array(
+ 'values' => $task,
+ 'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id']),
+ 'project' => $project,
+ )));
+ }
+
+ /**
+ * Validate an assignee modification
+ *
+ * @access public
+ */
+ public function updateAssignee()
+ {
+ $values = $this->request->getValues();
+
+ list($valid,) = $this->taskValidator->validateAssigneeModification($values);
+
+ if ($valid && $this->taskModificationModel->update($values)) {
+ $this->flash->success(t('Task updated successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to update your task.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $values['project_id'])), true);
+ }
+
+ /**
+ * Change a task category directly from the board
+ *
+ * @access public
+ */
+ public function changeCategory()
+ {
+ $task = $this->getTask();
+ $project = $this->projectModel->getById($task['project_id']);
+
+ $this->response->html($this->template->render('task_popover/change_category', array(
+ 'values' => $task,
+ 'categories_list' => $this->categoryModel->getList($project['id']),
+ 'project' => $project,
+ )));
+ }
+
+ /**
+ * Validate a category modification
+ *
+ * @access public
+ */
+ public function updateCategory()
+ {
+ $values = $this->request->getValues();
+
+ list($valid,) = $this->taskValidator->validateCategoryModification($values);
+
+ if ($valid && $this->taskModificationModel->update($values)) {
+ $this->flash->success(t('Task updated successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to update your task.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $values['project_id'])), true);
+ }
+
+ /**
+ * Screenshot popover
+ *
+ * @access public
+ */
+ public function screenshot()
+ {
+ $task = $this->getTask();
+
+ $this->response->html($this->template->render('task_file/screenshot', array(
+ 'task' => $task,
+ )));
+ }
+}
diff --git a/app/Controller/TaskRecurrence.php b/app/Controller/TaskRecurrenceController.php
index 569ef8d9..dc7a0e1b 100644
--- a/app/Controller/TaskRecurrence.php
+++ b/app/Controller/TaskRecurrenceController.php
@@ -5,15 +5,19 @@ namespace Kanboard\Controller;
/**
* Task Recurrence controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class TaskRecurrence extends Base
+class TaskRecurrenceController extends BaseController
{
/**
* Edit recurrence form
*
* @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
*/
public function edit(array $values = array(), array $errors = array())
{
@@ -27,10 +31,10 @@ class TaskRecurrence extends Base
'values' => $values,
'errors' => $errors,
'task' => $task,
- 'recurrence_status_list' => $this->task->getRecurrenceStatusList(),
- 'recurrence_trigger_list' => $this->task->getRecurrenceTriggerList(),
- 'recurrence_timeframe_list' => $this->task->getRecurrenceTimeframeList(),
- 'recurrence_basedate_list' => $this->task->getRecurrenceBasedateList(),
+ 'recurrence_status_list' => $this->taskModel->getRecurrenceStatusList(),
+ 'recurrence_trigger_list' => $this->taskModel->getRecurrenceTriggerList(),
+ 'recurrence_timeframe_list' => $this->taskModel->getRecurrenceTimeframeList(),
+ 'recurrence_basedate_list' => $this->taskModel->getRecurrenceBasedateList(),
)));
}
@@ -47,15 +51,15 @@ class TaskRecurrence extends Base
list($valid, $errors) = $this->taskValidator->validateEditRecurrence($values);
if ($valid) {
- if ($this->taskModification->update($values)) {
+ if ($this->taskModificationModel->update($values)) {
$this->flash->success(t('Task updated successfully.'));
} else {
$this->flash->failure(t('Unable to update your task.'));
}
- $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
}
- $this->edit($values, $errors);
+ return $this->edit($values, $errors);
}
}
diff --git a/app/Controller/Taskstatus.php b/app/Controller/TaskStatusController.php
index a67459c9..82b4f9c4 100644
--- a/app/Controller/Taskstatus.php
+++ b/app/Controller/TaskStatusController.php
@@ -5,10 +5,10 @@ namespace Kanboard\Controller;
/**
* Task Status controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class Taskstatus extends Base
+class TaskStatusController extends BaseController
{
/**
* Close a task
@@ -46,16 +46,16 @@ class Taskstatus extends Base
if ($this->request->getStringParam('confirmation') === 'yes') {
$this->checkCSRFParam();
- if ($this->taskStatus->$method($task['id'])) {
+ if ($this->taskStatusModel->$method($task['id'])) {
$this->flash->success($success_message);
} else {
$this->flash->failure($failure_message);
}
- return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
+ return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
}
- $this->response->html($this->template->render($template, array(
+ return $this->response->html($this->template->render($template, array(
'task' => $task,
)));
}
diff --git a/app/Controller/TaskSuppressionController.php b/app/Controller/TaskSuppressionController.php
new file mode 100644
index 00000000..600107c9
--- /dev/null
+++ b/app/Controller/TaskSuppressionController.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Controller\AccessForbiddenException;
+
+/**
+ * Class TaskSuppressionController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class TaskSuppressionController extends BaseController
+{
+ /**
+ * Confirmation dialog box before to remove the task
+ */
+ public function confirm()
+ {
+ $task = $this->getTask();
+
+ if (! $this->helper->user->canRemoveTask($task)) {
+ throw new AccessForbiddenException();
+ }
+
+ $this->response->html($this->template->render('task_suppression/remove', array(
+ 'task' => $task,
+ 'redirect' => $this->request->getStringParam('redirect'),
+ )));
+ }
+
+ /**
+ * Remove a task
+ */
+ public function remove()
+ {
+ $task = $this->getTask();
+ $this->checkCSRFParam();
+
+ if (! $this->helper->user->canRemoveTask($task)) {
+ throw new AccessForbiddenException();
+ }
+
+ if ($this->taskModel->remove($task['id'])) {
+ $this->flash->success(t('Task removed successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to remove this task.'));
+ }
+
+ $redirect = $this->request->getStringParam('redirect') === '';
+ $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $task['project_id'])), $redirect);
+ }
+}
diff --git a/app/Controller/TaskViewController.php b/app/Controller/TaskViewController.php
new file mode 100644
index 00000000..2a79ee45
--- /dev/null
+++ b/app/Controller/TaskViewController.php
@@ -0,0 +1,146 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Controller\AccessForbiddenException;
+use Kanboard\Core\Controller\PageNotFoundException;
+use Kanboard\Core\DateParser;
+
+/**
+ * Task Controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class TaskViewController extends BaseController
+{
+ /**
+ * Public access (display a task)
+ *
+ * @access public
+ */
+ public function readonly()
+ {
+ $project = $this->projectModel->getByToken($this->request->getStringParam('token'));
+
+ // Token verification
+ if (empty($project)) {
+ throw AccessForbiddenException::getInstance()->withoutLayout();
+ }
+
+ $task = $this->taskFinderModel->getDetails($this->request->getIntegerParam('task_id'));
+
+ if (empty($task)) {
+ throw PageNotFoundException::getInstance()->withoutLayout();
+ }
+
+ if ($task['project_id'] != $project['id']) {
+ throw AccessForbiddenException::getInstance()->withoutLayout();
+ }
+
+ $this->response->html($this->helper->layout->app('task/public', array(
+ 'project' => $project,
+ 'comments' => $this->commentModel->getAll($task['id']),
+ 'subtasks' => $this->subtaskModel->getAll($task['id']),
+ 'links' => $this->taskLinkModel->getAllGroupedByLabel($task['id']),
+ 'task' => $task,
+ 'columns_list' => $this->columnModel->getList($task['project_id']),
+ 'colors_list' => $this->colorModel->getList(),
+ 'title' => $task['title'],
+ 'no_layout' => true,
+ 'auto_refresh' => true,
+ 'not_editable' => true,
+ )));
+ }
+
+ /**
+ * Show a task
+ *
+ * @access public
+ */
+ public function show()
+ {
+ $task = $this->getTask();
+ $subtasks = $this->subtaskModel->getAll($task['id']);
+
+ $values = array(
+ 'id' => $task['id'],
+ 'date_started' => $task['date_started'],
+ 'time_estimated' => $task['time_estimated'] ?: '',
+ 'time_spent' => $task['time_spent'] ?: '',
+ );
+
+ $values = $this->dateParser->format($values, array('date_started'), $this->configModel->get('application_datetime_format', DateParser::DATE_TIME_FORMAT));
+
+ $this->response->html($this->helper->layout->task('task/show', array(
+ 'task' => $task,
+ 'project' => $this->projectModel->getById($task['project_id']),
+ 'values' => $values,
+ 'files' => $this->taskFileModel->getAllDocuments($task['id']),
+ 'images' => $this->taskFileModel->getAllImages($task['id']),
+ 'comments' => $this->commentModel->getAll($task['id'], $this->userSession->getCommentSorting()),
+ 'subtasks' => $subtasks,
+ 'internal_links' => $this->taskLinkModel->getAllGroupedByLabel($task['id']),
+ 'external_links' => $this->taskExternalLinkModel->getAll($task['id']),
+ 'link_label_list' => $this->linkModel->getList(0, false),
+ )));
+ }
+
+ /**
+ * Display task analytics
+ *
+ * @access public
+ */
+ public function analytics()
+ {
+ $task = $this->getTask();
+
+ $this->response->html($this->helper->layout->task('task/analytics', array(
+ 'task' => $task,
+ 'project' => $this->projectModel->getById($task['project_id']),
+ 'lead_time' => $this->taskAnalyticModel->getLeadTime($task),
+ 'cycle_time' => $this->taskAnalyticModel->getCycleTime($task),
+ 'time_spent_columns' => $this->taskAnalyticModel->getTimeSpentByColumn($task),
+ )));
+ }
+
+ /**
+ * Display the time tracking details
+ *
+ * @access public
+ */
+ public function timetracking()
+ {
+ $task = $this->getTask();
+
+ $subtask_paginator = $this->paginator
+ ->setUrl('TaskViewController', 'timetracking', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'pagination' => 'subtasks'))
+ ->setMax(15)
+ ->setOrder('start')
+ ->setDirection('DESC')
+ ->setQuery($this->subtaskTimeTrackingModel->getTaskQuery($task['id']))
+ ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
+
+ $this->response->html($this->helper->layout->task('task/time_tracking_details', array(
+ 'task' => $task,
+ 'project' => $this->projectModel->getById($task['project_id']),
+ 'subtask_paginator' => $subtask_paginator,
+ )));
+ }
+
+ /**
+ * Display the task transitions
+ *
+ * @access public
+ */
+ public function transitions()
+ {
+ $task = $this->getTask();
+
+ $this->response->html($this->helper->layout->task('task/transitions', array(
+ 'task' => $task,
+ 'project' => $this->projectModel->getById($task['project_id']),
+ 'transitions' => $this->transitionModel->getAllByTask($task['id']),
+ )));
+ }
+}
diff --git a/app/Controller/Twofactor.php b/app/Controller/TwoFactorController.php
index 10292261..d02c8950 100644
--- a/app/Controller/Twofactor.php
+++ b/app/Controller/TwoFactorController.php
@@ -2,23 +2,27 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\AccessForbiddenException;
+
/**
* Two Factor Auth controller
*
- * @package controller
+ * @package Kanboard/Controller
* @author Frederic Guillot
*/
-class Twofactor extends User
+class TwoFactorController extends UserViewController
{
/**
* Only the current user can access to 2FA settings
*
* @access private
+ * @param array $user
+ * @throws AccessForbiddenException
*/
private function checkCurrentUser(array $user)
{
if ($user['id'] != $this->userSession->getId()) {
- $this->forbidden();
+ throw new AccessForbiddenException();
}
}
@@ -87,7 +91,7 @@ class Twofactor extends User
if ($provider->authenticate()) {
$this->flash->success(t('The two factor authentication code is valid.'));
- $this->user->update(array(
+ $this->userModel->update(array(
'id' => $user['id'],
'twofactor_activated' => 1,
'twofactor_secret' => $this->authenticationManager->getPostAuthenticationProvider()->getSecret(),
@@ -96,10 +100,10 @@ class Twofactor extends User
unset($this->sessionStorage->twoFactorSecret);
$this->userSession->disablePostAuthentication();
- $this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id'])));
+ $this->response->redirect($this->helper->url->to('TwoFactorController', 'index', array('user_id' => $user['id'])));
} else {
$this->flash->failure(t('The two factor authentication code is not valid.'));
- $this->response->redirect($this->helper->url->to('twofactor', 'show', array('user_id' => $user['id'])));
+ $this->response->redirect($this->helper->url->to('TwoFactorController', 'show', array('user_id' => $user['id'])));
}
}
@@ -113,7 +117,7 @@ class Twofactor extends User
$user = $this->getUser();
$this->checkCurrentUser($user);
- $this->user->update(array(
+ $this->userModel->update(array(
'id' => $user['id'],
'twofactor_activated' => 0,
'twofactor_secret' => '',
@@ -123,7 +127,7 @@ class Twofactor extends User
$this->userSession->disablePostAuthentication();
$this->flash->success(t('User updated successfully.'));
- $this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id'])));
+ $this->response->redirect($this->helper->url->to('TwoFactorController', 'index', array('user_id' => $user['id'])));
}
/**
@@ -145,10 +149,10 @@ class Twofactor extends User
if ($provider->authenticate()) {
$this->userSession->validatePostAuthentication();
$this->flash->success(t('The two factor authentication code is valid.'));
- $this->response->redirect($this->helper->url->to('app', 'index'));
+ $this->response->redirect($this->helper->url->to('DashboardController', 'show'));
} else {
$this->flash->failure(t('The two factor authentication code is not valid.'));
- $this->response->redirect($this->helper->url->to('twofactor', 'code'));
+ $this->response->redirect($this->helper->url->to('TwoFactorController', 'code'));
}
}
@@ -182,16 +186,16 @@ class Twofactor extends User
if ($this->request->getStringParam('disable') === 'yes') {
$this->checkCSRFParam();
- $this->user->update(array(
+ $this->userModel->update(array(
'id' => $user['id'],
'twofactor_activated' => 0,
'twofactor_secret' => '',
));
- $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
+ return $this->response->redirect($this->helper->url->to('UserViewController', 'show', array('user_id' => $user['id'])));
}
- $this->response->html($this->helper->layout->user('twofactor/disable', array(
+ return $this->response->html($this->helper->layout->user('twofactor/disable', array(
'user' => $user,
)));
}
diff --git a/app/Controller/User.php b/app/Controller/User.php
deleted file mode 100644
index f7d7d2e0..00000000
--- a/app/Controller/User.php
+++ /dev/null
@@ -1,408 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-use Kanboard\Notification\Mail as MailNotification;
-use Kanboard\Model\Project as ProjectModel;
-use Kanboard\Core\Security\Role;
-
-/**
- * User controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-class User extends Base
-{
- /**
- * List all users
- *
- * @access public
- */
- public function index()
- {
- $paginator = $this->paginator
- ->setUrl('user', 'index')
- ->setMax(30)
- ->setOrder('username')
- ->setQuery($this->user->getQuery())
- ->calculate();
-
- $this->response->html(
- $this->helper->layout->app('user/index', array(
- 'title' => t('Users').' ('.$paginator->getTotal().')',
- 'paginator' => $paginator,
- )
- ));
- }
-
- /**
- * Public user profile
- *
- * @access public
- */
- public function profile()
- {
- $user = $this->user->getById($this->request->getIntegerParam('user_id'));
-
- if (empty($user)) {
- $this->notfound();
- }
-
- $this->response->html(
- $this->helper->layout->app('user/profile', array(
- 'title' => $user['name'] ?: $user['username'],
- 'user' => $user,
- )
- ));
- }
-
- /**
- * Display a form to create a new user
- *
- * @access public
- */
- public function create(array $values = array(), array $errors = array())
- {
- $is_remote = $this->request->getIntegerParam('remote') == 1 || (isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1);
-
- $this->response->html($this->helper->layout->app($is_remote ? 'user/create_remote' : 'user/create_local', array(
- 'timezones' => $this->config->getTimezones(true),
- 'languages' => $this->config->getLanguages(true),
- 'roles' => $this->role->getApplicationRoles(),
- 'projects' => $this->project->getList(),
- 'errors' => $errors,
- 'values' => $values + array('role' => Role::APP_USER),
- 'title' => t('New user')
- )));
- }
-
- /**
- * Validate and save a new user
- *
- * @access public
- */
- public function save()
- {
- $values = $this->request->getValues();
- list($valid, $errors) = $this->userValidator->validateCreation($values);
-
- if ($valid) {
- $project_id = empty($values['project_id']) ? 0 : $values['project_id'];
- unset($values['project_id']);
-
- $user_id = $this->user->create($values);
-
- if ($user_id !== false) {
- $this->projectUserRole->addUser($project_id, $user_id, Role::PROJECT_MEMBER);
-
- if (! empty($values['notifications_enabled'])) {
- $this->userNotificationType->saveSelectedTypes($user_id, array(MailNotification::TYPE));
- }
-
- $this->flash->success(t('User created successfully.'));
- $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user_id)));
- } else {
- $this->flash->failure(t('Unable to create your user.'));
- $values['project_id'] = $project_id;
- }
- }
-
- $this->create($values, $errors);
- }
-
- /**
- * Display user information
- *
- * @access public
- */
- public function show()
- {
- $user = $this->getUser();
- $this->response->html($this->helper->layout->user('user/show', array(
- 'user' => $user,
- 'timezones' => $this->config->getTimezones(true),
- 'languages' => $this->config->getLanguages(true),
- )));
- }
-
- /**
- * Display timesheet
- *
- * @access public
- */
- public function timesheet()
- {
- $user = $this->getUser();
-
- $subtask_paginator = $this->paginator
- ->setUrl('user', 'timesheet', array('user_id' => $user['id'], 'pagination' => 'subtasks'))
- ->setMax(20)
- ->setOrder('start')
- ->setDirection('DESC')
- ->setQuery($this->subtaskTimeTracking->getUserQuery($user['id']))
- ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
-
- $this->response->html($this->helper->layout->user('user/timesheet', array(
- 'subtask_paginator' => $subtask_paginator,
- 'user' => $user,
- )));
- }
-
- /**
- * Display last password reset
- *
- * @access public
- */
- public function passwordReset()
- {
- $user = $this->getUser();
- $this->response->html($this->helper->layout->user('user/password_reset', array(
- 'tokens' => $this->passwordReset->getAll($user['id']),
- 'user' => $user,
- )));
- }
-
- /**
- * Display last connections
- *
- * @access public
- */
- public function last()
- {
- $user = $this->getUser();
- $this->response->html($this->helper->layout->user('user/last', array(
- 'last_logins' => $this->lastLogin->getAll($user['id']),
- 'user' => $user,
- )));
- }
-
- /**
- * Display user sessions
- *
- * @access public
- */
- public function sessions()
- {
- $user = $this->getUser();
- $this->response->html($this->helper->layout->user('user/sessions', array(
- 'sessions' => $this->rememberMeSession->getAll($user['id']),
- 'user' => $user,
- )));
- }
-
- /**
- * Remove a "RememberMe" token
- *
- * @access public
- */
- public function removeSession()
- {
- $this->checkCSRFParam();
- $user = $this->getUser();
- $this->rememberMeSession->remove($this->request->getIntegerParam('id'));
- $this->response->redirect($this->helper->url->to('user', 'sessions', array('user_id' => $user['id'])));
- }
-
- /**
- * Display user notifications
- *
- * @access public
- */
- public function notifications()
- {
- $user = $this->getUser();
-
- if ($this->request->isPost()) {
- $values = $this->request->getValues();
- $this->userNotification->saveSettings($user['id'], $values);
- $this->flash->success(t('User updated successfully.'));
- $this->response->redirect($this->helper->url->to('user', 'notifications', array('user_id' => $user['id'])));
- }
-
- $this->response->html($this->helper->layout->user('user/notifications', array(
- 'projects' => $this->projectUserRole->getProjectsByUser($user['id'], array(ProjectModel::ACTIVE)),
- 'notifications' => $this->userNotification->readSettings($user['id']),
- 'types' => $this->userNotificationType->getTypes(),
- 'filters' => $this->userNotificationFilter->getFilters(),
- 'user' => $user,
- )));
- }
-
- /**
- * Display user integrations
- *
- * @access public
- */
- public function integrations()
- {
- $user = $this->getUser();
-
- if ($this->request->isPost()) {
- $values = $this->request->getValues();
- $this->userMetadata->save($user['id'], $values);
- $this->flash->success(t('User updated successfully.'));
- $this->response->redirect($this->helper->url->to('user', 'integrations', array('user_id' => $user['id'])));
- }
-
- $this->response->html($this->helper->layout->user('user/integrations', array(
- 'user' => $user,
- 'values' => $this->userMetadata->getall($user['id']),
- )));
- }
-
- /**
- * Display external accounts
- *
- * @access public
- */
- public function external()
- {
- $user = $this->getUser();
- $this->response->html($this->helper->layout->user('user/external', array(
- 'last_logins' => $this->lastLogin->getAll($user['id']),
- 'user' => $user,
- )));
- }
-
- /**
- * Public access management
- *
- * @access public
- */
- public function share()
- {
- $user = $this->getUser();
- $switch = $this->request->getStringParam('switch');
-
- if ($switch === 'enable' || $switch === 'disable') {
- $this->checkCSRFParam();
-
- if ($this->user->{$switch.'PublicAccess'}($user['id'])) {
- $this->flash->success(t('User updated successfully.'));
- } else {
- $this->flash->failure(t('Unable to update this user.'));
- }
-
- $this->response->redirect($this->helper->url->to('user', 'share', array('user_id' => $user['id'])));
- }
-
- $this->response->html($this->helper->layout->user('user/share', array(
- 'user' => $user,
- 'title' => t('Public access'),
- )));
- }
-
- /**
- * Password modification
- *
- * @access public
- */
- public function password()
- {
- $user = $this->getUser();
- $values = array('id' => $user['id']);
- $errors = array();
-
- if ($this->request->isPost()) {
- $values = $this->request->getValues();
- list($valid, $errors) = $this->userValidator->validatePasswordModification($values);
-
- if ($valid) {
- if ($this->user->update($values)) {
- $this->flash->success(t('Password modified successfully.'));
- } else {
- $this->flash->failure(t('Unable to change the password.'));
- }
-
- $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
- }
- }
-
- $this->response->html($this->helper->layout->user('user/password', array(
- 'values' => $values,
- 'errors' => $errors,
- 'user' => $user,
- )));
- }
-
- /**
- * Display a form to edit a user
- *
- * @access public
- */
- public function edit()
- {
- $user = $this->getUser();
- $values = $user;
- $errors = array();
-
- unset($values['password']);
-
- if ($this->request->isPost()) {
- $values = $this->request->getValues();
-
- if (! $this->userSession->isAdmin()) {
- if (isset($values['role'])) {
- unset($values['role']);
- }
- }
-
- list($valid, $errors) = $this->userValidator->validateModification($values);
-
- if ($valid) {
- if ($this->user->update($values)) {
- $this->flash->success(t('User updated successfully.'));
- } else {
- $this->flash->failure(t('Unable to update your user.'));
- }
-
- $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
- }
- }
-
- $this->response->html($this->helper->layout->user('user/edit', array(
- 'values' => $values,
- 'errors' => $errors,
- 'user' => $user,
- 'timezones' => $this->config->getTimezones(true),
- 'languages' => $this->config->getLanguages(true),
- 'roles' => $this->role->getApplicationRoles(),
- )));
- }
-
- /**
- * Display a form to edit authentication
- *
- * @access public
- */
- public function authentication()
- {
- $user = $this->getUser();
- $values = $user;
- $errors = array();
-
- unset($values['password']);
-
- if ($this->request->isPost()) {
- $values = $this->request->getValues() + array('disable_login_form' => 0, 'is_ldap_user' => 0);
- list($valid, $errors) = $this->userValidator->validateModification($values);
-
- if ($valid) {
- if ($this->user->update($values)) {
- $this->flash->success(t('User updated successfully.'));
- } else {
- $this->flash->failure(t('Unable to update your user.'));
- }
-
- $this->response->redirect($this->helper->url->to('user', 'authentication', array('user_id' => $user['id'])));
- }
- }
-
- $this->response->html($this->helper->layout->user('user/authentication', array(
- 'values' => $values,
- 'errors' => $errors,
- 'user' => $user,
- )));
- }
-}
diff --git a/app/Controller/UserHelper.php b/app/Controller/UserAjaxController.php
index 47bbe554..ed180471 100644
--- a/app/Controller/UserHelper.php
+++ b/app/Controller/UserAjaxController.php
@@ -4,15 +4,15 @@ namespace Kanboard\Controller;
use Kanboard\Filter\UserNameFilter;
use Kanboard\Formatter\UserAutoCompleteFormatter;
-use Kanboard\Model\User as UserModel;
+use Kanboard\Model\UserModel;
/**
- * User Helper
+ * User Ajax Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class UserHelper extends Base
+class UserAjaxController extends BaseController
{
/**
* User auto-completion (Ajax)
@@ -36,7 +36,17 @@ class UserHelper extends Base
{
$project_id = $this->request->getStringParam('project_id');
$query = $this->request->getStringParam('q');
- $users = $this->projectPermission->findUsernames($project_id, $query);
+ $users = $this->projectPermissionModel->findUsernames($project_id, $query);
$this->response->json($users);
}
+
+ /**
+ * Check if the user is connected
+ *
+ * @access public
+ */
+ public function status()
+ {
+ $this->response->text('OK');
+ }
}
diff --git a/app/Controller/UserCreationController.php b/app/Controller/UserCreationController.php
new file mode 100644
index 00000000..9c873f85
--- /dev/null
+++ b/app/Controller/UserCreationController.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Security\Role;
+use Kanboard\Notification\MailNotification;
+
+/**
+ * Class UserCreationController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class UserCreationController extends BaseController
+{
+ /**
+ * Display a form to create a new user
+ *
+ * @access public
+ * @param array $values
+ * @param array $errors
+ */
+ public function show(array $values = array(), array $errors = array())
+ {
+ $isRemote = $this->request->getIntegerParam('remote') == 1 || (isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1);
+ $template = $isRemote ? 'user_creation/remote' : 'user_creation/local';
+
+ $this->response->html($this->template->render($template, array(
+ 'timezones' => $this->timezoneModel->getTimezones(true),
+ 'languages' => $this->languageModel->getLanguages(true),
+ 'roles' => $this->role->getApplicationRoles(),
+ 'projects' => $this->projectModel->getList(),
+ 'errors' => $errors,
+ 'values' => $values + array('role' => Role::APP_USER),
+ )));
+ }
+
+ /**
+ * Validate and save a new user
+ *
+ * @access public
+ */
+ public function save()
+ {
+ $values = $this->request->getValues();
+ list($valid, $errors) = $this->userValidator->validateCreation($values);
+
+ if ($valid) {
+ $this->createUser($values);
+ } else {
+ $this->show($values, $errors);
+ }
+ }
+
+ /**
+ * Create user
+ *
+ * @param array $values
+ */
+ private function createUser(array $values)
+ {
+ $project_id = empty($values['project_id']) ? 0 : $values['project_id'];
+ unset($values['project_id']);
+
+ $user_id = $this->userModel->create($values);
+
+ if ($user_id !== false) {
+ if ($project_id !== 0) {
+ $this->projectUserRoleModel->addUser($project_id, $user_id, Role::PROJECT_MEMBER);
+ }
+
+ if (! empty($values['notifications_enabled'])) {
+ $this->userNotificationTypeModel->saveSelectedTypes($user_id, array(MailNotification::TYPE));
+ }
+
+ $this->flash->success(t('User created successfully.'));
+ $this->response->redirect($this->helper->url->to('UserViewController', 'show', array('user_id' => $user_id)));
+ } else {
+ $this->flash->failure(t('Unable to create your user.'));
+ $this->response->redirect($this->helper->url->to('UserListController', 'show'));
+ }
+ }
+}
diff --git a/app/Controller/UserCredentialController.php b/app/Controller/UserCredentialController.php
new file mode 100644
index 00000000..4021dc37
--- /dev/null
+++ b/app/Controller/UserCredentialController.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class UserCredentialController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class UserCredentialController extends BaseController
+{
+ /**
+ * Password modification form
+ *
+ * @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function changePassword(array $values = array(), array $errors = array())
+ {
+ $user = $this->getUser();
+
+ return $this->response->html($this->helper->layout->user('user_credential/password', array(
+ 'values' => $values + array('id' => $user['id']),
+ 'errors' => $errors,
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Save new password
+ *
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function savePassword()
+ {
+ $user = $this->getUser();
+ $values = $this->request->getValues();
+
+ list($valid, $errors) = $this->userValidator->validatePasswordModification($values);
+
+ if ($valid) {
+ if ($this->userModel->update($values)) {
+ $this->flash->success(t('Password modified successfully.'));
+ $this->userLockingModel->resetFailedLogin($user['username']);
+ } else {
+ $this->flash->failure(t('Unable to change the password.'));
+ }
+
+ return $this->response->redirect($this->helper->url->to('UserViewController', 'show', array('user_id' => $user['id'])));
+ }
+
+ return $this->changePassword($values, $errors);
+ }
+
+ /**
+ * Display a form to edit authentication
+ *
+ * @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function changeAuthentication(array $values = array(), array $errors = array())
+ {
+ $user = $this->getUser();
+
+ if (empty($values)) {
+ $values = $user;
+ unset($values['password']);
+ }
+
+ return $this->response->html($this->helper->layout->user('user_credential/authentication', array(
+ 'values' => $values,
+ 'errors' => $errors,
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Save authentication
+ *
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function saveAuthentication()
+ {
+ $user = $this->getUser();
+ $values = $this->request->getValues() + array('disable_login_form' => 0, 'is_ldap_user' => 0);
+ list($valid, $errors) = $this->userValidator->validateModification($values);
+
+ if ($valid) {
+ if ($this->userModel->update($values)) {
+ $this->flash->success(t('User updated successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to update your user.'));
+ }
+
+ return $this->response->redirect($this->helper->url->to('UserCredentialController', 'changeAuthentication', array('user_id' => $user['id'])));
+ }
+
+ return $this->changeAuthentication($values, $errors);
+ }
+}
diff --git a/app/Controller/UserImport.php b/app/Controller/UserImportController.php
index debd69e5..fec9a31d 100644
--- a/app/Controller/UserImport.php
+++ b/app/Controller/UserImportController.php
@@ -7,51 +7,43 @@ use Kanboard\Core\Csv;
/**
* User Import controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class UserImport extends Base
+class UserImportController extends BaseController
{
/**
* Upload the file and ask settings
*
+ * @param array $values
+ * @param array $errors
*/
- public function step1(array $values = array(), array $errors = array())
+ public function show(array $values = array(), array $errors = array())
{
- $this->response->html($this->helper->layout->app('user_import/step1', array(
+ $this->response->html($this->template->render('user_import/show', array(
'values' => $values,
'errors' => $errors,
'max_size' => ini_get('upload_max_filesize'),
'delimiters' => Csv::getDelimiters(),
'enclosures' => Csv::getEnclosures(),
- 'title' => t('Import users from CSV file'),
)));
}
/**
- * Process CSV file
- *
+ * Submit form
*/
- public function step2()
+ public function save()
{
$values = $this->request->getValues();
$filename = $this->request->getFilePath('file');
if (! file_exists($filename)) {
- $this->step1($values, array('file' => array(t('Unable to read your file'))));
- }
-
- $csv = new Csv($values['delimiter'], $values['enclosure']);
- $csv->setColumnMapping($this->userImport->getColumnMapping());
- $csv->read($filename, array($this->userImport, 'import'));
-
- if ($this->userImport->counter > 0) {
- $this->flash->success(t('%d user(s) have been imported successfully.', $this->userImport->counter));
+ $this->flash->failure(t('Unable to read your file'));
} else {
- $this->flash->failure(t('Nothing have been imported!'));
+ $this->importFile($values, $filename);
}
- $this->response->redirect($this->helper->url->to('userImport', 'step1'));
+ $this->response->redirect($this->helper->url->to('UserListController', 'show'));
}
/**
@@ -60,7 +52,26 @@ class UserImport extends Base
*/
public function template()
{
- $this->response->forceDownload('users.csv');
+ $this->response->withFileDownload('users.csv');
$this->response->csv(array($this->userImport->getColumnMapping()));
}
+
+ /**
+ * Process file
+ *
+ * @param array $values
+ * @param $filename
+ */
+ private function importFile(array $values, $filename)
+ {
+ $csv = new Csv($values['delimiter'], $values['enclosure']);
+ $csv->setColumnMapping($this->userImport->getColumnMapping());
+ $csv->read($filename, array($this->userImport, 'import'));
+
+ if ($this->userImport->counter > 0) {
+ $this->flash->success(t('%d user(s) have been imported successfully.', $this->userImport->counter));
+ } else {
+ $this->flash->failure(t('Nothing have been imported!'));
+ }
+ }
}
diff --git a/app/Controller/UserListController.php b/app/Controller/UserListController.php
new file mode 100644
index 00000000..31fcdd44
--- /dev/null
+++ b/app/Controller/UserListController.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class User List Controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class UserListController extends BaseController
+{
+ /**
+ * List all users
+ *
+ * @access public
+ */
+ public function show()
+ {
+ $paginator = $this->paginator
+ ->setUrl('UserListController', 'show')
+ ->setMax(30)
+ ->setOrder('username')
+ ->setQuery($this->userModel->getQuery())
+ ->calculate();
+
+ $this->response->html($this->helper->layout->app('user_list/show', array(
+ 'title' => t('Users').' ('.$paginator->getTotal().')',
+ 'paginator' => $paginator,
+ )));
+ }
+}
diff --git a/app/Controller/UserModificationController.php b/app/Controller/UserModificationController.php
new file mode 100644
index 00000000..d339fd9a
--- /dev/null
+++ b/app/Controller/UserModificationController.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Class UserModificationController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class UserModificationController extends BaseController
+{
+ /**
+ * Display a form to edit user information
+ *
+ * @access public
+ * @param array $values
+ * @param array $errors
+ * @throws \Kanboard\Core\Controller\AccessForbiddenException
+ * @throws \Kanboard\Core\Controller\PageNotFoundException
+ */
+ public function show(array $values = array(), array $errors = array())
+ {
+ $user = $this->getUser();
+
+ if (empty($values)) {
+ $values = $user;
+ unset($values['password']);
+ }
+
+ return $this->response->html($this->helper->layout->user('user_modification/show', array(
+ 'values' => $values,
+ 'errors' => $errors,
+ 'user' => $user,
+ 'timezones' => $this->timezoneModel->getTimezones(true),
+ 'languages' => $this->languageModel->getLanguages(true),
+ 'roles' => $this->role->getApplicationRoles(),
+ )));
+ }
+
+ /**
+ * Save user information
+ */
+ public function save()
+ {
+ $user = $this->getUser();
+ $values = $this->request->getValues();
+
+ if (! $this->userSession->isAdmin()) {
+ if (isset($values['role'])) {
+ unset($values['role']);
+ }
+ }
+
+ list($valid, $errors) = $this->userValidator->validateModification($values);
+
+ if ($valid) {
+ if ($this->userModel->update($values)) {
+ $this->flash->success(t('User updated successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to update your user.'));
+ }
+
+ return $this->response->redirect($this->helper->url->to('UserViewController', 'show', array('user_id' => $user['id'])));
+ }
+
+ return $this->show($values, $errors);
+ }
+}
diff --git a/app/Controller/UserStatus.php b/app/Controller/UserStatusController.php
index b8ee5c91..070fb6fc 100644
--- a/app/Controller/UserStatus.php
+++ b/app/Controller/UserStatusController.php
@@ -5,10 +5,10 @@ namespace Kanboard\Controller;
/**
* User Status Controller
*
- * @package controller
+ * @package Kanboard\Controller
* @author Frederic Guillot
*/
-class UserStatus extends Base
+class UserStatusController extends BaseController
{
/**
* Confirm remove a user
@@ -34,13 +34,13 @@ class UserStatus extends Base
$user = $this->getUser();
$this->checkCSRFParam();
- if ($this->user->remove($user['id'])) {
+ if ($this->userModel->remove($user['id'])) {
$this->flash->success(t('User removed successfully.'));
} else {
$this->flash->failure(t('Unable to remove this user.'));
}
- $this->response->redirect($this->helper->url->to('user', 'index'));
+ $this->response->redirect($this->helper->url->to('UserListController', 'show'));
}
/**
@@ -67,13 +67,13 @@ class UserStatus extends Base
$user = $this->getUser();
$this->checkCSRFParam();
- if ($this->user->enable($user['id'])) {
+ if ($this->userModel->enable($user['id'])) {
$this->flash->success(t('User activated successfully.'));
} else {
$this->flash->failure(t('Unable to enable this user.'));
}
- $this->response->redirect($this->helper->url->to('user', 'index'));
+ $this->response->redirect($this->helper->url->to('UserListController', 'show'));
}
/**
@@ -100,12 +100,12 @@ class UserStatus extends Base
$user = $this->getUser();
$this->checkCSRFParam();
- if ($this->user->disable($user['id'])) {
+ if ($this->userModel->disable($user['id'])) {
$this->flash->success(t('User disabled successfully.'));
} else {
$this->flash->failure(t('Unable to disable this user.'));
}
- $this->response->redirect($this->helper->url->to('user', 'index'));
+ $this->response->redirect($this->helper->url->to('UserListController', 'show'));
}
}
diff --git a/app/Controller/UserViewController.php b/app/Controller/UserViewController.php
new file mode 100644
index 00000000..a73c5c51
--- /dev/null
+++ b/app/Controller/UserViewController.php
@@ -0,0 +1,217 @@
+<?php
+
+namespace Kanboard\Controller;
+
+use Kanboard\Core\Controller\PageNotFoundException;
+use Kanboard\Model\ProjectModel;
+
+/**
+ * Class UserViewController
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class UserViewController extends BaseController
+{
+ /**
+ * Public user profile
+ *
+ * @access public
+ * @throws PageNotFoundException
+ */
+ public function profile()
+ {
+ $user = $this->userModel->getById($this->request->getIntegerParam('user_id'));
+
+ if (empty($user)) {
+ throw new PageNotFoundException();
+ }
+
+ $this->response->html($this->helper->layout->app('user_view/profile', array(
+ 'title' => $user['name'] ?: $user['username'],
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Display user information
+ *
+ * @access public
+ */
+ public function show()
+ {
+ $user = $this->getUser();
+ $this->response->html($this->helper->layout->user('user_view/show', array(
+ 'user' => $user,
+ 'timezones' => $this->timezoneModel->getTimezones(true),
+ 'languages' => $this->languageModel->getLanguages(true),
+ )));
+ }
+
+ /**
+ * Display timesheet
+ *
+ * @access public
+ */
+ public function timesheet()
+ {
+ $user = $this->getUser();
+
+ $subtask_paginator = $this->paginator
+ ->setUrl('UserViewController', 'timesheet', array('user_id' => $user['id'], 'pagination' => 'subtasks'))
+ ->setMax(20)
+ ->setOrder('start')
+ ->setDirection('DESC')
+ ->setQuery($this->subtaskTimeTrackingModel->getUserQuery($user['id']))
+ ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
+
+ $this->response->html($this->helper->layout->user('user_view/timesheet', array(
+ 'subtask_paginator' => $subtask_paginator,
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Display last password reset
+ *
+ * @access public
+ */
+ public function passwordReset()
+ {
+ $user = $this->getUser();
+ $this->response->html($this->helper->layout->user('user_view/password_reset', array(
+ 'tokens' => $this->passwordResetModel->getAll($user['id']),
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Display last connections
+ *
+ * @access public
+ */
+ public function lastLogin()
+ {
+ $user = $this->getUser();
+ $this->response->html($this->helper->layout->user('user_view/last', array(
+ 'last_logins' => $this->lastLoginModel->getAll($user['id']),
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Display user sessions
+ *
+ * @access public
+ */
+ public function sessions()
+ {
+ $user = $this->getUser();
+ $this->response->html($this->helper->layout->user('user_view/sessions', array(
+ 'sessions' => $this->rememberMeSessionModel->getAll($user['id']),
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Remove a "RememberMe" token
+ *
+ * @access public
+ */
+ public function removeSession()
+ {
+ $this->checkCSRFParam();
+ $user = $this->getUser();
+ $this->rememberMeSessionModel->remove($this->request->getIntegerParam('id'));
+ $this->response->redirect($this->helper->url->to('UserViewController', 'sessions', array('user_id' => $user['id'])));
+ }
+
+ /**
+ * Display user notifications
+ *
+ * @access public
+ */
+ public function notifications()
+ {
+ $user = $this->getUser();
+
+ if ($this->request->isPost()) {
+ $values = $this->request->getValues();
+ $this->userNotificationModel->saveSettings($user['id'], $values);
+ $this->flash->success(t('User updated successfully.'));
+ return $this->response->redirect($this->helper->url->to('UserViewController', 'notifications', array('user_id' => $user['id'])));
+ }
+
+ return $this->response->html($this->helper->layout->user('user_view/notifications', array(
+ 'projects' => $this->projectUserRoleModel->getProjectsByUser($user['id'], array(ProjectModel::ACTIVE)),
+ 'notifications' => $this->userNotificationModel->readSettings($user['id']),
+ 'types' => $this->userNotificationTypeModel->getTypes(),
+ 'filters' => $this->userNotificationFilterModel->getFilters(),
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Display user integrations
+ *
+ * @access public
+ */
+ public function integrations()
+ {
+ $user = $this->getUser();
+
+ if ($this->request->isPost()) {
+ $values = $this->request->getValues();
+ $this->userMetadataModel->save($user['id'], $values);
+ $this->flash->success(t('User updated successfully.'));
+ $this->response->redirect($this->helper->url->to('UserViewController', 'integrations', array('user_id' => $user['id'])));
+ }
+
+ $this->response->html($this->helper->layout->user('user_view/integrations', array(
+ 'user' => $user,
+ 'values' => $this->userMetadataModel->getAll($user['id']),
+ )));
+ }
+
+ /**
+ * Display external accounts
+ *
+ * @access public
+ */
+ public function external()
+ {
+ $user = $this->getUser();
+ $this->response->html($this->helper->layout->user('user_view/external', array(
+ 'last_logins' => $this->lastLoginModel->getAll($user['id']),
+ 'user' => $user,
+ )));
+ }
+
+ /**
+ * Public access management
+ *
+ * @access public
+ */
+ public function share()
+ {
+ $user = $this->getUser();
+ $switch = $this->request->getStringParam('switch');
+
+ if ($switch === 'enable' || $switch === 'disable') {
+ $this->checkCSRFParam();
+
+ if ($this->userModel->{$switch . 'PublicAccess'}($user['id'])) {
+ $this->flash->success(t('User updated successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to update this user.'));
+ }
+
+ return $this->response->redirect($this->helper->url->to('UserViewController', 'share', array('user_id' => $user['id'])));
+ }
+
+ return $this->response->html($this->helper->layout->user('user_view/share', array(
+ 'user' => $user,
+ 'title' => t('Public access'),
+ )));
+ }
+}
diff --git a/app/Controller/WebNotification.php b/app/Controller/WebNotification.php
deleted file mode 100644
index dca5cb46..00000000
--- a/app/Controller/WebNotification.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-/**
- * Web notification controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-class WebNotification extends Base
-{
- /**
- * Mark all notifications as read
- *
- * @access public
- */
- public function flush()
- {
- $user_id = $this->getUserId();
-
- $this->userUnreadNotification->markAllAsRead($user_id);
- $this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id)));
- }
-
- /**
- * Mark a notification as read
- *
- * @access public
- */
- public function remove()
- {
- $user_id = $this->getUserId();
- $notification_id = $this->request->getIntegerParam('notification_id');
-
- $this->userUnreadNotification->markAsRead($user_id, $notification_id);
- $this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id)));
- }
-
- private function getUserId()
- {
- $user_id = $this->request->getIntegerParam('user_id');
-
- if (! $this->userSession->isAdmin() && $user_id != $this->userSession->getId()) {
- $user_id = $this->userSession->getId();
- }
-
- return $user_id;
- }
-}
diff --git a/app/Controller/WebNotificationController.php b/app/Controller/WebNotificationController.php
new file mode 100644
index 00000000..46a42063
--- /dev/null
+++ b/app/Controller/WebNotificationController.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Kanboard\Controller;
+
+/**
+ * Web notification controller
+ *
+ * @package Kanboard\Controller
+ * @author Frederic Guillot
+ */
+class WebNotificationController extends BaseController
+{
+ /**
+ * Mark all notifications as read
+ *
+ * @access public
+ */
+ public function flush()
+ {
+ $user_id = $this->getUserId();
+
+ $this->userUnreadNotificationModel->markAllAsRead($user_id);
+ $this->response->redirect($this->helper->url->to('DashboardController', 'notifications', array('user_id' => $user_id)));
+ }
+
+ /**
+ * Mark a notification as read
+ *
+ * @access public
+ */
+ public function remove()
+ {
+ $user_id = $this->getUserId();
+ $notification_id = $this->request->getIntegerParam('notification_id');
+
+ $this->userUnreadNotificationModel->markAsRead($user_id, $notification_id);
+ $this->response->redirect($this->helper->url->to('DashboardController', 'notifications', array('user_id' => $user_id)));
+ }
+
+ /**
+ * Redirect to the task and mark notification as read
+ */
+ public function redirect()
+ {
+ $user_id = $this->getUserId();
+ $notification_id = $this->request->getIntegerParam('notification_id');
+
+ $notification = $this->userUnreadNotificationModel->getById($notification_id);
+ $this->userUnreadNotificationModel->markAsRead($user_id, $notification_id);
+
+ if (empty($notification)) {
+ $this->response->redirect($this->helper->url->to('DashboardController', 'notifications', array('user_id' => $user_id)));
+ } elseif ($this->helper->text->contains($notification['event_name'], 'comment')) {
+ $this->response->redirect($this->helper->url->to(
+ 'TaskViewController',
+ 'show',
+ array('task_id' => $notification['event_data']['task']['id'], 'project_id' => $notification['event_data']['task']['project_id']),
+ 'comment-'.$notification['event_data']['comment']['id']
+ ));
+ } else {
+ $this->response->redirect($this->helper->url->to(
+ 'TaskViewController',
+ 'show',
+ array('task_id' => $notification['event_data']['task']['id'], 'project_id' => $notification['event_data']['task']['project_id'])
+ ));
+ }
+ }
+
+ private function getUserId()
+ {
+ $user_id = $this->request->getIntegerParam('user_id');
+
+ if (! $this->userSession->isAdmin() && $user_id != $this->userSession->getId()) {
+ $user_id = $this->userSession->getId();
+ }
+
+ return $user_id;
+ }
+}
diff --git a/app/Controller/Webhook.php b/app/Controller/Webhook.php
deleted file mode 100644
index 0eafe3e5..00000000
--- a/app/Controller/Webhook.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-namespace Kanboard\Controller;
-
-/**
- * Webhook controller
- *
- * @package controller
- * @author Frederic Guillot
- */
-class Webhook extends Base
-{
- /**
- * Webhook to create a task
- *
- * @access public
- */
- public function task()
- {
- $this->checkWebhookToken();
-
- $defaultProject = $this->project->getFirst();
-
- $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', $defaultProject['id']),
- 'owner_id' => $this->request->getIntegerParam('owner_id'),
- 'column_id' => $this->request->getIntegerParam('column_id'),
- 'category_id' => $this->request->getIntegerParam('category_id'),
- );
-
- list($valid, ) = $this->taskValidator->validateCreation($values);
-
- if ($valid && $this->taskCreation->create($values)) {
- $this->response->text('OK');
- }
-
- $this->response->text('FAILED');
- }
-}