* @package project * @version $Id * @link http://www.zentao.net */ class project extends control { /** * Project create guide. * * @param int $projectID * @param string $from * @access public * @return void */ public function createGuide($projectID = 0, $from = 'project') { $this->view->from = $from; $this->view->projectID = $projectID; $this->display(); } /** * Update children user view. * * @param int $projectID * @param array $account * @access public * @return void */ public function updateChildUserView($projectID = 0, $account = array()) { $childPrograms = $this->dao->select('id')->from(TABLE_PROJECT)->where('path')->like("%,$projectID,%")->andWhere('type')->eq('project')->fetchPairs(); $childProjects = $this->dao->select('id')->from(TABLE_PROJECT)->where('path')->like("%,$projectID,%")->andWhere('type')->eq('project')->fetchPairs(); $childProducts = $this->dao->select('id')->from(TABLE_PRODUCT)->where('project')->eq($projectID)->fetchPairs(); if(!empty($childPrograms)) $this->user->updateUserView($childPrograms, 'project', array($account)); if(!empty($childProjects)) $this->user->updateUserView($childProjects, 'project', array($account)); if(!empty($childProducts)) $this->user->updateUserView($childProducts, 'product', array($account)); } /** * Export project. * * @param string $status * @param string $orderBy * @access public * @return void */ public function export($status, $orderBy) { if($_POST) { $projectLang = $this->lang->project; $projectConfig = $this->config->project; /* Create field lists. */ $fields = $this->post->exportFields ? $this->post->exportFields : explode(',', $projectConfig->list->exportFields); foreach($fields as $key => $fieldName) { $fieldName = trim($fieldName); $fields[$fieldName] = zget($projectLang, $fieldName); unset($fields[$key]); } $projects = $this->project->getInfoList($status, 30, $orderBy, null); $users = $this->loadModel('user')->getPairs('noletter'); $this->loadModel('product'); foreach($projects as $i => $project) { $project->PM = zget($users, $project->PM); $project->status = $this->processStatus('project', $project); $project->model = zget($projectLang->modelList, $project->model); $project->product = zget($projectLang->productList, $project->product); $project->budget = $project->budget . zget($projectLang->unitList, $project->budgetUnit); $project->parent = $project->parentName; $linkedProducts = $this->product->getProducts($project->id, 'all', '', false); $project->linkedProducts = implode(',', $linkedProducts); if($this->post->exportType == 'selected') { $checkedItem = $this->cookie->checkedItem; if(strpos(",$checkedItem,", ",{$project->id},") === false) unset($projects[$i]); } } if(isset($this->config->bizVersion)) list($fields, $projectStats) = $this->loadModel('workflowfield')->appendDataFromFlow($fields, $projectStats); $this->post->set('fields', $fields); $this->post->set('rows', $projects); $this->post->set('kind', 'project'); $this->fetch('file', 'export2' . $this->post->fileType, $_POST); } $this->display(); } /** * Ajax get project drop menu. * * @param int $projectID * @param string $module * @param string $method * @access public * @return void */ public function ajaxGetDropMenu($projectID = 0, $module, $method) { /* Load module. */ $this->loadModel('program'); /* Set cookie for show all project. */ $_COOKIE['showClosed'] = 1; /* Sort project. */ $programs = array(); $orderedProjects = array(); $projects = $this->dao->select('*')->from(TABLE_PROJECT) ->where('type')->eq('project') ->andWhere('deleted')->eq(0) ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->projects)->fi() ->orderBy('order_asc') ->fetchAll('id'); $programs = $this->program->getPairs(true); foreach($projects as $project) { $project->parent = $this->program->getTopByID($project->parent); $project->parent = isset($programs[$project->parent]) ? $project->parent : $project->id; $orderedProjects[$project->parent][] = $project; unset($projects[$project->id]); } $this->view->projectID = $projectID; $this->view->projects = $orderedProjects; $this->view->module = $module; $this->view->method = $method; $this->view->programs = $programs; $this->display(); } /** * Ajax get projects. * * @access public * @return void */ public function ajaxGetCopyProjects() { $data = fixer::input('post')->get(); $projects = $this->dao->select('id, name')->from(TABLE_PROJECT) ->where('type')->eq('project') ->andWhere('deleted')->eq(0) ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->projects)->fi() ->beginIF(trim($data->name))->andWhere('name')->like("%$data->name%")->fi() ->fetchPairs(); $html = empty($projects) ? "
{$this->lang->noData}
" : ''; foreach($projects as $id => $name) { $active = $data->cpoyProjectID == $id ? 'active' : ''; $html .= "
" . html::icon($this->lang->icons['project'], 'text-muted') . $name . "
"; } echo $html; } /** * Ajax get unlink tips when unlink team member. * * @param int $projectID * @param int $account * @access public * @return void */ public function ajaxGetUnlinkTips($projectID, $account) { $executions = $this->loadModel('execution')->getByProject($projectID, 'undone', 0, true); $executionMembers = $this->dao->select('t1.root,t2.name')->from(TABLE_TEAM)->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.root=t2.id') ->where('t1.root')->in(array_keys($executions)) ->andWhere('t1.type')->eq('execution') ->andWhere('t1.account')->eq($account) ->fetchPairs(); if(empty($executionMembers)) die(); $executionNames = ''; $count = 0; foreach($executionMembers as $executionName) { if($count == 0) $executionNames = $executionName; if($count == 1) $executionNames .= ',' . $executionName; if($count > 1) break; $count++; } if(count($executionMembers) <= 2) $this->lang->project->etc = ' '; if(strpos($this->app->getClientLang(), 'zh') !== false) { $this->lang->project->unlinkExecutionMember = sprintf($this->lang->project->unlinkExecutionMember, $executionNames, $this->lang->project->etc, count($executionMembers)); } else { $this->lang->project->unlinkExecutionMember = sprintf($this->lang->project->unlinkExecutionMember, count($executionMembers), $executionNames, $this->lang->project->etc); } die($this->lang->project->unlinkExecutionMember); } /** * Project index view. * * @param int $projectID * @access public * @return void */ public function index($projectID = 0) { $projectID = $this->project->saveState($projectID, $this->project->getPairsByProgram()); if($projectID == 0 and common::hasPriv('project', 'create')) $this->locate($this->createLink('project', 'create')); if($projectID == 0 and !common::hasPriv('project', 'create')) $this->locate($this->createLink('project', 'browse')); $this->project->setMenu($projectID); $project = $this->project->getByID($projectID); if(empty($project) || $project->type != 'project') die(js::error($this->lang->notFound) . js::locate('back')); if(!$projectID) $this->locate($this->createLink('project', 'browse')); setCookie("lastProject", $projectID, $this->config->cookieLife, $this->config->webRoot, '', false, true); $this->view->title = $this->lang->project->common . $this->lang->colon . $this->lang->project->index; $this->view->position[] = $this->lang->project->index; $this->view->project = $project; $this->display(); } /** * Project list. * * @param int $programID * @param string $browseType * @param int $param * @param string $orderBy * @param int $recTotal * @param int $recPerPage * @param int $pageID * @access public * @return void */ public function browse($programID = 0, $browseType = 'doing', $param = 0, $orderBy = 'order_asc', $recTotal = 0, $recPerPage = 15, $pageID = 1) { $this->loadModel('datatable'); $this->loadModel('execution'); $this->session->set('projectList', $this->app->getURI(true), 'project'); $projectType = $this->cookie->projectType ? $this->cookie->projectType : 'bylist'; /* Load pager and get tasks. */ $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage, $pageID); $queryID = ($browseType == 'bysearch') ? (int)$param : 0; $programTitle = $this->loadModel('setting')->getItem('owner=' . $this->app->user->account . '&module=project&key=programTitle'); $projectStats = $this->loadModel('program')->getProjectStats($programID, $browseType, $queryID, $orderBy, $pager, $programTitle); $this->view->title = $this->lang->project->browse; $this->view->position[] = $this->lang->project->browse; $this->view->projectStats = $projectStats; $this->view->pager = $pager; $this->view->programID = $programID; $this->view->program = $this->program->getByID($programID); $this->view->programTree = $this->project->getTreeMenu(0, array('projectmodel', 'createManageLink'), 0, 'list'); $this->view->programs = array('0' => '') + $this->program->getParentPairs(); $this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst|nodeleted'); $this->view->usersAvatar = $this->user->getAvatarPairs(); $this->view->browseType = $browseType; $this->view->projectType = $projectType; $this->view->param = $param; $this->view->orderBy = $orderBy; $this->view->recTotal = $recTotal; $this->view->recPerPage = $recPerPage; $this->view->pageID = $pageID; $this->display(); } /** * Project kanban. * * @access public * @return void */ public function kanban() { extract($this->project->getStats4Kanban()); $this->view->title = $this->lang->project->kanban; $this->view->kanbanGroup = array_filter($kanbanGroup); $this->view->latestExecutions = $latestExecutions; $this->view->programPairs = array(0 => $this->lang->project->noProgram) + $this->loadModel('program')->getPairs(true, 'order_asc'); $this->display(); } /** * Set module display mode. * * @access public * @return void */ public function programTitle() { $this->loadModel('setting'); if($_POST) { $programTitle = $this->post->programTitle; $this->setting->setItem($this->app->user->account . '.project.programTitle', $programTitle); die(js::reload('parent.parent')); } $status = $this->setting->getItem('owner=' . $this->app->user->account . '&module=project&key=programTitle'); $this->view->status = empty($status) ? '0' : $status; $this->display(); } /** * Create a project. * * @param string $model * @param int $programID * @param int $copyProjectID * @param string $extra * @access public * @return void */ public function create($model = 'scrum', $programID = 0, $copyProjectID = 0, $extra = '') { $this->loadModel('execution'); $this->loadModel('product'); if($_POST) { $projectID = $this->project->create(); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); $this->loadModel('action')->create('project', $projectID, 'opened'); /* Link the plan stories. */ if(!empty($_POST['plans'])) { $planIdList = array(); foreach($_POST['plans'] as $plans) { foreach($plans as $planID) $planIdList[$planID] = $planID; } $planStoryGroup = $this->loadModel('story')->getStoriesByPlanIdList($planIdList); foreach($planIdList as $planID) { $planStories = $planProducts = array(); $planStory = isset($planStoryGroup[$planID]) ? $planStoryGroup[$planID] : array(); if(!empty($planStory)) { foreach($planStory as $id => $story) { if($story->status == 'draft') { unset($planStory[$id]); continue; } $planProducts[$story->id] = $story->product; } $planStories = array_keys($planStory); $this->execution->linkStory($projectID, $planStories, $planProducts); } } } if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $projectID)); if($this->app->tab == 'program') { return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('program', 'browse'))); } elseif($this->app->tab == 'doc') { return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('doc', 'objectLibs', "type=project&objectID=$projectID"))); } else { if($model == 'waterfall') { $productID = $this->product->getProductIDByProject($projectID, true); $this->session->set('projectPlanList', $this->createLink('programplan', 'browse', "projectID=$projectID&productID=$productID&type=lists", '', '', $projectID), 'project'); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('programplan', 'create', "projectID=$projectID", '', '', $projectID))); } $parent = isset($_POST['parent']) ? $_POST['parent'] : 0; return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('project', 'browse', "programID=$parent&browseType=all", '', '', $projectID))); } } if($this->app->tab == 'program') $this->loadModel('program')->setMenu($programID); $this->session->set('projectModel', $model); $extra = str_replace(array(',', ' '), array('&', ''), $extra); parse_str($extra, $output); $name = ''; $code = ''; $team = ''; $whitelist = ''; $acl = 'private'; $auth = 'extend'; $products = array(); $productPlans = array(); $parentProgram = $this->loadModel('program')->getByID($programID); if($copyProjectID) { $copyProject = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($copyProjectID)->fetch(); $name = $copyProject->name; $code = $copyProject->code; $team = $copyProject->team; $acl = $copyProject->acl; $auth = $copyProject->auth; $whitelist = $copyProject->whitelist; $programID = $copyProject->parent; $model = $copyProject->model; $products = $this->product->getProducts($copyProjectID); foreach($products as $product) { $productPlans[$product->id] = $this->loadModel('productplan')->getPairs($product->id); } } if($this->app->tab == 'doc') unset($this->lang->doc->menu->project['subMenu']); $topProgramID = $this->program->getTopByID($programID); $this->view->title = $this->lang->project->create; $this->view->position[] = $this->lang->project->create; $this->view->gobackLink = (isset($output['from']) and $output['from'] == 'global') ? $this->createLink('project', 'browse') : ''; $this->view->pmUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst'); $this->view->users = $this->user->getPairs('noclosed|nodeleted'); $this->view->copyProjects = $this->project->getPairsByModel(); $this->view->products = $products; $this->view->allProducts = array('0' => '') + $this->program->getProductPairs($programID, 'assign', 'noclosed'); $this->view->productPlans = array('0' => '') + $productPlans; $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), 'noclosed'); $this->view->programID = $programID; $this->view->multiBranchProducts = $this->product->getMultiBranchPairs($topProgramID); $this->view->model = $model; $this->view->name = $name; $this->view->code = $code; $this->view->team = $team; $this->view->acl = $acl; $this->view->auth = $auth; $this->view->whitelist = $whitelist; $this->view->copyProjectID = $copyProjectID; $this->view->programList = $this->program->getParentPairs(); $this->view->parentProgram = $parentProgram; $this->view->URSRPairs = $this->loadModel('custom')->getURSRPairs(); $this->view->availableBudget = $this->program->getBudgetLeft($parentProgram); $this->view->budgetUnitList = $this->program->getBudgetUnitList(); $this->display(); } /** * Edit a project. * * @param int $projectID * @param string $from * @access public * @return void */ public function edit($projectID = 0, $from = '') { $this->loadModel('action'); $this->loadModel('custom'); $this->loadModel('productplan'); $this->loadModel('user'); $this->loadModel('program'); $this->loadModel('execution'); $project = $this->project->getByID($projectID); $programID = $project->parent; $this->project->setMenu($projectID); if($_POST) { $oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->andWhere('plan')->ne(0)->fetchPairs('plan'); $changes = $this->project->update($projectID); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); if($changes) { $actionID = $this->action->create('project', $projectID, 'edited'); $this->action->logHistory($actionID, $changes); } /* Link the plan stories. */ $newPlans = array(); if(isset($_POST['plans'])) { foreach($_POST['plans'] as $plans) { foreach($plans as $planID) $newPlans[$planID] = $planID; } } $diffResult = array_diff($oldPlans, $newPlans); if(!empty($newPlans) and !empty($diffResult)) { $this->loadModel('productplan')->linkProject($projectID, $newPlans); } if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); $locateLink = ($this->session->projectList and $from != 'view') ? $this->session->projectList : inLink('view', "projectID=$projectID"); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locateLink)); } $linkedBranches = array(); $productPlans = array(0 => ''); $allProducts = $this->program->getProductPairs($project->parent, 'assign', 'noclosed'); $linkedProducts = $this->loadModel('product')->getProducts($projectID); $parentProject = $this->program->getByID($project->parent); $branches = $this->project->getBranchesByProject($projectID); $plans = $this->productplan->getGroupByProduct(array_keys($linkedProducts), 'skipParent'); $projectStories = $this->project->getStoriesByProject($projectID); $projectBranches = $this->project->getBranchGroupByProject($projectID, array_keys($linkedProducts)); /* If the story of the product which linked the project, you don't allow to remove the product. */ $unmodifiableProducts = array(); $unmodifiableBranches = array(); $unmodifiableMainBranches = array(); foreach($linkedProducts as $productID => $linkedProduct) { if(!isset($allProducts[$productID])) $allProducts[$productID] = $linkedProduct->name; foreach($branches[$productID] as $branchID => $branch) { $linkedBranches[$productID][$branchID] = $branchID; if($branch != BRANCH_MAIN) $productPlans[$productID][$branchID] = isset($plans[$productID][BRANCH_MAIN]) ? $plans[$productID][BRANCH_MAIN] : array(); $productPlans[$productID][$branchID] += isset($plans[$productID][$branchID]) ? $plans[$productID][$branchID] : array(); if(!empty($projectStories[$productID][$branchID]) or !empty($projectBranches[$productID][$branchID])) { if($branchID == BRANCH_MAIN) $unmodifiableMainBranches[$productID] = $branchID; array_push($unmodifiableProducts, $productID); array_push($unmodifiableBranches, $branchID); } } } $this->view->title = $this->lang->project->edit; $this->view->position[] = $this->lang->project->edit; $this->view->PMUsers = $this->user->getPairs('noclosed|nodeleted|pmfirst', $project->PM); $this->view->users = $this->user->getPairs('noclosed|nodeleted'); $this->view->project = $project; $this->view->programList = $this->program->getParentPairs(); $this->view->program = $this->program->getByID($project->parent); $this->view->projectID = $projectID; $this->view->allProducts = array('0' => '') + $allProducts; $this->view->multiBranchProducts = $this->loadModel('product')->getMultiBranchPairs(); $this->view->productPlans = array_filter($productPlans); $this->view->linkedProducts = $linkedProducts; $this->view->linkedBranches = $linkedBranches; $this->view->branches = $branches; $this->view->unmodifiableProducts = $unmodifiableProducts; $this->view->unmodifiableBranches = $unmodifiableBranches; $this->view->unmodifiableMainBranches = $unmodifiableMainBranches; $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($linkedProducts), 'noclosed'); $this->view->URSRPairs = $this->custom->getURSRPairs(); $this->view->parentProject = $parentProject; $this->view->parentProgram = $this->program->getByID($project->parent); $this->view->availableBudget = $this->program->getBudgetLeft($parentProject) + (float)$project->budget; $this->view->budgetUnitList = $this->project->getBudgetUnitList(); $this->display(); } /** * Batch edit projects. * * @param string $from * @param int $projectID * @access public * @return void */ public function batchEdit($from = 'browse', $projectID = 0) { $this->loadModel('action'); $this->loadModel('execution'); if($this->post->names) { $allChanges = $this->project->batchUpdate(); if(!empty($allChanges)) { foreach($allChanges as $projectID => $changes) { if(empty($changes)) continue; $actionID = $this->action->create('project', $projectID, 'Edited'); $this->action->logHistory($actionID, $changes); } } die(js::locate($this->session->projectList, 'parent')); } if($this->app->tab == 'program') $this->loadModel('program')->setMenu(0); $projectIdList = $this->post->projectIdList ? $this->post->projectIdList : die(js::locate($this->session->projectList, 'parent')); $projects = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->in($projectIdList)->fetchAll('id'); /* Get program list. */ $programs = $this->loadModel('program')->getParentPairs(); $unauthorizedIDList = array(); foreach($projects as $project) { if(!isset($programs[$project->parent]) and !in_array($project->parent, $unauthorizedIDList)) $unauthorizedIDList[] = $project->parent; $appendPMUsers[$project->PM] = $project->PM; } $unauthorizedPrograms = $this->program->getPairsByList($unauthorizedIDList); $this->view->title = $this->lang->project->batchEdit; $this->view->position[] = $this->lang->project->batchEdit; $this->view->projects = $projects; $this->view->programs = $programs; $this->view->unauthorizedPrograms = $unauthorizedPrograms; $this->view->PMUsers = $this->loadModel('user')->getPairs('noclosed|nodeleted|pmfirst', $appendPMUsers); $this->display(); } /** * View a project. * * @param int $projectID * @access public * @return void */ public function view($projectID = 0) { if(!defined('RUN_MODE') || RUN_MODE != 'api') $projectID = $this->project->saveState((int)$projectID, $this->project->getPairsByProgram()); $project = $this->project->getById($projectID); if(empty($project) || strpos('scrum,waterfall', $project->model) === false) { if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'code' => 404, 'message' => '404 Not found')); die(js::error($this->lang->notFound) . js::locate($this->createLink('project', 'browse'))); } $this->project->setMenu($projectID); $products = $this->loadModel('product')->getProducts($projectID); $linkedBranches = array(); foreach($products as $product) { if(isset($product->branches)) { foreach($product->branches as $branchID) $linkedBranches[$branchID] = $branchID; } } /* Load pager. */ $this->app->loadClass('pager', $static = true); $pager = new pager(0, 30, 1); $this->view->title = $this->lang->project->view; $this->view->position = $this->lang->project->view; $this->view->projectID = $projectID; $this->view->project = $project; $this->view->products = $products; $this->view->actions = $this->loadModel('action')->getList('project', $projectID); $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->view->teamMembers = $this->project->getTeamMembers($projectID); $this->view->statData = $this->project->getStatData($projectID); $this->view->workhour = $this->project->getWorkhour($projectID); $this->view->planGroup = $this->loadModel('execution')->getPlans($products); $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), '', $linkedBranches); $this->view->dynamics = $this->loadModel('action')->getDynamic('all', 'all', 'date_desc', $pager, 'all', $projectID); $this->display(); } /** * Project browse groups. * * @param int $projectID * @param int $programID * @access public * @return void */ public function group($projectID = 0, $programID = 0) { $this->loadModel('group'); $this->project->setMenu($projectID); $title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->browse; $position[] = $this->lang->group->browse; $groups = $this->group->getList($projectID); $groupUsers = array(); foreach($groups as $group) $groupUsers[$group->id] = $this->group->getUserPairs($group->id); $this->view->title = $title; $this->view->position = $position; $this->view->groups = $groups; $this->view->project = $this->dao->findById($projectID)->from(TABLE_PROJECT)->fetch(); $this->view->projectID = $projectID; $this->view->programID = $programID; $this->view->groupUsers = $groupUsers; $this->display(); } /** * Project create a group. * * @param int $projectID * @access public * @return void */ public function createGroup($projectID = 0) { $this->loadModel('group'); if(!empty($_POST)) { $_POST['project'] = $projectID; $groupID = $this->group->create(); if(dao::isError()) die(js::error(dao::getError())); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $groupID)); die(js::closeModal('parent.parent')); } $this->view->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->create; $this->view->position[] = $this->lang->group->create; $this->display('group', 'create'); } /** * Project dynamic. * * @param int $projectID * @param string $type * @param string $param * @param int $recTotal * @param string $date * @param string $direction next|pre * @access public * @return void */ public function dynamic($projectID = 0, $type = 'today', $param = '', $recTotal = 0, $date = '', $direction = 'next') { $this->project->setMenu($projectID); /* Save session. */ $uri = $this->app->getURI(true); $this->session->set('productList', $uri, 'product'); $this->session->set('productPlanList', $uri, 'product'); $this->session->set('releaseList', $uri, 'product'); $this->session->set('storyList', $uri, 'product'); $this->session->set('taskList', $uri, 'execution'); $this->session->set('buildList', $uri, 'execution'); $this->session->set('bugList', $uri, 'qa'); $this->session->set('caseList', $uri, 'qa'); $this->session->set('testtaskList', $uri, 'qa'); $this->session->set('reportList', $uri, 'qa'); if(isset($this->config->maxVersion)) { $this->session->set('riskList', $uri, 'project'); $this->session->set('issueList', $uri, 'project'); } /* Append id for secend sort. */ $orderBy = $direction == 'next' ? 'date_desc' : 'date_asc'; $sort = $this->loadModel('common')->appendOrder($orderBy); /* Set the pager. */ $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage = 50, $pageID = 1); /* Set the user and type. */ $account = 'all'; if($type == 'account') { $user = $this->loadModel('user')->getById($param, 'account'); if($user) $account = $user->account; } $period = $type == 'account' ? 'all' : $type; $date = empty($date) ? '' : date('Y-m-d', $date); $actions = $this->loadModel('action')->getDynamic($account, $period, $sort, $pager, 'all', $projectID, 'all', $date, $direction); /* The header and position. */ $project = $this->project->getByID($projectID); $this->view->title = $project->name . $this->lang->colon . $this->lang->project->dynamic; $this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); $this->view->position[] = $this->lang->project->dynamic; $this->view->userIdPairs = $this->loadModel('user')->getTeamMemberPairs($projectID, 'project'); $this->view->accountPairs = $this->user->getPairs('noletter|nodeleted'); /* Assign. */ $this->view->projectID = $projectID; $this->view->type = $type; $this->view->orderBy = $orderBy; $this->view->pager = $pager; $this->view->account = $account; $this->view->param = $param; $this->view->dateGroups = $this->action->buildDateGroup($actions, $direction, $type); $this->view->direction = $direction; $this->display(); } /** * Execution list. * * @param string $status * @param int $projectID * @param string $orderBy * @param int $productID * @param int $recTotal * @param int $recPerPage * @param int $pageID * @access public * @return void */ public function execution($status = 'all', $projectID = 0, $orderBy = 'order_asc', $productID = 0, $recTotal = 0, $recPerPage = 10, $pageID = 1) { $uri = $this->app->getURI(true); $this->app->session->set('executionList', $uri, 'project'); echo $this->fetch('execution', 'all', "status=$status&projectID=$projectID&orderBy=$orderBy&productID=$productID&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID"); } /** * Project qa dashboard. * * @param int $projectID * @access public * @return void */ public function qa($projectID = 0) { $this->project->setMenu($projectID); $this->view->title = $this->lang->project->qa; $this->display(); } /** * Project bug list. * * @param int $projectID * @param int $productID * @param string $orderBy * @param int $build * @param string $type * @param int $param * @param int $recTotal * @param int $recPerPage * @param int $pageID * @access public * @return void */ public function bug($projectID = 0, $productID = 0, $orderBy = 'status,id_desc', $build = 0, $type = 'all', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1) { /* Load these two models. */ $this->loadModel('bug'); $this->loadModel('user'); $this->loadModel('product'); /* Save session. */ $this->session->set('bugList', $this->app->getURI(true), 'project'); $this->project->setMenu($projectID); $project = $this->project->getByID($projectID); $type = strtolower($type); $queryID = ($type == 'bysearch') ? (int)$param : 0; $products = $this->product->getProducts($projectID); $branchID = isset($products[$productID]) ? current($products[$productID]->branches) : 0; $productPairs = array('0' => $this->lang->product->all); foreach($products as $product) $productPairs[$product->id] = $product->name; $this->lang->modulePageNav = $this->product->select($productPairs, $productID, 'project', 'bug', '', $branchID, 0, '', false); /* Header and position. */ $title = $project->name . $this->lang->colon . $this->lang->bug->common; $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); $position[] = $this->lang->bug->common; /* Load pager and get bugs, user. */ $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage, $pageID); $sort = $this->loadModel('common')->appendOrder($orderBy); $bugs = $this->bug->getProjectBugs($projectID, $productID, $build, $type, $param, $sort, '', $pager); $users = $this->user->getPairs('noletter'); /* team member pairs. */ $memberPairs = array(); $memberPairs[] = ""; $teamMembers = $this->project->getTeamMembers($projectID); foreach($teamMembers as $key => $member) $memberPairs[$key] = $member->realname; /* Build the search form. */ $actionURL = $this->createLink('project', 'bug', "projectID=$projectID&productID=$productID&orderBy=$orderBy&build=$build&type=bysearch&queryID=myQueryID"); $this->loadModel('execution')->buildBugSearchForm($products, $queryID, $actionURL, 'project'); /* Assign. */ $this->view->title = $title; $this->view->position = $position; $this->view->bugs = $bugs; $this->view->tabID = 'bug'; $this->view->build = $this->loadModel('build')->getById($build); $this->view->buildID = $this->view->build ? $this->view->build->id : 0; $this->view->pager = $pager; $this->view->orderBy = $orderBy; $this->view->users = $users; $this->view->productID = $productID; $this->view->project = $this->project->getById($projectID); $this->view->branchID = empty($this->view->build->branch) ? $branchID : $this->view->build->branch; $this->view->memberPairs = $memberPairs; $this->view->type = $type; $this->view->param = $param; $this->display(); } /** * Project case list. * * @param int $projectID * @param int $productID * @param string|int $branch * @param string $browseType * @param int $param * @param string $orderBy * @param int $recTotal * @param int $recPerPage * @param int $pageID * @access public * @return void */ public function testcase($projectID = 0, $productID = 0, $branch = 'all', $browseType = 'all', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { $this->loadModel('product'); $this->session->set('bugList', $this->app->getURI(true), 'project'); $products = array('0' => $this->lang->product->all) + $this->product->getProducts($projectID, 'all', '', false); $extra = "$projectID|$browseType"; $this->lang->modulePageNav = $this->product->select($products, $productID, 'project', 'testcase', $extra, $branch, 0, '', false); echo $this->fetch('testcase', 'browse', "productID=$productID&branch=$branch&browseType=$browseType¶m=$param&orderBy=$orderBy&recTotal=$orderBy&recPerPage=$recPerPage&pageID=$pageID&projectID=$projectID"); } /** * List of test reports for the project. * * @param int $projectID * @param string $objectType project|execution|product * @param string $extra * @param string $orderBy * @param int $recTotal * @param int $recPerPage * @param int $pageID * @access public * @return void */ public function testreport($projectID = 0, $objectType = 'project', $extra = '', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { echo $this->fetch('testreport', 'browse', "objectID=$projectID&objectType=$objectType&extra=$extra&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID"); } /** * Project test task list. * * @param int $projectID * @param string $orderBy * @param int $recTotal * @param int $recPerPage * @param int $pageID * @access public * @return void */ public function testtask($projectID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { $this->loadModel('testtask'); $this->app->loadLang('testreport'); /* Save session. */ $this->session->set('testtaskList', $this->app->getURI(true), 'qa'); $this->session->set('buildList', $this->app->getURI(true), 'execution'); $this->project->setMenu($projectID); /* Load pager. */ $this->app->loadClass('pager', $static = true); $pager = pager::init($recTotal, $recPerPage, $pageID); $productTasks = array(); $project = $this->project->getByID($projectID); $tasks = $this->testtask->getProjectTasks($projectID, $orderBy, $pager); foreach($tasks as $key => $task) $productTasks[$task->product][] = $task; $this->view->title = $project->name . $this->lang->colon . $this->lang->project->common; $this->view->position[] = html::a($this->createLink('project', 'testtask', "projectID=$projectID"), $project->name); $this->view->position[] = $this->lang->testtask->common; $this->view->project = $project; $this->view->projectID = $projectID; $this->view->projectName = $project->name; $this->view->pager = $pager; $this->view->orderBy = $orderBy; $this->view->tasks = $productTasks; $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); $this->view->products = $this->loadModel('product')->getPairs('', 0); $this->view->canBeChanged = common::canModify('project', $project); // Determines whether an object is editable. $this->display(); } /** * Browse builds of a project. * * @param int $projectID * @param string $type all|product|bysearch * @param int $param * @param string $orderBy * @access public * @return void */ public function build($projectID = 0, $type = 'all', $param = 0, $orderBy = 't1.date_desc,t1.id_desc') { /* Load module and get project. */ $this->loadModel('build'); $this->loadModel('product'); $project = $this->project->getByID($projectID); $this->project->setMenu($projectID); $this->session->set('buildList', $this->app->getURI(true), 'project'); /* Get products' list. */ $products = $this->product->getProducts($projectID, 'all', '', false); $products = array('' => '') + $products; /* Build the search form. */ $type = strtolower($type); $queryID = ($type == 'bysearch') ? (int)$param : 0; $actionURL = $this->createLink('project', 'build', "projectID=$projectID&type=bysearch&queryID=myQueryID"); $executions = $this->loadModel('execution')->getByProject($projectID, 'all', '', true); $this->config->build->search['fields']['execution'] = $this->project->lang->executionCommon; $this->config->build->search['params']['execution'] = array('operator' => '=', 'control' => 'select', 'values' => array('' => '') + $executions); $product = $param ? $this->loadModel('product')->getById($param) : ''; if($product and $product->type != 'normal') { $this->loadModel('build'); $this->loadModel('branch'); $branches = array(BRANCH_MAIN => $this->lang->branch->main) + $this->branch->getPairs($product->id, '', $projectID); $this->config->build->search['fields']['branch'] = sprintf($this->lang->build->branchName, $this->lang->product->branchName[$product->type]); $this->config->build->search['params']['branch'] = array('operator' => '=', 'control' => 'select', 'values' => $branches); } $this->project->buildProjectBuildSearchForm($products, $queryID, $actionURL, 'project'); if($type == 'bysearch') { $builds = $this->build->getProjectBuildsBySearch((int)$projectID, (int)$param, $orderBy); } else { $builds = $this->build->getProjectBuilds((int)$projectID, $type, $param, $orderBy); } /* Set project builds. */ $projectBuilds = array(); $productList = $this->product->getProducts($projectID); $this->app->loadLang('branch'); if(!empty($builds)) { foreach($builds as $build) { /* If product is normal, unset branch name. */ if(isset($productList[$build->product]) and $productList[$build->product]->type == 'normal') { $build->branchName = ''; } else { $build->branchName = isset($build->branchName) ? $build->branchName : $this->lang->branch->main; } $projectBuilds[$build->product][] = $build; } } /* Header and position. */ $this->view->title = $project->name . $this->lang->colon . $this->lang->execution->build; $this->view->position[] = $this->lang->execution->build; $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->view->buildsTotal = count($builds); $this->view->projectBuilds = $projectBuilds; $this->view->product = $type == 'product' ? $param : 'all'; $this->view->projectID = $projectID; $this->view->project = $project; $this->view->products = $products; $this->view->executions = $executions; $this->view->type = $type; $this->display(); } /** * Manage privleges of a group. * * @param int $projectID * @param string $type * @param int $param * @param string $menu * @param string $version * @access public * @return void */ public function managePriv($projectID, $type = 'byGroup', $param = 0, $menu = '', $version = '') { $this->loadModel('group'); if($type == 'byGroup') { $groupID = $param; $group = $this->group->getById($groupID); } $this->view->type = $type; foreach($this->lang->resource as $moduleName => $action) { if($this->group->checkMenuModule($menu, $moduleName) or $type != 'byGroup') $this->app->loadLang($moduleName); } if(!empty($_POST)) { if($type == 'byGroup') $result = $this->group->updatePrivByGroup($groupID, $menu, $version); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('group', "projectID=$group->project"))); } $this->project->setMenu($projectID); if($type == 'byGroup') { $this->group->sortResource(); $groupPrivs = $this->group->getPrivs($groupID); $this->view->title = $group->name . $this->lang->colon . $this->lang->group->managePriv; $this->view->position[] = $group->name; $this->view->position[] = $this->lang->group->managePriv; /* Join changelog when be equal or greater than this version.*/ $realVersion = str_replace('_', '.', $version); $changelog = array(); foreach($this->lang->changelog as $currentVersion => $currentChangeLog) { if(version_compare($currentVersion, $realVersion, '>=')) $changelog[] = join(',', $currentChangeLog); } $this->view->group = $group; $this->view->changelogs = ',' . join(',', $changelog) . ','; $this->view->groupPrivs = $groupPrivs; $this->view->groupID = $groupID; $this->view->projectID = $projectID; $this->view->menu = $menu; $this->view->version = $version; /* Unset not project privs. */ $project = $this->project->getByID($group->project); foreach($this->lang->resource as $module => $methods) { if(!in_array($module, $this->config->programPriv->{$project->model})) { unset($this->lang->resource->$module); } else { if($project->model == 'scrum' and $module == 'projectstory') $this->config->project->removePriv[$module][] = 'track'; foreach($methods as $method => $label) { if(isset($this->config->project->removePriv[$module]) and in_array($method, $this->config->project->removePriv[$module])) unset($this->lang->resource->$module->$method); } } } } $this->display(); } /** * Browse team of a project. * * @param int $projectID * @access public * @return void */ public function team($projectID = 0) { $this->app->loadLang('execution'); $this->project->setMenu($projectID); $project = $this->project->getById($projectID); $this->view->title = $project->name . $this->lang->colon . $this->lang->project->team; $this->view->projectID = $projectID; $this->view->teamMembers = $this->project->getTeamMembers($projectID); $this->view->deptUsers = $this->loadModel('dept')->getDeptUserPairs($this->app->user->dept, 'id'); $this->view->canBeChanged = common::canModify('project', $project); $this->display(); } /** * Unlink a memeber. * * @param int $projectID * @param int $userID * @param string $confirm yes|no * @param string $removeExecution yes|no * @access public * @return void */ public function unlinkMember($projectID, $userID, $confirm = 'no', $removeExecution = 'no') { if($confirm == 'no') die(js::confirm($this->lang->project->confirmUnlinkMember, $this->inlink('unlinkMember', "projectID=$projectID&userID=$userID&confirm=yes"))); $user = $this->loadModel('user')->getById($userID, 'id'); $account = $user->account; $this->project->unlinkMember($projectID, $account, $removeExecution); if(!dao::isError()) $this->loadModel('action')->create('team', $projectID, 'managedTeam'); /* if ajax request, send result. */ if($this->server->ajax) { if(dao::isError()) { $response['result'] = 'fail'; $response['message'] = dao::getError(); } else { $response['result'] = 'success'; $response['message'] = ''; } return $this->send($response); } die(js::locate($this->inlink('team', "projectID=$projectID"), 'parent')); } /** * Manage project members. * * @param int $projectID * @param int $dept * @param int $copyProjectID * @access public * @return void */ public function manageMembers($projectID, $dept = '', $copyProjectID = 0) { /* Load model. */ $this->loadModel('user'); $this->loadModel('dept'); $this->loadModel('execution'); $this->project->setMenu($projectID); if(!empty($_POST)) { $this->project->manageMembers($projectID); $this->loadModel('action')->create('team', $projectID, 'ManagedTeam'); $link = $this->createLink('project', 'team', "projectID=$projectID"); return $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'locate' => $link)); } $project = $this->project->getById($projectID); $users = $this->user->getPairs('noclosed|nodeleted|devfirst|nofeedback'); $roles = $this->user->getUserRoles(array_keys($users)); $deptUsers = $dept === '' ? array() : $this->dept->getDeptUserPairs($dept); $currentMembers = $this->project->getTeamMembers($projectID); $members2Import = $this->project->getMembers2Import($copyProjectID, array_keys($currentMembers)); $this->view->title = $this->lang->project->manageMembers . $this->lang->colon . $project->name; $this->view->position[] = $this->lang->project->manageMembers; $this->view->project = $project; $this->view->users = $users; $this->view->deptUsers = $deptUsers; $this->view->roles = $roles; $this->view->dept = $dept; $this->view->depts = array('' => '') + $this->dept->getOptionMenu(); $this->view->currentMembers = $currentMembers; $this->view->members2Import = $members2Import; $this->view->teams2Import = array('' => '') + $this->loadModel('personnel')->getCopiedObjects($projectID, 'project'); $this->view->copyProjectID = $copyProjectID; $this->display(); } /** * Manage members of a group. * * @param int $groupID * @param int $deptID * @access public * @return void */ public function manageGroupMember($groupID, $deptID = 0) { $this->loadModel('group'); if(!empty($_POST)) { $this->group->updateUser($groupID); if(isonlybody()) die(js::closeModal('parent.parent', 'this')); die(js::locate($this->createLink('group', 'browse'), 'parent')); } $group = $this->group->getById($groupID); $groupUsers = $this->group->getUserPairs($groupID); $allUsers = $this->loadModel('dept')->getDeptUserPairs($deptID); $otherUsers = array_diff_assoc($allUsers, $groupUsers); if($this->config->systemMode == 'new') { $outsideUsers = $this->loadModel('user')->getPairs('outside|noclosed|noletter|noempty'); $this->view->outsideUsers = array_diff_assoc($outsideUsers, $groupUsers); } $title = $group->name . $this->lang->colon . $this->lang->group->manageMember; $position[] = $group->name; $position[] = $this->lang->group->manageMember; $this->view->title = $title; $this->view->position = $position; $this->view->group = $group; $this->view->deptTree = $this->loadModel('dept')->getTreeMenu($rooteDeptID = 0, array('deptModel', 'createGroupManageMemberLink'), $groupID); $this->view->groupUsers = $groupUsers; $this->view->otherUsers = $otherUsers; $this->display('group', 'manageMember'); } /** * Project copy a group. * * @param int $groupID * @access public * @return void */ public function copyGroup($groupID) { $this->loadModel('group'); if(!empty($_POST)) { $group = $this->group->getByID($groupID); $_POST['project'] = $group->project; $this->group->copy($groupID); if(dao::isError()) die(js::error(dao::getError())); die(js::closeModal('parent.parent', 'this')); } $this->view->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->copy; $this->view->position[] = $this->lang->group->copy; $this->view->group = $this->group->getById($groupID); $this->display('group', 'copy'); } /** * Project edit a group. * * @param int $groupID * @access public * @return void */ public function editGroup($groupID) { $this->loadModel('group'); if(!empty($_POST)) { $this->group->update($groupID); die(js::closeModal('parent.parent', 'this')); } $this->view->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->edit; $this->view->position[] = $this->lang->group->edit; $this->view->group = $this->group->getById($groupID); $this->display('group', 'edit'); } /** * Start project. * * @param int $projectID * @access public * @return void */ public function start($projectID) { $this->loadModel('action'); $project = $this->project->getByID($projectID); if(!empty($_POST)) { $changes = $this->project->start($projectID); if(dao::isError()) die(js::error(dao::getError())); if($this->post->comment != '' or !empty($changes)) { $actionID = $this->action->create('project', $projectID, 'Started', $this->post->comment); $this->action->logHistory($actionID, $changes); } /* Start all superior projects. */ if($project->parent) { $path = explode(',', $project->path); $path = array_filter($path); foreach($path as $projectID) { if($projectID == $projectID) continue; $project = $this->project->getPGMByID($projectID); if($project->status == 'wait' || $project->status == 'suspended') { $changes = $this->project->start($projectID); if(dao::isError()) die(js::error(dao::getError())); if($this->post->comment != '' or !empty($changes)) { $actionID = $this->action->create('project', $projectID, 'Started', $this->post->comment); $this->action->logHistory($actionID, $changes); } } } } $this->loadModel('common')->syncPPEStatus($projectID); $this->executeHooks($projectID); die(js::reload('parent.parent')); } $this->view->title = $this->lang->project->start; $this->view->position[] = $this->lang->project->start; $this->view->project = $project; $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->view->actions = $this->action->getList('project', $projectID); $this->display(); } /** * Suspend a project. * * @param int $projectID * @access public * @return void */ public function suspend($projectID) { $this->loadModel('action'); if(!empty($_POST)) { $changes = $this->project->suspend($projectID); if(dao::isError()) die(js::error(dao::getError())); if($this->post->comment != '' or !empty($changes)) { $actionID = $this->action->create('project', $projectID, 'Suspended', $this->post->comment); $this->action->logHistory($actionID, $changes); } $this->executeHooks($projectID); die(js::reload('parent.parent')); } $this->view->title = $this->lang->project->suspend; $this->view->position[] = $this->lang->project->suspend; $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->view->actions = $this->action->getList('project', $projectID); $this->view->project = $this->project->getByID($projectID); $this->display(); } /** * Close a project. * * @param int $projectID * @access public * @return void */ public function close($projectID) { $this->loadModel('action'); if(!empty($_POST)) { $changes = $this->project->close($projectID); if(dao::isError()) die(js::error(dao::getError())); if($this->post->comment != '' or !empty($changes)) { $actionID = $this->action->create('project', $projectID, 'Closed', $this->post->comment); $this->action->logHistory($actionID, $changes); } $this->executeHooks($projectID); die(js::reload('parent.parent')); } $this->view->title = $this->lang->project->close; $this->view->position[] = $this->lang->project->close; $this->view->project = $this->project->getByID($projectID); $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->view->actions = $this->action->getList('project', $projectID); $this->display(); } /** * Activate a project. * * @param int $projectID * @access public * @return void */ public function activate($projectID) { $this->loadModel('action'); $this->app->loadLang('execution'); $project = $this->project->getByID($projectID); if(!empty($_POST)) { $changes = $this->project->activate($projectID); if(dao::isError()) die(js::error(dao::getError())); if($this->post->comment != '' or !empty($changes)) { $actionID = $this->action->create('project', $projectID, 'Activated', $this->post->comment); $this->action->logHistory($actionID, $changes); } $this->executeHooks($projectID); die(js::reload('parent.parent')); } $newBegin = date('Y-m-d'); $dateDiff = helper::diffDate($newBegin, $project->begin); $newEnd = date('Y-m-d', strtotime($project->end) + $dateDiff * 24 * 3600); $this->view->title = $this->lang->project->activate; $this->view->position[] = $this->lang->project->activate; $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->view->actions = $this->action->getList('project', $projectID); $this->view->newBegin = $newBegin; $this->view->newEnd = $newEnd; $this->view->project = $project; $this->display(); } /** * Delete a project. * * @param int $projectID * @param string $from * @access public * @return void */ public function delete($projectID, $confirm = 'no') { if($confirm == 'no') { $project = $this->project->getByID($projectID); echo js::confirm(sprintf($this->lang->project->confirmDelete, $project->name), $this->createLink('project', 'delete', "projectID=$projectID&confirm=yes")); die(); } else { $this->loadModel('user'); $this->loadModel('action'); $this->project->delete(TABLE_PROJECT, $projectID); $this->dao->update(TABLE_DOCLIB)->set('deleted')->eq(1)->where('execution')->eq($projectID)->exec(); $this->user->updateUserView($projectID, 'project'); /* Delete the execution under the project. */ $executionIdList = $this->loadModel('execution')->getByProject($projectID); $url = $this->createLink('project', 'browse'); if($this->app->tab == 'program') $url = $this->createLink('program', 'browse'); if(empty($executionIdList)) { if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess)); die(js::locate($url, 'parent')); } $this->dao->update(TABLE_EXECUTION)->set('deleted')->eq(1)->where('id')->in(array_keys($executionIdList))->exec(); foreach($executionIdList as $executionID => $execution) $this->action->create('execution', $executionID, 'deleted', '', ACTIONMODEL::CAN_UNDELETED); $this->user->updateUserView($executionIdList, 'sprint'); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess)); $this->session->set('project', ''); die(js::locate($url, 'parent')); } } /** * Update projects order. * * @access public * @return void */ public function updateOrder() { $idList = explode(',', trim($this->post->projects, ',')); $orderBy = $this->post->orderBy; if(strpos($orderBy, 'order') === false) return false; $projects = $this->dao->select('id,`order`')->from(TABLE_PROJECT)->where('id')->in($idList)->orderBy($orderBy)->fetchPairs('order', 'id'); foreach($projects as $order => $id) { $newID = array_shift($idList); if($id == $newID) continue; $this->dao->update(TABLE_PROJECT) ->set('`order`')->eq($order) ->set('lastEditedBy')->eq($this->app->user->account) ->set('lastEditedDate')->eq(helper::now()) ->where('id')->eq($newID) ->exec(); } } /** * Get white list personnel. * * @param int $projectID * @param string $module * @param string $from project|program|programProject * @param string $objectType * @param string $orderby * @param int $recTotal * @param int $recPerPage * @param int $pageID * @access public * @return void */ public function whitelist($projectID = 0, $module = 'project', $from = 'project', $objectType = 'project', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { echo $this->fetch('personnel', 'whitelist', "objectID=$projectID&module=$module&browseType=$objectType&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&projectID=$projectID&from=$from"); } /** * Adding users to the white list. * * @param int $projectID * @param int $deptID * @param int $copyID * @param int $programID * @param int $from * @access public * @return void */ public function addWhitelist($projectID = 0, $deptID = 0, $copyID = 0, $programID = 0, $from = 'project') { echo $this->fetch('personnel', 'addWhitelist', "objectID=$projectID&dept=$deptID©ID=$copyID&objectType=project&module=project&programID=$programID&from=$from"); } /* * Removing users from the white list. * * @param int $id * @param string $confirm * @access public * @return void */ public function unbindWhitelist($id = 0, $confirm = 'no') { echo $this->fetch('personnel', 'unbindWhitelist', "id=$id&confirm=$confirm"); } /** * Manage products. * * @param int $projectID * @param string $from project|program|programproject * @access public * @return void */ public function manageProducts($projectID, $from = 'project') { $this->loadModel('product'); $this->loadModel('program'); if(!empty($_POST)) { if(!isset($_POST['products'])) { dao::$errors['message'][] = $this->lang->project->errorNoProducts; return $this->send(array('result' => 'fail', 'message' => dao::getError())); } $oldProducts = $this->product->getProducts($projectID); $this->project->updateProducts($projectID); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); $oldProducts = array_keys($oldProducts); $newProducts = $this->product->getProducts($projectID); $newProducts = array_keys($newProducts); $diffProducts = array_merge(array_diff($oldProducts, $newProducts), array_diff($newProducts, $oldProducts)); if($diffProducts) $this->loadModel('action')->create('project', $projectID, 'Managed', '', !empty($_POST['products']) ? join(',', $_POST['products']) : ''); $locateLink = inLink('manageProducts', "projectID=$projectID"); if($from == 'program') $locateLink = $this->createLink('program', 'browse'); if($from == 'programproject') $locateLink = $this->session->programProject ? $this->session->programProject : inLink('programProject', "projectID=$projectID"); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locateLink)); } $project = $this->project->getById($projectID); if($this->app->tab == 'program') { $this->program->setMenu($project->parent); } else if($this->app->tab == 'project') { $this->project->setMenu($projectID); } $linkedBranches = array(); $allProducts = $this->program->getProductPairs($project->parent, 'assign', 'noclosed'); $linkedProducts = $this->product->getProducts($projectID); $branches = $this->project->getBranchesByProject($projectID); $projectStories = $this->project->getStoriesByProject($projectID); $projectBranches = $this->project->getBranchGroupByProject($projectID, array_keys($linkedProducts)); /* If the story of the product which linked the project, you don't allow to remove the product. */ $unmodifiableProducts = array(); $unmodifiableBranches = array(); $unmodifiableMainBranches = array(); foreach($linkedProducts as $productID => $linkedProduct) { $linkedBranches[$productID] = array(); if(!isset($allProducts[$productID])) $allProducts[$productID] = $linkedProduct->name; foreach($branches[$productID] as $branchID => $branch) { $linkedBranches[$productID][$branchID] = $branchID; if(!empty($projectStories[$productID][$branchID]) or !empty($projectBranches[$productID][$branchID])) { if($branchID == BRANCH_MAIN) $unmodifiableMainBranches[$productID] = $branchID; array_push($unmodifiableProducts, $productID); array_push($unmodifiableBranches, $branchID); } } } /* Assign. */ $this->view->title = $this->lang->project->manageProducts . $this->lang->colon . $project->name; $this->view->position[] = $this->lang->project->manageProducts; $this->view->allProducts = $allProducts; $this->view->linkedProducts = $linkedProducts; $this->view->linkedBranches = $linkedBranches; $this->view->branches = $branches; $this->view->unmodifiableProducts = $unmodifiableProducts; $this->view->unmodifiableBranches = $unmodifiableBranches; $this->view->unmodifiableMainBranches = $unmodifiableMainBranches; $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal|noclosed'); $this->display(); } /** * AJAX: Check products. * * @param int $programID * @param int $projectID * @access public * @return void */ public function ajaxCheckProduct($programID, $projectID) { /* Set vars. */ $project = $this->project->getByID($projectID); $oldTopPGM = $this->loadModel('program')->getTopByID($project->parent); $newTopPGM = $this->program->getTopByID($programID); if($oldTopPGM == $newTopPGM) die(); $response = array(); $response['result'] = true; $response['message'] = $this->lang->project->changeProgramTip; /* Get new program products. */ $newProducts = $this->program->getProductPairs($programID, 'assign', 'noclosed'); $response['newProducts'] = html::select("newProducts", array('0' => '') + $newProducts, '', "class='form-control chosen' onchange='loadBranches(this)'"); $multiLinkedProducts = $this->project->getMultiLinkedProducts($projectID); if($multiLinkedProducts) { $multiLinkedProjects = array(); foreach($multiLinkedProducts as $productID => $product) { $multiLinkedProjects[$productID] = $this->loadModel('product')->getProjectPairsByProduct($productID); } $response['result'] = false; $response['message'] = $multiLinkedProducts; $response['multiLinkedProjects'] = $multiLinkedProjects; } die(json_encode($response)); } }