* @package bug * @version $Id$ * @link http://www.zentao.net */ ?> loadModel('product')->setMenu($products, $productID); $selectHtml = $this->product->select($products, $productID, 'bug', 'browse'); foreach($this->lang->bug->menu as $key => $menu) { $replace = ($key == 'product') ? $selectHtml . $this->lang->arrow : $productID; common::setMenuVars($this->lang->bug->menu, $key, $replace); } } /** * Create a bug. * * @access public * @return int|bool */ public function create() { $now = helper::now(); $bug = fixer::input('post') ->add('openedBy', $this->app->user->account) ->add('openedDate', $now) ->setDefault('project,story,task', 0) ->setDefault('openedBuild', '') ->setIF($this->post->assignedTo != '', 'assignedDate', $now) ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) ->specialChars('title,keyword') ->cleanInt('product, module, severity') ->join('openedBuild', ',') ->remove('files, labels') ->get(); $this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec(); if(!dao::isError()) { $bugID = $this->dao->lastInsertID(); $this->loadModel('file')->saveUpload('bug', $bugID); return $bugID; } return false; } /** * Get bugs of a module. * * @param int $productID * @param string|array $moduleIds * @param string $orderBy * @param object $pager * @access public * @return array */ public function getModuleBugs($productID, $moduleIds = 0, $orderBy = 'id_desc', $pager = null) { return $this->dao->select('*')->from(TABLE_BUG) ->where('product')->eq((int)$productID) ->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi() ->andWhere('deleted')->eq(0) ->orderBy($orderBy)->page($pager)->fetchAll(); } /** * Get info of a bug. * * @param int $bugID * @access public * @return object */ public function getById($bugID) { $bug = $this->dao->select('t1.*, t2.name AS projectName, t3.title AS storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, t4.name AS taskName') ->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') ->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id') ->leftJoin(TABLE_TASK)->alias('t4')->on('t1.task = t4.id') ->where('t1.id')->eq((int)$bugID)->fetch(); if(!$bug) return false; $bug->steps = $this->loadModel('file')->setImgSize($bug->steps); foreach($bug as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $bug->$key = ''; if($bug->mailto) { $bug->mailto = ltrim(trim($bug->mailto), ','); // Remove the first , $bug->mailto = str_replace(' ', '', $bug->mailto); $bug->mailto = rtrim($bug->mailto, ',') . ','; $bug->mailto = str_replace(',', ', ', $bug->mailto); } if($bug->duplicateBug) $bug->duplicateBugTitle = $this->dao->findById($bug->duplicateBug)->from(TABLE_BUG)->fields('title')->fetch('title'); if($bug->case) $bug->caseTitle = $this->dao->findById($bug->case)->from(TABLE_CASE)->fields('title')->fetch('title'); if($bug->linkBug) $bug->linkBugTitles = $this->dao->select('id,title')->from(TABLE_BUG)->where('id')->in($bug->linkBug)->fetchPairs(); $bug->files = $this->loadModel('file')->getByObject('bug', $bugID); return $bug; } /** * Get active Bugs. * * @access public * @return void */ public function getActiveBugs($pager) { return $this->dao->select('*')->from(TABLE_BUG)->where('status')->eq('active')->andWhere('toTask')->eq(0)->orderBy('id desc')->page($pager)->fetchAll(); } /** * Update a bug. * * @param int $bugID * @access public * @return void */ public function update($bugID) { $oldBug = $this->getById($bugID); $now = helper::now(); $bug = fixer::input('post') ->cleanInt('product,module,severity,project,story,task') ->specialChars('title,keyword') ->remove('comment,files,labels') ->setDefault('project,module,project,story,task,duplicateBug', 0) ->setDefault('openedBuild', '') ->add('lastEditedBy', $this->app->user->account) ->add('lastEditedDate', $now) ->join('openedBuild', ',') ->setIF($this->post->assignedTo != $oldBug->assignedTo, 'assignedDate', $now) ->setIF($this->post->resolvedBy != '' and $this->post->resolvedDate == '', 'resolvedDate', $now) ->setIF($this->post->resolution != '' and $this->post->resolvedDate == '', 'resolvedDate', $now) ->setIF($this->post->resolution != '' and $this->post->resolvedBy == '', 'resolvedBy', $this->app->user->account) ->setIF($this->post->closedBy != '' and $this->post->closedDate == '', 'closedDate', $now) ->setIF($this->post->closedDate != '' and $this->post->closedBy == '', 'closedBy', $this->app->user->account) ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedTo', 'closed') ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedDate', $now) ->setIF($this->post->resolution != '' or $this->post->resolvedDate != '', 'status', 'resolved') ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'status', 'closed') ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedTo', $oldBug->openedBy) ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedDate', $now) ->setIF($this->post->resolution == '' and $this->post->resolvedDate =='', 'status', 'active') ->setIF($this->post->resolution != '', 'confirmed', 1) ->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) ->get(); $this->dao->update(TABLE_BUG)->data($bug) ->autoCheck() ->batchCheck($this->config->bug->edit->requiredFields, 'notempty') ->checkIF($bug->resolvedBy, 'resolution', 'notempty') ->checkIF($bug->closedBy, 'resolution', 'notempty') ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty') ->where('id')->eq((int)$bugID) ->exec(); if(!dao::isError()) return common::createChanges($oldBug, $bug); } /** * Confirm a bug. * * @param int $bugID * @access public * @return void */ public function confirm($bugID) { $now = helper::now(); $bug->confirmed = 1; $bug->lastEditedBy = $this->app->user->account; $bug->lastEditedDate = $now; $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec(); } /** * Resolve a bug. * * @param int $bugID * @access public * @return void */ public function resolve($bugID) { $oldBug = $this->getById($bugID); $now = helper::now(); $bug = fixer::input('post') ->add('resolvedBy', $this->app->user->account) ->add('resolvedDate', $now) ->add('status', 'resolved') ->add('confirmed', 1) ->add('assignedDate', $now) ->add('lastEditedBy', $this->app->user->account) ->add('lastEditedDate', $now) ->setDefault('duplicateBug', 0) ->setDefault('assignedTo', $oldBug->openedBy) ->remove('comment') ->get(); $this->dao->update(TABLE_BUG)->data($bug) ->autoCheck() ->batchCheck($this->config->bug->resolve->requiredFields, 'notempty') ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty') ->checkIF($bug->resolution == 'fixed', 'resolvedBuild','notempty') ->where('id')->eq((int)$bugID) ->exec(); } /** * Activate a bug. * * @param int $bugID * @access public * @return void */ public function activate($bugID) { $oldBug = $this->getById($bugID); $now = helper::now(); $bug = fixer::input('post') ->setDefault('assignedTo', $oldBug->resolvedBy) ->add('assignedDate', $now) ->add('resolution', '') ->add('status', 'active') ->add('resolvedDate', '0000-00-00') ->add('resolvedBy', '') ->add('resolvedBuild', '') ->add('closedBy', '') ->add('closedDate', '0000-00-00') ->add('duplicateBug', 0) ->add('lastEditedBy', $this->app->user->account) ->add('lastEditedDate', $now) ->join('openedBuild', ',') ->remove('comment,files,labels') ->get(); $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec(); $this->dao->update(TABLE_BUG)->set('activatedCount = activatedCount + 1')->where('id')->eq((int)$bugID)->exec(); } /** * Close a bug. * * @param int $bugID * @access public * @return void */ public function close($bugID) { $oldBug = $this->getById($bugID); $now = helper::now(); $bug = fixer::input('post') ->add('assignedTo', 'closed') ->add('assignedDate', $now) ->add('status', 'closed') ->add('closedBy', $this->app->user->account) ->add('closedDate', $now) ->add('lastEditedBy', $this->app->user->account) ->add('lastEditedDate', $now) ->add('confirmed', 1) ->remove('comment') ->get(); $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec(); } /** * Extract accounts from some bugs. * * @param int $bugs * @access public * @return array */ public function extractAccountsFromList($bugs) { $accounts = array(); foreach($bugs as $bug) { if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy; if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo; if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy; if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy; if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy; } return array_unique($accounts); } /** * Extract accounts from a bug. * * @param object $bug * @access public * @return array */ public function extractAccountsFromSingle($bug) { $accounts = array(); if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy; if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo; if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy; if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy; if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy; return array_unique($accounts); } /** * Get bug pairs of a user. * * @param int $account * @param bool $appendProduct * @param int $limit * @access public * @return array */ public function getUserBugPairs($account, $appendProduct = true, $limit = 0) { $bugs = array(); $stmt = $this->dao->select('t1.id, t1.title, t2.name as product') ->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2') ->on('t1.product=t2.id') ->where('t1.assignedTo')->eq($account) ->andWhere('t1.deleted')->eq(0) ->orderBy('id desc') ->beginIF($limit > 0)->limit($limit)->fi() ->query(); while($bug = $stmt->fetch()) { if($appendProduct) $bug->title = $bug->product . ' / ' . $bug->title; $bugs[$bug->id] = $bug->title; } return $bugs; } /** * Get bugs of a project. * * @param int $projectID * @param string $orderBy * @param object $pager * @access public * @return array */ public function getProjectBugs($projectID, $orderBy = 'id_desc', $pager = null) { return $this->dao->select('*')->from(TABLE_BUG) ->where('project')->eq((int)$projectID) ->andWhere('deleted')->eq(0) ->orderBy($orderBy)->page($pager)->fetchAll(); } /** * Get bug info from a result. * * @param int $resultID * @param int $caseID * @param int $version * @access public * @return array */ public function getBugInfoFromResult($resultID, $caseID = 0, $version = 0) { $title = ''; $bugSteps = ''; $result = $this->dao->findById($resultID)->from(TABLE_TESTRESULT)->fetch(); if($caseID > 0) $run->case = $this->loadModel('testcase')->getById($caseID, $version); else $run = $this->loadModel('testtask')->getRunById($result->run); if($result and $result->caseResult == 'fail') { $title = $run->case->title; $caseSteps = $run->case->steps; $stepResults = unserialize($result->stepResults); if($run->case->precondition != '') { $bugSteps = "
[" . $this->lang->testcase->precondition . "]
" . "\n" . $run->case->precondition; } $bugSteps .= $this->lang->bug->tplStep; if(!empty($stepResults)) { foreach($caseSteps as $key => $step) { $bugSteps .= ($key + 1) . '. ' .$step->desc . "