From 44f680cf2f1463721eb5bdb7eda4d3b339e63ba9 Mon Sep 17 00:00:00 2001
From: Frederic Guillot
Date: Sat, 10 Sep 2016 22:37:57 -0400
Subject: Add ui to create new custom project roles and column restrictions
---
app/Controller/ColumnController.php | 5 +-
app/Controller/ColumnMoveRestrictionController.php | 102 ++++++++++++++++++++
app/Controller/ProjectOverviewController.php | 2 +-
app/Controller/ProjectPermissionController.php | 2 +-
app/Controller/ProjectRoleController.php | 107 +++++++++++++++++++++
app/Controller/ProjectUserOverviewController.php | 4 +-
app/Core/Base.php | 2 +
.../ColumnMoveRestrictionCacheDecorator.php | 6 +-
app/Helper/BoardHelper.php | 10 +-
app/Model/ColumnMoveRestrictionModel.php | 46 +++++++--
app/Model/ProjectRoleModel.php | 79 ++++++++++++++-
app/ServiceProvider/ClassProvider.php | 2 +
app/Template/column/index.php | 2 +
app/Template/column/remove.php | 2 +-
app/Template/column_move_restriction/create.php | 24 +++++
app/Template/column_move_restriction/remove.php | 14 +++
app/Template/project/sidebar.php | 3 +
app/Template/project_role/create.php | 18 ++++
app/Template/project_role/remove.php | 14 +++
app/Template/project_role/show.php | 58 +++++++++++
app/Validator/ColumnMoveRestrictionValidator.php | 41 ++++++++
app/Validator/ProjectRoleValidator.php | 70 ++++++++++++++
app/functions.php | 4 +-
23 files changed, 594 insertions(+), 23 deletions(-)
create mode 100644 app/Controller/ColumnMoveRestrictionController.php
create mode 100644 app/Controller/ProjectRoleController.php
create mode 100644 app/Template/column_move_restriction/create.php
create mode 100644 app/Template/column_move_restriction/remove.php
create mode 100644 app/Template/project_role/create.php
create mode 100644 app/Template/project_role/remove.php
create mode 100644 app/Template/project_role/show.php
create mode 100644 app/Validator/ColumnMoveRestrictionValidator.php
create mode 100644 app/Validator/ProjectRoleValidator.php
(limited to 'app')
diff --git a/app/Controller/ColumnController.php b/app/Controller/ColumnController.php
index d3f0e36e..8c366c6e 100644
--- a/app/Controller/ColumnController.php
+++ b/app/Controller/ColumnController.php
@@ -25,7 +25,7 @@ class ColumnController extends BaseController
$this->response->html($this->helper->layout->project('column/index', array(
'columns' => $columns,
'project' => $project,
- 'title' => t('Edit board')
+ 'title' => t('Edit columns')
)));
}
@@ -49,7 +49,6 @@ class ColumnController extends BaseController
'values' => $values,
'errors' => $errors,
'project' => $project,
- 'title' => t('Add a new column')
)));
}
@@ -102,7 +101,6 @@ class ColumnController extends BaseController
'values' => $values ?: $column,
'project' => $project,
'column' => $column,
- 'title' => t('Edit column "%s"', $column['title'])
)));
}
@@ -168,7 +166,6 @@ class ColumnController extends BaseController
$this->response->html($this->helper->layout->project('column/remove', array(
'column' => $this->columnModel->getById($this->request->getIntegerParam('column_id')),
'project' => $project,
- 'title' => t('Remove a column from a board')
)));
}
diff --git a/app/Controller/ColumnMoveRestrictionController.php b/app/Controller/ColumnMoveRestrictionController.php
new file mode 100644
index 00000000..3f1b878f
--- /dev/null
+++ b/app/Controller/ColumnMoveRestrictionController.php
@@ -0,0 +1,102 @@
+getProject();
+ $role_id = $this->request->getIntegerParam('role_id');
+ $role = $this->projectRoleModel->getById($project['id'], $role_id);
+
+ $this->response->html($this->template->render('column_move_restriction/create', array(
+ 'project' => $project,
+ 'role' => $role,
+ 'columns' => $this->columnModel->getList($project['id']),
+ 'values' => $values + array('project_id' => $project['id'], 'role_id' => $role['role_id']),
+ 'errors' => $errors,
+ )));
+ }
+
+ /**
+ * Save new column restriction
+ */
+ public function save()
+ {
+ $project = $this->getProject();
+ $values = $this->request->getValues();
+
+ list($valid, $errors) = $this->columnMoveRestrictionValidator->validateCreation($values);
+
+ if ($valid) {
+ $role_id = $this->columnMoveRestrictionModel->create(
+ $project['id'],
+ $values['role_id'],
+ $values['src_column_id'],
+ $values['dst_column_id']
+ );
+
+ if ($role_id !== false) {
+ $this->flash->success(t('The column restriction has been created successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to create this column restriction.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectRoleController', 'show', array('project_id' => $project['id'])));
+ } else {
+ $this->create($values, $errors);
+ }
+ }
+
+ /**
+ * Confirm suppression
+ *
+ * @access public
+ */
+ public function confirm()
+ {
+ $project = $this->getProject();
+ $restriction_id = $this->request->getIntegerParam('restriction_id');
+
+ $this->response->html($this->helper->layout->project('column_move_restriction/remove', array(
+ 'project' => $project,
+ 'restriction' => $this->columnMoveRestrictionModel->getById($project['id'], $restriction_id),
+ )));
+ }
+
+ /**
+ * Remove a restriction
+ *
+ * @access public
+ */
+ public function remove()
+ {
+ $project = $this->getProject();
+ $this->checkCSRFParam();
+ $restriction_id = $this->request->getIntegerParam('restriction_id');
+
+ if ($this->columnMoveRestrictionModel->remove($restriction_id)) {
+ $this->flash->success(t('Column restriction removed successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to remove this restriction.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectRoleController', 'show', array('project_id' => $project['id'])));
+ }
+}
diff --git a/app/Controller/ProjectOverviewController.php b/app/Controller/ProjectOverviewController.php
index abdff657..eb002936 100644
--- a/app/Controller/ProjectOverviewController.php
+++ b/app/Controller/ProjectOverviewController.php
@@ -23,7 +23,7 @@ class ProjectOverviewController extends BaseController
'title' => $project['name'],
'description' => $this->helper->projectHeader->getDescription($project),
'users' => $this->projectUserRoleModel->getAllUsersGroupedByRole($project['id']),
- 'roles' => $this->role->getProjectRoles(),
+ 'roles' => $this->projectRoleModel->getList($project['id']),
'events' => $this->helper->projectActivity->getProjectEvents($project['id'], 10),
'images' => $this->projectFileModel->getAllImages($project['id']),
'files' => $this->projectFileModel->getAllDocuments($project['id']),
diff --git a/app/Controller/ProjectPermissionController.php b/app/Controller/ProjectPermissionController.php
index 99f556e8..1aa59c6d 100644
--- a/app/Controller/ProjectPermissionController.php
+++ b/app/Controller/ProjectPermissionController.php
@@ -52,7 +52,7 @@ class ProjectPermissionController extends BaseController
'project' => $project,
'users' => $this->projectUserRoleModel->getUsers($project['id']),
'groups' => $this->projectGroupRoleModel->getGroups($project['id']),
- 'roles' => $this->role->getProjectRoles(),
+ 'roles' => $this->projectRoleModel->getList($project['id']),
'values' => $values,
'errors' => $errors,
'title' => t('Project Permissions'),
diff --git a/app/Controller/ProjectRoleController.php b/app/Controller/ProjectRoleController.php
new file mode 100644
index 00000000..87868748
--- /dev/null
+++ b/app/Controller/ProjectRoleController.php
@@ -0,0 +1,107 @@
+getProject();
+
+ $this->response->html($this->helper->layout->project('project_role/show', array(
+ 'project' => $project,
+ 'roles' => $this->projectRoleModel->getAllWithRestrictions($project['id']),
+ 'title' => t('Custom Project Roles'),
+ )));
+ }
+
+ /**
+ * Show form to create new role
+ *
+ * @param array $values
+ * @param array $errors
+ * @throws AccessForbiddenException
+ */
+ public function create(array $values = array(), array $errors = array())
+ {
+ $project = $this->getProject();
+
+ $this->response->html($this->template->render('project_role/create', array(
+ 'project' => $project,
+ 'values' => $values + array('project_id' => $project['id']),
+ 'errors' => $errors,
+ )));
+ }
+
+ /**
+ * Save new role
+ */
+ public function save()
+ {
+ $project = $this->getProject();
+ $values = $this->request->getValues();
+
+ list($valid, $errors) = $this->projectRoleValidator->validateCreation($values);
+
+ if ($valid) {
+ $role_id = $this->projectRoleModel->create($project['id'], $values['role']);
+
+ if ($role_id !== false) {
+ $this->flash->success(t('Your custom project role has been created successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to create custom project role.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectRoleController', 'show', array('project_id' => $project['id'])));
+ } else {
+ $this->create($values, $errors);
+ }
+ }
+
+ /**
+ * Confirm suppression
+ *
+ * @access public
+ */
+ public function confirm()
+ {
+ $project = $this->getProject();
+ $role_id = $this->request->getIntegerParam('role_id');
+
+ $this->response->html($this->helper->layout->project('project_role/remove', array(
+ 'project' => $project,
+ 'role' => $this->projectRoleModel->getById($project['id'], $role_id),
+ )));
+ }
+
+ /**
+ * Remove a custom role
+ *
+ * @access public
+ */
+ public function remove()
+ {
+ $project = $this->getProject();
+ $this->checkCSRFParam();
+ $role_id = $this->request->getIntegerParam('role_id');
+
+ if ($this->projectRoleModel->remove($project['id'], $role_id)) {
+ $this->flash->success(t('Custom project role removed successfully.'));
+ } else {
+ $this->flash->failure(t('Unable to remove this project role.'));
+ }
+
+ $this->response->redirect($this->helper->url->to('ProjectRoleController', 'show', array('project_id' => $project['id'])));
+ }
+}
diff --git a/app/Controller/ProjectUserOverviewController.php b/app/Controller/ProjectUserOverviewController.php
index 686de830..5faf5790 100644
--- a/app/Controller/ProjectUserOverviewController.php
+++ b/app/Controller/ProjectUserOverviewController.php
@@ -122,9 +122,9 @@ class ProjectUserOverviewController extends BaseController
{
$project = $this->getProject();
- return $this->response->html($this->template->render('project_user_overview/tooltip_users', array(
+ $this->response->html($this->template->render('project_user_overview/tooltip_users', array(
'users' => $this->projectUserRoleModel->getAllUsersGroupedByRole($project['id']),
- 'roles' => $this->role->getProjectRoles(),
+ 'roles' => $this->projectRoleModel->getList($project['id']),
)));
}
}
diff --git a/app/Core/Base.php b/app/Core/Base.php
index 747b1917..cadaef72 100644
--- a/app/Core/Base.php
+++ b/app/Core/Base.php
@@ -135,6 +135,7 @@ use Pimple\Container;
* @property \Kanboard\Validator\AuthValidator $authValidator
* @property \Kanboard\Validator\ColumnValidator $columnValidator
* @property \Kanboard\Validator\CategoryValidator $categoryValidator
+ * @property \Kanboard\Validator\ColumnMoveRestrictionValidator $columnMoveRestrictionValidator
* @property \Kanboard\Validator\CommentValidator $commentValidator
* @property \Kanboard\Validator\CurrencyValidator $currencyValidator
* @property \Kanboard\Validator\CustomFilterValidator $customFilterValidator
@@ -143,6 +144,7 @@ use Pimple\Container;
* @property \Kanboard\Validator\LinkValidator $linkValidator
* @property \Kanboard\Validator\PasswordResetValidator $passwordResetValidator
* @property \Kanboard\Validator\ProjectValidator $projectValidator
+ * @property \Kanboard\Validator\ProjectRoleValidator $projectRoleValidator
* @property \Kanboard\Validator\SubtaskValidator $subtaskValidator
* @property \Kanboard\Validator\SwimlaneValidator $swimlaneValidator
* @property \Kanboard\Validator\TagValidator $tagValidator
diff --git a/app/Decorator/ColumnMoveRestrictionCacheDecorator.php b/app/Decorator/ColumnMoveRestrictionCacheDecorator.php
index 331bdebb..cb5e860c 100644
--- a/app/Decorator/ColumnMoveRestrictionCacheDecorator.php
+++ b/app/Decorator/ColumnMoveRestrictionCacheDecorator.php
@@ -42,13 +42,13 @@ class ColumnMoveRestrictionCacheDecorator
* @param int $project_id
* @return array|mixed
*/
- public function getAllSrcColumns($project_id)
+ public function getAllSrcColumns($project_id, $role)
{
- $key = $this->cachePrefix.$project_id;
+ $key = $this->cachePrefix.$project_id.$role;
$columnIds = $this->cache->get($key);
if ($columnIds === null) {
- $columnIds = $this->columnMoveRestrictionModel->getAllSrcColumns($project_id);
+ $columnIds = $this->columnMoveRestrictionModel->getAllSrcColumns($project_id, $role);
$this->cache->set($key, $columnIds);
}
diff --git a/app/Helper/BoardHelper.php b/app/Helper/BoardHelper.php
index c3d28dc4..394d80b7 100644
--- a/app/Helper/BoardHelper.php
+++ b/app/Helper/BoardHelper.php
@@ -34,8 +34,14 @@ class BoardHelper extends Base
public function isDraggable(array $task)
{
if ($task['is_active'] == 1 && $this->helper->user->hasProjectAccess('BoardViewController', 'save', $task['project_id'])) {
- $srcColumnIds = $this->columnMoveRestrictionCacheDecorator->getAllSrcColumns($task['project_id']);
- return ! isset($srcColumnIds[$task['column_id']]);
+ $role = $this->helper->user->getProjectUserRole($task['project_id']);
+
+ if ($this->role->isCustomProjectRole($role)) {
+ $srcColumnIds = $this->columnMoveRestrictionCacheDecorator->getAllSrcColumns($task['project_id'], $role);
+ return ! isset($srcColumnIds[$task['column_id']]);
+ }
+
+ return true;
}
return false;
diff --git a/app/Model/ColumnMoveRestrictionModel.php b/app/Model/ColumnMoveRestrictionModel.php
index 63e739bf..aae1a391 100644
--- a/app/Model/ColumnMoveRestrictionModel.php
+++ b/app/Model/ColumnMoveRestrictionModel.php
@@ -34,6 +34,35 @@ class ColumnMoveRestrictionModel extends Base
->exists();
}
+ /**
+ * Fetch one restriction
+ *
+ * @param int $project_id
+ * @param int $restriction_id
+ * @return array|null
+ */
+ public function getById($project_id, $restriction_id)
+ {
+ return $this->db
+ ->table(self::TABLE)
+ ->columns(
+ self::TABLE.'.restriction_id',
+ self::TABLE.'.project_id',
+ self::TABLE.'.role_id',
+ self::TABLE.'.src_column_id',
+ self::TABLE.'.dst_column_id',
+ 'pr.role',
+ 'sc.title as src_column_title',
+ 'dc.title as dst_column_title'
+ )
+ ->left(ColumnModel::TABLE, 'sc', 'id', self::TABLE, 'src_column_id')
+ ->left(ColumnModel::TABLE, 'dc', 'id', self::TABLE, 'dst_column_id')
+ ->left(ProjectRoleModel::TABLE, 'pr', 'role_id', self::TABLE, 'role_id')
+ ->eq(self::TABLE.'.project_id', $project_id)
+ ->eq(self::TABLE.'.restriction_id', $restriction_id)
+ ->findOne();
+ }
+
/**
* Get all project column restrictions
*
@@ -45,9 +74,11 @@ class ColumnMoveRestrictionModel extends Base
return $this->db
->table(self::TABLE)
->columns(
- 'restriction_id',
- 'src_column_id',
- 'dst_column_id',
+ self::TABLE.'.restriction_id',
+ self::TABLE.'.project_id',
+ self::TABLE.'.role_id',
+ self::TABLE.'.src_column_id',
+ self::TABLE.'.dst_column_id',
'pr.role',
'sc.title as src_column_title',
'dc.title as dst_column_title'
@@ -61,15 +92,18 @@ class ColumnMoveRestrictionModel extends Base
/**
* Get all source column Ids
- *
- * @param int $project_id
+ *
+ * @param int $project_id
+ * @param string $role
* @return array
*/
- public function getAllSrcColumns($project_id)
+ public function getAllSrcColumns($project_id, $role)
{
return $this->db
->hashtable(self::TABLE)
+ ->left(ProjectRoleModel::TABLE, 'pr', 'role_id', self::TABLE, 'role_id')
->eq(self::TABLE.'.project_id', $project_id)
+ ->eq('pr.role', $role)
->getAll('src_column_id', 'src_column_id');
}
diff --git a/app/Model/ProjectRoleModel.php b/app/Model/ProjectRoleModel.php
index 93fe1dcc..82f22806 100644
--- a/app/Model/ProjectRoleModel.php
+++ b/app/Model/ProjectRoleModel.php
@@ -3,6 +3,7 @@
namespace Kanboard\Model;
use Kanboard\Core\Base;
+use Kanboard\Core\Security\Role;
/**
* Class ProjectRoleModel
@@ -14,6 +15,38 @@ class ProjectRoleModel extends Base
{
const TABLE = 'project_has_roles';
+ /**
+ * Get list of project roles
+ *
+ * @param int $project_id
+ * @return array
+ */
+ public function getList($project_id)
+ {
+ $defaultRoles = $this->role->getProjectRoles();
+ $customRoles = $this->db
+ ->hashtable(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->getAll('role', 'role');
+
+ return $defaultRoles + $customRoles;
+ }
+
+ /**
+ * Get a role
+ *
+ * @param int $project_id
+ * @param int $role_id
+ * @return array|null
+ */
+ public function getById($project_id, $role_id)
+ {
+ return $this->db->table(self::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('role_id', $role_id)
+ ->findOne();
+ }
+
/**
* Get all project roles
*
@@ -28,6 +61,22 @@ class ProjectRoleModel extends Base
->findAll();
}
+ /**
+ * Get all project roles with restrictions
+ *
+ * @param int $project_id
+ * @return array
+ */
+ public function getAllWithRestrictions($project_id)
+ {
+ $roles = $this->getAll($project_id);
+ $restrictions = $this->columnMoveRestrictionModel->getAll($project_id);
+ $restrictions = array_column_index($restrictions, 'role_id');
+ array_merge_relation($roles, $restrictions, 'restrictions', 'role_id');
+
+ return $roles;
+ }
+
/**
* Create a new project role
*
@@ -73,10 +122,38 @@ class ProjectRoleModel extends Base
*/
public function remove($project_id, $role_id)
{
- return $this->db
+ $this->db->startTransaction();
+
+ $role = $this->getById($project_id, $role_id);
+
+ $r1 = $this->db
+ ->table(ProjectUserRoleModel::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('role', $role['role'])
+ ->update(array(
+ 'role' => Role::PROJECT_MEMBER
+ ));
+
+ $r2 = $this->db
+ ->table(ProjectGroupRoleModel::TABLE)
+ ->eq('project_id', $project_id)
+ ->eq('role', $role['role'])
+ ->update(array(
+ 'role' => Role::PROJECT_MEMBER
+ ));
+
+ $r3 = $this->db
->table(self::TABLE)
->eq('project_id', $project_id)
->eq('role_id', $role_id)
->remove();
+
+ if ($r1 && $r2 && $r3) {
+ $this->db->closeTransaction();
+ return true;
+ }
+
+ $this->db->cancelTransaction();
+ return false;
}
}
diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php
index e79ffcee..98669e6d 100644
--- a/app/ServiceProvider/ClassProvider.php
+++ b/app/ServiceProvider/ClassProvider.php
@@ -99,6 +99,7 @@ class ClassProvider implements ServiceProviderInterface
'ActionValidator',
'AuthValidator',
'CategoryValidator',
+ 'ColumnMoveRestrictionValidator',
'ColumnValidator',
'CommentValidator',
'CurrencyValidator',
@@ -108,6 +109,7 @@ class ClassProvider implements ServiceProviderInterface
'LinkValidator',
'PasswordResetValidator',
'ProjectValidator',
+ 'ProjectRoleValidator',
'SubtaskValidator',
'SwimlaneValidator',
'TagValidator',
diff --git a/app/Template/column/index.php b/app/Template/column/index.php
index 66890ba5..8c96a350 100644
--- a/app/Template/column/index.php
+++ b/app/Template/column/index.php
@@ -41,9 +41,11 @@
-
+
= $this->url->link(t('Edit'), 'ColumnController', 'edit', array('project_id' => $project['id'], 'column_id' => $column['id']), false, 'popover') ?>
-
+
= $this->url->link(t('Remove'), 'ColumnController', 'confirm', array('project_id' => $project['id'], 'column_id' => $column['id']), false, 'popover') ?>
diff --git a/app/Template/column/remove.php b/app/Template/column/remove.php
index b231a9a7..dc0a4712 100644
--- a/app/Template/column/remove.php
+++ b/app/Template/column/remove.php
@@ -9,7 +9,7 @@
- = $this->url->link(t('Yes'), 'ColumnController', 'remove', array('project_id' => $project['id'], 'column_id' => $column['id'], 'remove' => 'yes'), true, 'btn btn-red') ?>
+ = $this->url->link(t('Yes'), 'ColumnController', 'remove', array('project_id' => $project['id'], 'column_id' => $column['id']), true, 'btn btn-red') ?>
= t('or') ?> = $this->url->link(t('cancel'), 'ColumnController', 'index', array('project_id' => $project['id']), false, 'close-popover') ?>
diff --git a/app/Template/column_move_restriction/create.php b/app/Template/column_move_restriction/create.php
new file mode 100644
index 00000000..69a75ce0
--- /dev/null
+++ b/app/Template/column_move_restriction/create.php
@@ -0,0 +1,24 @@
+
diff --git a/app/Template/column_move_restriction/remove.php b/app/Template/column_move_restriction/remove.php
new file mode 100644
index 00000000..1985e167
--- /dev/null
+++ b/app/Template/column_move_restriction/remove.php
@@ -0,0 +1,14 @@
+
+
+
+
+ = t('Do you really want to remove this column restriction: "%s" to "%s"?', $restriction['src_column_title'], $restriction['dst_column_title']) ?>
+
+
+
+ = $this->url->link(t('Yes'), 'ColumnMoveRestrictionController', 'remove', array('project_id' => $project['id'], 'restriction_id' => $restriction['restriction_id']), true, 'btn btn-red') ?>
+ = t('or') ?> = $this->url->link(t('cancel'), 'ProjectRoleController', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
+
+
diff --git a/app/Template/project/sidebar.php b/app/Template/project/sidebar.php
index 3be0da48..6e7fff05 100644
--- a/app/Template/project/sidebar.php
+++ b/app/Template/project/sidebar.php
@@ -38,6 +38,9 @@
app->checkMenuSelection('ProjectPermissionController') ?>>
= $this->url->link(t('Permissions'), 'ProjectPermissionController', 'index', array('project_id' => $project['id'])) ?>
+ app->checkMenuSelection('ProjectRoleController') ?>>
+ = $this->url->link(t('Custom roles'), 'ProjectRoleController', 'show', array('project_id' => $project['id'])) ?>
+
app->checkMenuSelection('ActionController') ?>>
= $this->url->link(t('Automatic actions'), 'ActionController', 'index', array('project_id' => $project['id'])) ?>
diff --git a/app/Template/project_role/create.php b/app/Template/project_role/create.php
new file mode 100644
index 00000000..8eee8f70
--- /dev/null
+++ b/app/Template/project_role/create.php
@@ -0,0 +1,18 @@
+
diff --git a/app/Template/project_role/remove.php b/app/Template/project_role/remove.php
new file mode 100644
index 00000000..25875e3a
--- /dev/null
+++ b/app/Template/project_role/remove.php
@@ -0,0 +1,14 @@
+
+
+
+
+ = t('Do you really want to remove this custom role: "%s"? All people assigned to this role will become project member.', $role['role']) ?>
+
+
+
+ = $this->url->link(t('Yes'), 'ProjectRoleController', 'remove', array('project_id' => $project['id'], 'role_id' => $role['role_id']), true, 'btn btn-red') ?>
+ = t('or') ?> = $this->url->link(t('cancel'), 'ProjectRoleController', 'show', array('project_id' => $project['id']), false, 'close-popover') ?>
+
+
diff --git a/app/Template/project_role/show.php b/app/Template/project_role/show.php
new file mode 100644
index 00000000..2114a1c9
--- /dev/null
+++ b/app/Template/project_role/show.php
@@ -0,0 +1,58 @@
+
+
+
+ = t('There is no custom role for this project.') ?>
+
+
+
+
+
+
+
+
+ -
+
+ = $this->url->link(t('Add a new column restriction'), 'ColumnMoveRestrictionController', 'create', array('project_id' => $project['id'], 'role_id' => $role['role_id']), false, 'popover') ?>
+
+ -
+
+ = $this->url->link(t('Remove this role'), 'ProjectRoleController', 'confirm', array('project_id' => $project['id'], 'role_id' => $role['role_id']), false, 'popover') ?>
+
+
+
+ |
+
+ = t('Actions') ?>
+ |
+
+
+
+ = t('There is no restriction for this role.') ?> |
+
+
+
+
+
+
+ = $this->text->e($restriction['src_column_title']) ?>
+
+ = $this->text->e($restriction['dst_column_title']) ?>
+ |
+
+
+ = $this->url->link(t('Remove'), 'ColumnMoveRestrictionController', 'confirm', array('project_id' => $project['id'], 'restriction_id' => $restriction['restriction_id']), false, 'popover') ?>
+ |
+
+
+
+
+
+
diff --git a/app/Validator/ColumnMoveRestrictionValidator.php b/app/Validator/ColumnMoveRestrictionValidator.php
new file mode 100644
index 00000000..99769c6b
--- /dev/null
+++ b/app/Validator/ColumnMoveRestrictionValidator.php
@@ -0,0 +1,41 @@
+execute(),
+ $v->getErrors()
+ );
+ }
+}
diff --git a/app/Validator/ProjectRoleValidator.php b/app/Validator/ProjectRoleValidator.php
new file mode 100644
index 00000000..a4b9da15
--- /dev/null
+++ b/app/Validator/ProjectRoleValidator.php
@@ -0,0 +1,70 @@
+commonValidationRules());
+
+ return array(
+ $v->execute(),
+ $v->getErrors()
+ );
+ }
+
+ /**
+ * Validate modification
+ *
+ * @access public
+ * @param array $values Form values
+ * @return array $valid, $errors [0] = Success or not, [1] = List of errors
+ */
+ public function validateModification(array $values)
+ {
+ $rules = array(
+ new Validators\Required('id', t('The id is required')),
+ );
+
+ $v = new Validator($values, array_merge($rules, $this->commonValidationRules()));
+
+ return array(
+ $v->execute(),
+ $v->getErrors()
+ );
+ }
+
+ /**
+ * Common validation rules
+ *
+ * @access private
+ * @return array
+ */
+ private function commonValidationRules()
+ {
+ return array(
+ new Validators\Required('role', t('This field is required')),
+ new Validators\MaxLength('role', t('The maximum length is %d characters', 100), 100),
+ new Validators\Required('project_id', t('This field is required')),
+ new Validators\Integer('project_id', t('This value must be an integer')),
+ new Validators\Integer('id', t('This value must be an integer')),
+ );
+ }
+}
diff --git a/app/functions.php b/app/functions.php
index eaf33a52..8f0d482c 100644
--- a/app/functions.php
+++ b/app/functions.php
@@ -25,13 +25,13 @@ function array_merge_relation(array &$input, array &$relations, $relation, $colu
* Create indexed array from a list of dict
*
* $input = [
- * ['k1' => 1, 'k2' => 2], ['k1' => 3, 'k2' => 4], ['k1' => 2, 'k2' => 5]
+ * ['k1' => 1, 'k2' => 2], ['k1' => 3, 'k2' => 4], ['k1' => 1, 'k2' => 5]
* ]
*
* array_column_index($input, 'k1') will returns:
*
* [
- * 1 => [['k1' => 1, 'k2' => 2], ['k1' => 2, 'k2' => 5]],
+ * 1 => [['k1' => 1, 'k2' => 2], ['k1' => 1, 'k2' => 5]],
* 3 => [['k1' => 3, 'k2' => 4]],
* ]
*
--
cgit v1.2.3