Project cloning/duplication (pull-request #196)

This commit is contained in:
Frédéric Guillot
2014-08-12 12:03:15 -07:00
parent 9f46120de9
commit 66b5659578
12 changed files with 264 additions and 1 deletions

View File

@@ -377,6 +377,212 @@ class Project extends Base
return $this->filterListByAccess($this->getListByStatus(self::ACTIVE), $user_id);
}
/**
* Create a project from another one.
*
* @author Antonio Rabelo
* @param integer $project_id Project Id
* @return integer Cloned Project Id
*/
public function createProjectFromAnotherProject($project_id)
{
// Recover the template project data
$project = $this->getById($project_id);
// Create a Clone project
$clone_project = array(
'name' => $project['name'].' ('.t('Clone').')',
'is_active' => true,
'last_modified' => 0,
'token' => Security::generateToken(),
);
// Register the cloned project
if (! $this->db->table(self::TABLE)->save($clone_project)) {
return false;
}
// Get the cloned project Id
return $this->db->getConnection()->getLastId();
}
/**
* Copy Board Columns from a project to another one.
*
* @author Antonio Rabelo
* @param integer $project_from Project Template
* @return integer $project_to Project that receives the copy
* @return boolean
*/
public function copyBoardFromAnotherProject($project_from, $project_to)
{
$boardModel = new Board($this->db, $this->event);
$columns = $this->db->table(Board::TABLE)->eq('project_id', $project_from)->asc('position')->findAllByColumn('title');
return $boardModel->create($project_to, $columns);
}
/**
* Copy Categories from a project to another one.
*
* @author Antonio Rabelo
* @param integer $project_from Project Template
* @return integer $project_to Project that receives the copy
* @return boolean
*/
public function copyCategoriesFromAnotherProject($project_from, $project_to)
{
$categoryModel = new Category($this->db, $this->event);
$categoriesTemplate = $categoryModel->getAll($project_from);
foreach ($categoriesTemplate as $category) {
unset($category['id']);
$category['project_id'] = $project_to;
if (! $categoryModel->create($category)) {
return false;
}
}
return true;
}
/**
* Copy User Access from a project to another one.
*
* @author Antonio Rabelo
* @param integer $project_from Project Template
* @return integer $project_to Project that receives the copy
* @return boolean
*/
public function copyUserAccessFromAnotherProject($project_from, $project_to)
{
$usersList = $this->getAllowedUsers($project_from);
foreach ($usersList as $id => $userName) {
if (! $this->allowUser($project_to, $id)) {
return false;
}
}
return true;
}
/**
* Copy Actions and related Actions Parameters from a project to another one.
*
* @author Antonio Rabelo
* @param integer $project_from Project Template
* @return integer $project_to Project that receives the copy
* @return boolean
*/
public function copyActionsFromAnotherProject($project_from, $project_to)
{
$actionModel = new Action($this->db, $this->event);
$actionTemplate = $actionModel->getAllByProject($project_from);
foreach ($actionTemplate as $action) {
unset($action['id']);
$action['project_id'] = $project_to;
$actionParams = $action['params'];
unset($action['params']);
if (! $this->db->table(Action::TABLE)->save($action)) {
return false;
}
$action_clone_id = $this->db->getConnection()->getLastId();
foreach ($actionParams as $param) {
unset($param['id']);
$param['value'] = $this->resolveValueParamToClonedAction($param, $project_to);
$param['action_id'] = $action_clone_id;
if (! $this->db->table(Action::TABLE_PARAMS)->save($param)) {
return false;
}
}
}
return true;
}
/**
* Resolve type of action value from a project to the respective value in another project.
*
* @author Antonio Rabelo
* @param integer $param A action parameter
* @return integer $project_to Project to find the corresponding values
* @return mixed The corresponding values from $project_to
*/
private function resolveValueParamToClonedAction($param, $project_to)
{
switch($param['name']) {
case 'project_id':
return $project_to;
case 'category_id':
$categoryModel = new Category($this->db, $this->event);
$categoryTemplate = $categoryModel->getById($param['value']);
$categoryFromNewProject = $this->db->table(Category::TABLE)->eq('project_id', $project_to)->eq('name', $categoryTemplate['name'])->findOne();
return $categoryFromNewProject['id'];
case 'column_id':
$boardModel = new Board($this->db, $this->event);
$boardTemplate = $boardModel->getColumn($param['value']);
$boardFromNewProject = $this->db->table(Board::TABLE)->eq('project_id', $project_to)->eq('title', $boardTemplate['title'])->findOne();
return $boardFromNewProject['id'];
default:
return $param['value'];
}
}
/**
* Clone a project
*
* @author Antonio Rabelo
* @param integer $project_id Project Id
* @return integer Cloned Project Id
*/
public function duplicate($project_id)
{
$this->db->startTransaction();
// Get the cloned project Id
$clone_project_id = $this->createProjectFromAnotherProject($project_id);
if (! $clone_project_id) {
$this->db->cancelTransaction();
return false;
}
// Clone Board
if (! $this->copyBoardFromAnotherProject($project_id, $clone_project_id)) {
$this->db->cancelTransaction();
return false;
}
// Clone Categories
if (! $this->copyCategoriesFromAnotherProject($project_id, $clone_project_id)) {
$this->db->cancelTransaction();
return false;
}
// Clone Allowed Users
if (! $this->copyUserAccessFromAnotherProject($project_id, $clone_project_id)) {
$this->db->cancelTransaction();
return false;
}
// Clone Actions
if (! $this->copyActionsFromAnotherProject($project_id, $clone_project_id)) {
$this->db->cancelTransaction();
return false;
}
$this->db->closeTransaction();
return (int) $clone_project_id;
}
/**
* Create a project
*