summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2015-06-20 14:34:47 -0400
committerFrederic Guillot <fred@kanboard.net>2015-06-20 14:34:47 -0400
commitaa6fdd3544b64eeab3d577c58425e128c809a135 (patch)
tree388de73e11567e8927bc12694cc65a3c629f6a59 /app
parentd3f789764dcf90923a0d0f639dd2ee56b1177f84 (diff)
Improve automatic action duplication with unit tests and improve database schema
Diffstat (limited to 'app')
-rw-r--r--app/Model/Action.php123
-rw-r--r--app/Model/Board.php13
-rw-r--r--app/Model/Category.php2
-rw-r--r--app/Schema/Mysql.php37
-rw-r--r--app/Schema/Postgres.php38
-rw-r--r--app/Schema/Sqlite.php52
6 files changed, 196 insertions, 69 deletions
diff --git a/app/Model/Action.php b/app/Model/Action.php
index 7547e37e..35872bdd 100644
--- a/app/Model/Action.php
+++ b/app/Model/Action.php
@@ -53,7 +53,7 @@ class Action extends Base
'TaskAssignCategoryColor' => t('Assign automatically a category based on a color'),
'CommentCreation' => t('Create a comment from an external provider'),
'TaskCreation' => t('Create a task from an external provider'),
- 'TaskLogMoveAnotherColumn' => t('Add a comment logging moving the task between columns'),
+ 'TaskLogMoveAnotherColumn' => t('Add a comment log when moving the task between columns'),
'TaskAssignUser' => t('Change the assignee based on an external username'),
'TaskAssignCategoryLabel' => t('Change the category based on an external label'),
'TaskUpdateStartDate' => t('Automatically update the start date'),
@@ -176,7 +176,6 @@ class Action extends Base
$params = array();
foreach ($this->getAll() as $action) {
-
$action = $this->load($action['action_name'], $action['project_id'], $action['event_name']);
$params += $action->getActionRequiredParameters();
}
@@ -194,7 +193,10 @@ class Action extends Base
public function getById($action_id)
{
$action = $this->db->table(self::TABLE)->eq('id', $action_id)->findOne();
- $action['params'] = $this->db->table(self::TABLE_PARAMS)->eq('action_id', $action_id)->findAll();
+
+ if (! empty($action)) {
+ $action['params'] = $this->db->table(self::TABLE_PARAMS)->eq('action_id', $action_id)->findAll();
+ }
return $action;
}
@@ -286,7 +288,7 @@ class Action extends Base
* @param string $name Action class name
* @param integer $project_id Project id
* @param string $event Event name
- * @return \Core\Listener Action instance
+ * @return \Action\Base
*/
public function load($name, $project_id, $event)
{
@@ -295,70 +297,111 @@ class Action extends Base
}
/**
- * Copy Actions and related Actions Parameters from a project to another one
+ * Copy actions from a project to another one (skip actions that cannot resolve parameters)
*
* @author Antonio Rabelo
- * @param integer $project_from Project Template
- * @return integer $project_to Project that receives the copy
+ * @param integer $src_project_id Source project id
+ * @return integer $dst_project_id Destination project id
* @return boolean
*/
- public function duplicate($project_from, $project_to)
+ public function duplicate($src_project_id, $dst_project_id)
{
- $actionTemplate = $this->action->getAllByProject($project_from);
+ $actions = $this->action->getAllByProject($src_project_id);
- foreach ($actionTemplate as $action) {
+ foreach ($actions as $action) {
- unset($action['id']);
- $action['project_id'] = $project_to;
- $actionParams = $action['params'];
- unset($action['params']);
+ $this->db->startTransaction();
- if (! $this->db->table(self::TABLE)->save($action)) {
- return false;
- }
+ $values = array(
+ 'project_id' => $dst_project_id,
+ 'event_name' => $action['event_name'],
+ 'action_name' => $action['action_name'],
+ );
- $action_clone_id = $this->db->getConnection()->getLastId();
+ if (! $this->db->table(self::TABLE)->insert($values)) {
+ $this->container['logger']->debug('Action::duplicate => unable to create '.$action['action_name']);
+ $this->db->cancelTransaction();
+ continue;
+ }
- foreach ($actionParams as $param) {
- unset($param['id']);
- $param['value'] = $this->resolveDuplicatedParameters($param, $project_to);
- $param['action_id'] = $action_clone_id;
+ $action_id = $this->db->getConnection()->getLastId();
- if (! $this->db->table(self::TABLE_PARAMS)->save($param)) {
- return false;
- }
+ if (! $this->duplicateParameters($dst_project_id, $action_id, $action['params'])) {
+ $this->container['logger']->debug('Action::duplicate => unable to copy parameters for '.$action['action_name']);
+ $this->db->cancelTransaction();
+ continue;
}
+
+ $this->db->closeTransaction();
}
- // $this->container['fileCache']->remove('proxy_action_getAll');
+ return true;
+ }
+
+ /**
+ * Duplicate action parameters
+ *
+ * @access public
+ * @param integer $project_id
+ * @param integer $action_id
+ * @param array $params
+ * @return boolean
+ */
+ public function duplicateParameters($project_id, $action_id, array $params)
+ {
+ foreach ($params as $param) {
+
+ $value = $this->resolveParameters($param, $project_id);
+
+ if ($value === false) {
+ $this->container['logger']->debug('Action::duplicateParameters => unable to resolve '.$param['name'].'='.$param['value']);
+ return false;
+ }
+
+ $values = array(
+ 'action_id' => $action_id,
+ 'name' => $param['name'],
+ 'value' => $value,
+ );
+
+ if (! $this->db->table(self::TABLE_PARAMS)->insert($values)) {
+ return false;
+ }
+ }
return true;
}
/**
- * Resolve type of action value from a project to the respective value in another project
+ * Resolve action parameter values according to another project
*
* @author Antonio Rabelo
- * @param integer $param An action parameter
- * @return integer $project_to Project to find the corresponding values
- * @return mixed The corresponding values from $project_to
+ * @access public
+ * @param array $param Action parameter
+ * @param integer $project_id Project to find the corresponding values
+ * @return mixed
*/
- private function resolveDuplicatedParameters($param, $project_to)
+ public function resolveParameters(array $param, $project_id)
{
- switch($param['name']) {
+ switch ($param['name']) {
case 'project_id':
- return $project_to;
+ return $project_id;
case 'category_id':
- $categoryTemplate = $this->category->getById($param['value']);
- $categoryFromNewProject = $this->db->table(Category::TABLE)->eq('project_id', $project_to)->eq('name', $categoryTemplate['name'])->findOne();
- return $categoryFromNewProject['id'];
+ return $this->category->getIdByName($project_id, $this->category->getNameById($param['value'])) ?: false;
case 'src_column_id':
case 'dest_column_id':
+ case 'dst_column_id':
case 'column_id':
- $boardTemplate = $this->board->getColumn($param['value']);
- $boardFromNewProject = $this->db->table(Board::TABLE)->eq('project_id', $project_to)->eq('title', $boardTemplate['title'])->findOne();
- return $boardFromNewProject['id'];
- // TODO: Add user_id
+ $column = $this->board->getColumn($param['value']);
+
+ if (empty($column)) {
+ return false;
+ }
+
+ return $this->board->getColumnIdByTitle($project_id, $column['title']) ?: false;
+ case 'user_id':
+ case 'owner_id':
+ return $this->projectPermission->isMember($project_id, $param['value']) ? $param['value'] : false;
default:
return $param['value'];
}
diff --git a/app/Model/Board.php b/app/Model/Board.php
index eecbc91c..f6f968f4 100644
--- a/app/Model/Board.php
+++ b/app/Model/Board.php
@@ -377,6 +377,19 @@ class Board extends Base
}
/**
+ * Get a column id by the name
+ *
+ * @access public
+ * @param integer $project_id
+ * @param string $title
+ * @return integer
+ */
+ public function getColumnIdByTitle($project_id, $title)
+ {
+ return (int) $this->db->table(self::TABLE)->eq('project_id', $project_id)->eq('title', $title)->findOneColumn('id');
+ }
+
+ /**
* Get the position of the last column for a given project
*
* @access public
diff --git a/app/Model/Category.php b/app/Model/Category.php
index c8ba7251..9f93e7be 100644
--- a/app/Model/Category.php
+++ b/app/Model/Category.php
@@ -58,7 +58,7 @@ class Category extends Base
}
/**
- * Get a category id by the project and the name
+ * Get a category id by the category name and project id
*
* @access public
* @param integer $project_id Project id
diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php
index bcb365bd..21b7a4de 100644
--- a/app/Schema/Mysql.php
+++ b/app/Schema/Mysql.php
@@ -6,7 +6,42 @@ use PDO;
use Core\Security;
use Model\Link;
-const VERSION = 73;
+const VERSION = 74;
+
+function version_74($pdo)
+{
+ $pdo->exec('ALTER TABLE project_has_categories MODIFY project_id INT NOT NULL');
+ $pdo->exec('ALTER TABLE project_has_categories MODIFY name VARCHAR(255) NOT NULL');
+
+ $pdo->exec('ALTER TABLE actions MODIFY project_id INT NOT NULL');
+ $pdo->exec('ALTER TABLE actions MODIFY event_name VARCHAR(50) NOT NULL');
+ $pdo->exec('ALTER TABLE actions MODIFY action_name VARCHAR(50) NOT NULL');
+
+ $pdo->exec('ALTER TABLE action_has_params MODIFY action_id INT NOT NULL');
+ $pdo->exec('ALTER TABLE action_has_params MODIFY name VARCHAR(50) NOT NULL');
+ $pdo->exec('ALTER TABLE action_has_params MODIFY value VARCHAR(50) NOT NULL');
+
+ $pdo->exec('ALTER TABLE files MODIFY name VARCHAR(255) NOT NULL');
+ $pdo->exec('ALTER TABLE files MODIFY task_id INT NOT NULL');
+
+ $pdo->exec('ALTER TABLE subtasks MODIFY title VARCHAR(255) NOT NULL');
+
+ $pdo->exec('ALTER TABLE tasks MODIFY project_id INT NOT NULL');
+ $pdo->exec('ALTER TABLE tasks MODIFY column_id INT NOT NULL');
+
+ $pdo->exec('ALTER TABLE columns MODIFY title VARCHAR(255) NOT NULL');
+ $pdo->exec('ALTER TABLE columns MODIFY project_id INT NOT NULL');
+
+ $pdo->exec('ALTER TABLE project_has_users MODIFY project_id INT NOT NULL');
+ $pdo->exec('ALTER TABLE project_has_users MODIFY user_id INT NOT NULL');
+
+ $pdo->exec('ALTER TABLE projects MODIFY name VARCHAR(255) NOT NULL UNIQUE');
+
+ $pdo->exec('ALTER TABLE users MODIFY username VARCHAR(50) NOT NULL');
+
+ $pdo->exec('ALTER TABLE user_has_notifications MODIFY project_id INT NOT NULL');
+ $pdo->exec('ALTER TABLE user_has_notifications MODIFY user_id INT NOT NULL');
+}
function version_73($pdo)
{
diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php
index 65a9c9bf..a8b76399 100644
--- a/app/Schema/Postgres.php
+++ b/app/Schema/Postgres.php
@@ -6,7 +6,43 @@ use PDO;
use Core\Security;
use Model\Link;
-const VERSION = 53;
+const VERSION = 54;
+
+function version_54($pdo)
+{
+ $pdo->exec("ALTER TABLE project_has_categories ALTER COLUMN project_id SET NOT NULL");
+ $pdo->exec("ALTER TABLE project_has_categories ALTER COLUMN name SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE actions ALTER COLUMN project_id SET NOT NULL");
+ $pdo->exec("ALTER TABLE actions ALTER COLUMN event_name SET NOT NULL");
+ $pdo->exec("ALTER TABLE actions ALTER COLUMN action_name SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE action_has_params ALTER COLUMN action_id SET NOT NULL");
+ $pdo->exec("ALTER TABLE action_has_params ALTER COLUMN name SET NOT NULL");
+ $pdo->exec("ALTER TABLE action_has_params ALTER COLUMN value SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE files ALTER COLUMN name SET NOT NULL");
+ $pdo->exec("ALTER TABLE files ALTER COLUMN task_id SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE subtasks ALTER COLUMN title SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE tasks ALTER COLUMN title SET NOT NULL");
+ $pdo->exec("ALTER TABLE tasks ALTER COLUMN project_id SET NOT NULL");
+ $pdo->exec("ALTER TABLE tasks ALTER COLUMN column_id SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE columns ALTER COLUMN title SET NOT NULL");
+ $pdo->exec("ALTER TABLE columns ALTER COLUMN project_id SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE project_has_users ALTER COLUMN project_id SET NOT NULL");
+ $pdo->exec("ALTER TABLE project_has_users ALTER COLUMN user_id SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE projects ALTER COLUMN name SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE users ALTER COLUMN username SET NOT NULL");
+
+ $pdo->exec("ALTER TABLE user_has_notifications ALTER COLUMN user_id SET NOT NULL");
+ $pdo->exec("ALTER TABLE user_has_notifications ALTER COLUMN user_id SET NOT NULL");
+}
function version_53($pdo)
{
diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php
index ceb3028c..6ad7f34a 100644
--- a/app/Schema/Sqlite.php
+++ b/app/Schema/Sqlite.php
@@ -429,10 +429,10 @@ function version_37($pdo)
$pdo->exec("
CREATE TABLE swimlanes (
id INTEGER PRIMARY KEY,
- name TEXT,
+ name TEXT NOT NULL,
position INTEGER DEFAULT 1,
is_active INTEGER DEFAULT 1,
- project_id INTEGER,
+ project_id INTEGER NOT NULL,
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
UNIQUE (name, project_id)
)
@@ -477,9 +477,9 @@ function version_33($pdo)
id INTEGER PRIMARY KEY,
date_creation INTEGER NOT NULL,
event_name TEXT NOT NULL,
- creator_id INTEGER,
- project_id INTEGER,
- task_id INTEGER,
+ creator_id INTEGE NOT NULL,
+ project_id INTEGER NOT NULL,
+ task_id INTEGER NOT NULL,
data TEXT,
FOREIGN KEY(creator_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
@@ -622,8 +622,8 @@ function version_23($pdo)
$pdo->exec("
CREATE TABLE user_has_notifications (
- user_id INTEGER,
- project_id INTEGER,
+ user_id INTEGER NOT NULL,
+ project_id INTEGER NOT NULL,
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
UNIQUE(project_id, user_id)
@@ -659,7 +659,7 @@ function version_18($pdo)
$pdo->exec("
CREATE TABLE task_has_subtasks (
id INTEGER PRIMARY KEY,
- title TEXT COLLATE NOCASE,
+ title TEXT COLLATE NOCASE NOT NULL,
status INTEGER DEFAULT 0,
time_estimated NUMERIC DEFAULT 0,
time_spent NUMERIC DEFAULT 0,
@@ -675,10 +675,10 @@ function version_17($pdo)
$pdo->exec("
CREATE TABLE task_has_files (
id INTEGER PRIMARY KEY,
- name TEXT COLLATE NOCASE,
+ name TEXT COLLATE NOCASE NOT NULL,
path TEXT,
is_image INTEGER DEFAULT 0,
- task_id INTEGER,
+ task_id INTEGER NOT NULL,
FOREIGN KEY(task_id) REFERENCES tasks(id) ON DELETE CASCADE
)"
);
@@ -689,8 +689,8 @@ function version_16($pdo)
$pdo->exec("
CREATE TABLE project_has_categories (
id INTEGER PRIMARY KEY,
- name TEXT COLLATE NOCASE,
- project_id INT,
+ name TEXT COLLATE NOCASE NOT NULL,
+ project_id INTEGER NOT NULL,
UNIQUE (project_id, name),
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
)"
@@ -721,7 +721,7 @@ function version_12($pdo)
$pdo->exec(
'CREATE TABLE remember_me (
id INTEGER PRIMARY KEY,
- user_id INTEGER,
+ user_id INTEGER NOT NULL,
ip TEXT,
user_agent TEXT,
token TEXT,
@@ -736,7 +736,7 @@ function version_12($pdo)
'CREATE TABLE last_logins (
id INTEGER PRIMARY KEY,
auth_type TEXT,
- user_id INTEGER,
+ user_id INTEGER NOT NULL,
ip TEXT,
user_agent TEXT,
date_creation INTEGER,
@@ -779,9 +779,9 @@ function version_10($pdo)
$pdo->exec(
'CREATE TABLE actions (
id INTEGER PRIMARY KEY,
- project_id INTEGER,
- event_name TEXT,
- action_name TEXT,
+ project_id INTEGER NOT NULL,
+ event_name TEXT NOT NULL,
+ action_name TEXT NOT NULL,
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
)'
);
@@ -789,9 +789,9 @@ function version_10($pdo)
$pdo->exec(
'CREATE TABLE action_has_params (
id INTEGER PRIMARY KEY,
- action_id INTEGER,
- name TEXT,
- value TEXT,
+ action_id INTEGER NOT NULL,
+ name TEXT NOT NULL,
+ value TEXT NOT NULL,
FOREIGN KEY(action_id) REFERENCES actions(id) ON DELETE CASCADE
)'
);
@@ -822,8 +822,8 @@ function version_7($pdo)
$pdo->exec("
CREATE TABLE project_has_users (
id INTEGER PRIMARY KEY,
- project_id INTEGER,
- user_id INTEGER,
+ project_id INTEGER NOT NULL,
+ user_id INTEGER NOT NULL,
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
UNIQUE(project_id, user_id)
@@ -869,7 +869,7 @@ function version_1($pdo)
$pdo->exec("
CREATE TABLE users (
id INTEGER PRIMARY KEY,
- username TEXT,
+ username TEXT NOT NULL,
password TEXT,
is_admin INTEGER DEFAULT 0,
default_project_id INTEGER DEFAULT 0
@@ -879,7 +879,7 @@ function version_1($pdo)
$pdo->exec("
CREATE TABLE projects (
id INTEGER PRIMARY KEY,
- name TEXT NOCASE UNIQUE,
+ name TEXT NOCASE NOT NULL UNIQUE,
is_active INTEGER DEFAULT 1
)
");
@@ -887,9 +887,9 @@ function version_1($pdo)
$pdo->exec("
CREATE TABLE columns (
id INTEGER PRIMARY KEY,
- title TEXT,
+ title TEXT NOT NULL,
position INTEGER,
- project_id INTEGER,
+ project_id INTEGER NOT NULL,
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE,
UNIQUE (title, project_id)
)