Improve automatic action duplication with unit tests and improve database schema

This commit is contained in:
Frederic Guillot
2015-06-20 14:34:47 -04:00
parent d3f789764d
commit aa6fdd3544
13 changed files with 444 additions and 81 deletions

View File

@@ -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'],
);
if (! $this->db->table(self::TABLE)->insert($values)) {
$this->container['logger']->debug('Action::duplicate => unable to create '.$action['action_name']);
$this->db->cancelTransaction();
continue;
}
$action_clone_id = $this->db->getConnection()->getLastId();
$action_id = $this->db->getConnection()->getLastId();
foreach ($actionParams as $param) {
unset($param['id']);
$param['value'] = $this->resolveDuplicatedParameters($param, $project_to);
$param['action_id'] = $action_clone_id;
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;
}
/**
* Resolve type of action value from a project to the respective value in another project
* 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 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'];
}

View File

@@ -376,6 +376,19 @@ class Board extends Base
return $this->db->table(self::TABLE)->eq('id', $column_id)->findOne();
}
/**
* 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
*

View File

@@ -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