* @package bug
* @version $Id: model.php 5079 2013-07-10 00:44:34Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
loadModel('product')->setMenu($products, $productID, $branch, $moduleID, 'bug');
$selectHtml = $this->product->select($products, $productID, 'bug', 'browse', '', $branch, $moduleID, 'bug');
$pageNav = '';
$pageActions = '';
$isMobile = $this->app->viewType == 'mhtml';
if($isMobile)
{
$this->app->loadLang('qa');
$pageNav = html::a(helper::createLink('qa', 'index'), $this->lang->qa->index) . $this->lang->colon;
}
else
{
if($this->config->global->flow == 'full')
{
$this->app->loadLang('qa');
$pageNav = '
[" . $this->lang->testcase->precondition . "]
" . "\n" . $run->case->precondition;
}
if(!empty($stepResults))
{
$i = 1;
$bugStep = '';
foreach($steps as $stepId)
{
if(!isset($caseSteps[$stepId])) continue;
$step = $caseSteps[$stepId];
$bugStep .= $i . '. ' . $step->desc . ".+)\)/', $this->reportCondition(), $matchs);
if(!empty($matchs) and isset($matchs['productIdList'])) $products = str_replace('\'', '', $matchs['productIdList']);
$builds = $this->loadModel('build')->getProductBuildPairs($products, $branch = 0, $params = '');
/* Deal with the situation that a bug maybe associate more than one openedBuild. */
foreach($datas as $buildIDList => $data)
{
$openBuildIDList = explode(',', $buildIDList);
if(count($openBuildIDList) > 1)
{
foreach($openBuildIDList as $buildID)
{
if(isset($datas[$buildID]))
{
$datas[$buildID]->value += $data->value;
}
else
{
if(!isset($datas[$buildID])) $datas[$buildID] = new stdclass();
$datas[$buildID]->name = $buildID;
$datas[$buildID]->value = $data->value;
}
}
unset($datas[$buildIDList]);
}
}
foreach($datas as $buildID => $data)
{
$data->name = isset($builds[$buildID]) ? $builds[$buildID] : $this->lang->report->undefined;
}
ksort($datas);
return $datas;
}
/**
* Get report data of bugs per module
*
* @access public
* @return array
*/
public function getDataOfBugsPerModule()
{
$datas = $this->dao->select('module as name, count(module) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('module')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
$modules = $this->loadModel('tree')->getModulesName(array_keys($datas), true, true);
foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/';
return $datas;
}
/**
* Get report data of opened bugs per day.
*
* @access public
* @return array
*/
public function getDataOfOpenedBugsPerDay()
{
return $this->dao->select('DATE_FORMAT(openedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('openedDate')->fetchAll();
}
/**
* Get report data of resolved bugs per day.
*
* @access public
* @return array
*/
public function getDataOfResolvedBugsPerDay()
{
return $this->dao->select('DATE_FORMAT(resolvedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)
->where($this->reportCondition())->groupBy('name')
->having('name != 0000-00-00')
->orderBy('resolvedDate')
->fetchAll();
}
/**
* Get report data of closed bugs per day.
*
* @access public
* @return array
*/
public function getDataOfClosedBugsPerDay()
{
return $this->dao->select('DATE_FORMAT(closedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)
->where($this->reportCondition())->groupBy('name')
->having('name != 0000-00-00')
->orderBy('closedDate')->fetchAll();
}
/**
* Get report data of openeded bugs per user.
*
* @access public
* @return array
*/
public function getDataOfOpenedBugsPerUser()
{
$datas = $this->dao->select('openedBy AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
return $datas;
}
/**
* Get report data of resolved bugs per user.
*
* @access public
* @return array
*/
public function getDataOfResolvedBugsPerUser()
{
$datas = $this->dao->select('resolvedBy AS name, COUNT(*) AS value')
->from(TABLE_BUG)->where($this->reportCondition())
->andWhere('resolvedBy')->ne('')
->groupBy('name')
->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
return $datas;
}
/**
* Get report data of closed bugs per user.
*
* @access public
* @return array
*/
public function getDataOfClosedBugsPerUser()
{
$datas = $this->dao->select('closedBy AS name, COUNT(*) AS value')
->from(TABLE_BUG)
->where($this->reportCondition())
->andWhere('closedBy')->ne('')
->groupBy('name')
->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
return $datas;
}
/**
* Get report data of bugs per severity.
*
* @access public
* @return array
*/
public function getDataOfBugsPerSeverity()
{
$datas = $this->dao->select('severity AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $severity => $data) if(isset($this->lang->bug->severityList[$severity])) $data->name = $this->lang->bug->severityList[$severity];
return $datas;
}
/**
* Get report data of bugs per resolution.
*
* @access public
* @return array
*/
public function getDataOfBugsPerResolution()
{
$datas = $this->dao->select('resolution AS name, COUNT(*) AS value')
->from(TABLE_BUG)
->where($this->reportCondition())
->andWhere('resolution')->ne('')
->groupBy('name')->orderBy('value DESC')
->fetchAll('name');
if(!$datas) return array();
foreach($datas as $resolution => $data) if(isset($this->lang->bug->resolutionList[$resolution])) $data->name = $this->lang->bug->resolutionList[$resolution];
return $datas;
}
/**
* Get report data of bugs per status.
*
* @access public
* @return array
*/
public function getDataOfBugsPerStatus()
{
$datas = $this->dao->select('status AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $status => $data) if(isset($this->lang->bug->statusList[$status])) $data->name = $this->lang->bug->statusList[$status];
return $datas;
}
/**
* Get report data of bugs per pri
*
* @access public
* @return array
*/
public function getDataOfBugsPerPri()
{
$datas = $this->dao->select('pri AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $status => $data) $data->name = $this->lang->bug->report->bugsPerPri->graph->xAxisName . ':' . zget($this->lang->bug->priList, $data->name);
return $datas;
}
/**
* Get report data of bugs per status.
*
* @access public
* @return array
*/
public function getDataOfBugsPerActivatedCount()
{
$datas = $this->dao->select('activatedCount AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $data) $data->name = $this->lang->bug->report->bugsPerActivatedCount->graph->xAxisName . ':' . $data->name;
return $datas;
}
/**
* Get report data of bugs per type.
*
* @access public
* @return array
*/
public function getDataOfBugsPerType()
{
$datas = $this->dao->select('type AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('name')->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
foreach($datas as $type => $data) if(isset($this->lang->bug->typeList[$type])) $data->name = $this->lang->bug->typeList[$type];
return $datas;
}
/**
* getDataOfBugsPerAssignedTo
*
* @access public
* @return void
*/
public function getDataOfBugsPerAssignedTo()
{
$datas = $this->dao->select('assignedTo AS name, COUNT(*) AS value')
->from(TABLE_BUG)->where($this->reportCondition())
->groupBy('name')
->orderBy('value DESC')->fetchAll('name');
if(!$datas) return array();
if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter');
foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account];
return $datas;
}
/**
* Merge the default chart settings and the settings of current chart.
*
* @param string $chartType
* @access public
* @return void
*/
public function mergeChartOption($chartType)
{
$chartOption = $this->lang->bug->report->$chartType;
$commonOption = $this->lang->bug->report->options;
$chartOption->graph->caption = $this->lang->bug->report->charts[$chartType];
if(!isset($chartOption->type)) $chartOption->type = $commonOption->type;
if(!isset($chartOption->width)) $chartOption->width = $commonOption->width;
if(!isset($chartOption->height)) $chartOption->height = $commonOption->height;
/* 合并配置。*/
foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value;
}
/**
* Return the file => label pairs of some fields.
*
* @param string $fields
* @access public
* @return array
*/
public function getFieldPairs($fields)
{
$fields = explode(',', $fields);
foreach($fields as $key => $field)
{
$field = trim($field);
$fields[$field] = $this->lang->bug->$field;
unset($fields[$key]);
}
return $fields;
}
/**
* Get all bugs.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getAllBugs($productID, $branch, $modules, $projects, $orderBy, $pager = null)
{
$bugs = $this->dao->select('t1.*, t2.title as planTitle')->from(TABLE_BUG)->alias('t1')
->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id')
->where('t1.product')->eq($productID)
->andWhere('t1.project')->in(array_keys($projects))
->beginIF($branch)->andWhere('t1.branch')->eq($branch)->fi()
->beginIF($modules)->andWhere('t1.module')->in($modules)->fi()
->andWhere('t1.deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
return $bugs;
}
/**
* Get bugs of assign to me.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getByAssigntome($productID, $branch, $modules, $projects, $orderBy, $pager)
{
return $this->dao->findByAssignedTo($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->andWhere('project')->in(array_keys($projects))
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get bugs of opened by me.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getByOpenedbyme($productID, $branch, $modules, $projects, $orderBy, $pager)
{
return $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->andWhere('project')->in(array_keys($projects))
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get bugs of resolved by me.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getByResolvedbyme($productID, $branch, $modules, $projects, $orderBy, $pager)
{
return $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID)
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->andWhere('project')->in(array_keys($projects))
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get bugs of nobody to do.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getByAssigntonull($productID, $branch, $modules, $projects, $orderBy, $pager)
{
return $this->dao->findByAssignedTo('')->from(TABLE_BUG)->andWhere('product')->eq($productID)
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->andWhere('project')->in(array_keys($projects))
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get unconfirmed bugs.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param int $projects
* @param int $orderBy
* @param int $pager
* @access public
* @return void
*/
public function getUnconfirmed($productID, $branch, $modules, $projects, $orderBy, $pager)
{
return $this->dao->select('*')->from(TABLE_BUG)
->where('confirmed')->eq(0)
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->andWhere('product')->eq($productID)
->andWhere('project')->in(array_keys($projects))
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get bugs the overdueBugs is active or unclosed.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $status
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getOverdueBugs($productID, $branch, $modules, $projects, $orderBy, $pager)
{
return $this->dao->select('*')->from(TABLE_BUG)
->where('project')->in(array_keys($projects))
->andWhere('product')->eq($productID)
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->andWhere('status')->eq('active')
->andWhere('deleted')->eq(0)
->andWhere('deadline')->ne('0000-00-00')
->andWhere('deadline')->lt(helper::today())
->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get bugs the status is active or unclosed.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $status
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getByStatus($productID, $branch, $modules, $projects, $status, $orderBy, $pager)
{
return $this->dao->select('*')->from(TABLE_BUG)
->where('project')->in(array_keys($projects))
->andWhere('product')->eq($productID)
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->beginIF($status == 'unclosed')->andWhere('status')->ne('closed')->fi()
->beginIF($status == 'unresolved')->andWhere('status')->eq('active')->fi()
->beginIF($status == 'toclosed')->andWhere('status')->eq('resolved')->fi()
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get unclosed bugs for long time.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getByLonglifebugs($productID, $branch, $modules, $projects, $orderBy, $pager)
{
$lastEditedDate = date(DT_DATE1, time() - $this->config->bug->longlife * 24 * 3600);
return $this->dao->findByLastEditedDate("<", $lastEditedDate)->from(TABLE_BUG)->andWhere('product')->eq($productID)
->andWhere('project')->in(array_keys($projects))
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->andWhere('openedDate')->lt($lastEditedDate)
->andWhere('deleted')->eq(0)
->andWhere('status')->ne('closed')->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get postponed bugs.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getByPostponedbugs($productID, $branch, $modules, $projects, $orderBy, $pager)
{
return $this->dao->findByResolution('postponed')->from(TABLE_BUG)->andWhere('product')->eq($productID)
->beginIF($branch)->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->andWhere('project')->in(array_keys($projects))
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
}
/**
* Get bugs need confirm.
*
* @param int $productID
* @param int $branch
* @param array $modules
* @param array $projects
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getByNeedconfirm($productID, $branch, $modules, $projects, $orderBy, $pager)
{
return $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_BUG)->alias('t1')->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
->where("t2.status = 'active'")
->andWhere('t1.product')->eq($productID)
->beginIF($branch)->andWhere('t1.branch')->in($branch)->fi()
->beginIF($modules)->andWhere('t1.module')->in($modules)->fi()
->andWhere('t2.version > t1.storyVersion')
->andWhere('t1.project')->in(array_keys($projects))
->andWhere('t1.deleted')->eq(0)
->orderBy($orderBy)
->page($pager)
->fetchAll();
}
/**
* Get bugs by search.
*
* @param int $productID
* @param int $queryID
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getBySearch($productID, $queryID, $orderBy, $pager = null, $branch = 0)
{
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
if($query)
{
$this->session->set('bugQuery', $query->sql);
$this->session->set('bugForm', $query->form);
}
else
{
$this->session->set('bugQuery', ' 1 = 1');
}
}
else
{
if($this->session->bugQuery == false) $this->session->set('bugQuery', ' 1 = 1');
}
$allProduct = "`product` = 'all'";
$bugQuery = $this->session->bugQuery;
if(strpos($bugQuery, '`product` =') === false) $bugQuery .= ' AND `product` = ' . $productID;
if(strpos($bugQuery, $allProduct) !== false)
{
$products = $this->app->user->view->products;
$bugQuery = str_replace($allProduct, '1', $bugQuery);
$bugQuery = $bugQuery . ' AND `product` ' . helper::dbIN($products);
}
$allBranch = "`branch` = 'all'";
if($branch and strpos($bugQuery, '`branch` =') === false) $bugQuery .= " AND `branch` in('0','$branch')";
if(strpos($bugQuery, $allBranch) !== false) $bugQuery = str_replace($allBranch, '1', $bugQuery);
/* Fix bug #2877. */
if(strpos($bugQuery, '`resolvedDate`') !== false) $bugQuery .= " AND `resolvedDate` != '0000-00-00 00:00:00'";
if(strpos($bugQuery, '`closedDate`') !== false) $bugQuery .= " AND `closedDate` != '0000-00-00 00:00:00'";
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery)
->beginIF(!$this->app->user->admin)->andWhere('project')->in('0,' . $this->app->user->view->projects)->fi()
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
return $bugs;
}
/**
* Form customed bugs.
*
* @param array $bugs
* @access public
* @return array
*/
public function formCustomedBugs($bugs)
{
/* Get related objects id lists. */
$relatedModuleIdList = array();
$relatedStoryIdList = array();
$relatedTaskIdList = array();
$relatedCaseIdList = array();
$relatedProjectIdList = array();
foreach($bugs as $bug)
{
$relatedModuleIdList[$bug->module] = $bug->module;
$relatedStoryIdList[$bug->story] = $bug->story;
$relatedTaskIdList[$bug->task] = $bug->task;
$relatedCaseIdList[$bug->case] = $bug->case;
$relatedProjectIdList[$bug->project] = $bug->project;
/* Get related objects title or names. */
$relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs();
$relatedStories = $this->dao->select('id, title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs();
$relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs();
$relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs();
$relatedProjects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->in($relatedProjectIdList)->fetchPairs();
/* fill some field with useful value. */
if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module];
if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story];
if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task];
if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case];
if(isset($relatedProjects[$bug->project])) $bug->project = $relatedProjects[$bug->project];
}
return $bugs;
}
/**
* Adjust the action is clickable.
*
* @param string $bug
* @param string $action
* @access public
* @return void
*/
public static function isClickable($object, $action)
{
$action = strtolower($action);
if($action == 'confirmbug') return $object->status == 'active' and $object->confirmed == 0;
if($action == 'resolve') return $object->status == 'active';
if($action == 'close') return $object->status == 'resolved';
if($action == 'activate') return $object->status != 'active';
if($action == 'tostory') return $object->status == 'active';
return true;
}
/**
* Get report condition from session.
*
* @access public
* @return void
*/
public function reportCondition()
{
if(isset($_SESSION['bugQueryCondition']))
{
if(!$this->session->bugOnlyCondition) return 'id in (' . preg_replace('/SELECT .* FROM/', 'SELECT t1.id FROM', $this->session->bugQueryCondition) . ')';
return $this->session->bugQueryCondition;
}
return true;
}
/**
* Link bug to build and release
*
* @param string|array $bugs
* @param int $resolvedBuild
* @access public
* @return bool
*/
public function linkBugToBuild($bugs, $resolvedBuild)
{
if(empty($resolvedBuild) or $resolvedBuild == 'trunk') return true;
if(is_array($bugs)) $bugs = join(',', $bugs);
$buildBugs = $this->dao->select('bugs')->from(TABLE_BUILD)->where('id')->eq($resolvedBuild)->fetch('bugs');
$buildBugs .= ',' . $bugs;
$buildBugs = explode(',', trim($buildBugs, ','));
$buildBugs = array_unique($buildBugs);
$this->dao->update(TABLE_BUILD)->set('bugs')->eq(join(',', $buildBugs))->where('id')->eq($resolvedBuild)->exec();
$release = $this->dao->select('id,bugs')->from(TABLE_RELEASE)->where('build')->eq($resolvedBuild)->andWhere('deleted')->eq('0')->fetch();
if($release)
{
$releaseBugs = $release->bugs .',' . $bugs;
$releaseBugs = explode(',', trim($releaseBugs, ','));
$releaseBugs = array_unique($releaseBugs);
$this->dao->update(TABLE_RELEASE)->set('bugs')->eq(join(',', $releaseBugs))->where('id')->eq($release->id)->exec();
}
return true;
}
/**
* Print cell data.
*
* @param object $col
* @param object $bug
* @param array $users
* @param array $builds
* @param array $branches
* @param array $modulePairs
* @param array $projects
* @param array $plans
* @param array $stories
* @param array $tasks
* @param string $mode
* @access public
* @return void
*/
public function printCell($col, $bug, $users, $builds, $branches, $modulePairs, $projects = array(), $plans = array(), $stories = array(), $tasks = array(), $mode = 'datatable')
{
$canBatchEdit = common::hasPriv('bug', 'batchEdit');
$canBatchConfirm = common::hasPriv('bug', 'batchConfirm');
$canBatchClose = common::hasPriv('bug', 'batchClose');
$canBatchActivate = common::hasPriv('bug', 'batchActivate');
$canBatchChangeBranch = common::hasPriv('bug', 'batchChangeBranch');
$canBatchChangeModule = common::hasPriv('bug', 'batchChangeModule');
$canBatchResolve = common::hasPriv('bug', 'batchResolve');
$canBatchAssignTo = common::hasPriv('bug', 'batchAssignTo');
$canBatchAction = $canBatchEdit or $canBatchConfirm or $canBatchClose or $canBatchActivate or $canBatchChangeBranch or $canBatchChangeModule or $canBatchResolve or $canBatchAssignTo;
$canView = common::hasPriv('bug', 'view');
$hasCustomSeverity = false;
foreach($this->lang->bug->severityList as $severityKey => $severityValue)
{
if(!empty($severityKey) and (string)$severityKey != (string)$severityValue)
{
$hasCustomSeverity = true;
break;
}
}
$bugLink = inlink('view', "bugID=$bug->id");
$account = $this->app->user->account;
$id = $col->id;
if($col->show)
{
$class = "c-$id";
$title = '';
if($id == 'id') $class .= ' cell-id';
if($id == 'status')
{
$class .= ' bug-' . $bug->status;
$title = "title='" . $this->processStatus('bug', $bug) . "'";
}
if($id == 'confirmed')
{
$class .= ' text-center';
}
if($id == 'title')
{
$class .= ' text-left';
$title = "title='{$bug->title}'";
}
if($id == 'type')
{
$title = "title='" . zget($this->lang->bug->typeList, $bug->type) . "'";
}
if($id == 'assignedTo')
{
$class .= ' has-btn text-left';
if($bug->assignedTo == $account) $class .= ' red';
}
if($id == 'deadline' && isset($bug->delay)) $class .= ' delayed';
if(strpos(',project,story,plan,task,openedBuild,', ",{$id},") !== false) $class .= ' text-ellipsis';
echo "";
if(isset($this->config->bizVersion)) $this->loadModel('flow')->printFlowCell('bug', $bug, $id);
switch($id)
{
case 'id':
if($canBatchAction)
{
echo html::checkbox('bugIDList', array($bug->id => '')) . html::a(helper::createLink('bug', 'view', "bugID=$bug->id"), sprintf('%03d', $bug->id));
}
else
{
printf('%03d', $bug->id);
}
break;
case 'severity':
if($hasCustomSeverity)
{
echo "" . zget($this->lang->bug->severityList, $bug->severity) . "";
}
else
{
echo "";
}
break;
case 'pri':
echo "";
echo zget($this->lang->bug->priList, $bug->pri, $bug->pri);
echo "";
break;
case 'confirmed':
$class = 'confirm' . $bug->confirmed;
echo "" . zget($this->lang->bug->confirmedList, $bug->confirmed, $bug->confirmed) . " ";
break;
case 'title':
if($bug->branch and isset($branches[$bug->branch])) echo "{$branches[$bug->branch]} ";
if($bug->module and isset($modulePairs[$bug->module])) echo "{$modulePairs[$bug->module]} ";
echo $canView ? html::a($bugLink, $bug->title, null, "style='color: $bug->color'") : "{$bug->title}";
break;
case 'branch':
echo zget($branches, $bug->branch, '');
break;
case 'project':
echo zget($projects, $bug->project, '');
break;
case 'plan':
echo zget($plans, $bug->plan, '');
break;
case 'story':
if(isset($stories[$bug->story]))
{
$story = $stories[$bug->story];
echo common::hasPriv('story', 'view') ? html::a(helper::createLink('story', 'view', "storyID=$story->id", 'html', true), $story->title, '', "class='iframe'") : $story->title;
}
break;
case 'task':
if(isset($tasks[$bug->task]))
{
$task = $tasks[$bug->task];
echo common::hasPriv('task', 'view') ? html::a(helper::createLink('task', 'view', "taskID=$task->id", 'html', true), $task->name, '', "class='iframe'") : $task->name;
}
break;
case 'type':
echo zget($this->lang->bug->typeList, $bug->type);
break;
case 'status':
echo "";
echo $this->processStatus('bug', $bug);
echo '';
break;
case 'activatedCount':
echo $bug->activatedCount;
break;
case 'activatedDate':
echo substr($bug->activatedDate, 5, 11);
break;
case 'keywords':
echo $bug->keywords;
break;
case 'os':
echo zget($this->lang->bug->osList, $bug->os);
break;
case 'browser':
echo zget($this->lang->bug->browserList, $bug->browser);
break;
case 'mailto':
$mailto = explode(',', $bug->mailto);
foreach($mailto as $account)
{
$account = trim($account);
if(empty($account)) continue;
echo zget($users, $account) . " ";
}
break;
case 'found':
echo zget($users, $bug->found);
break;
case 'openedBy':
echo zget($users, $bug->openedBy);
break;
case 'openedDate':
echo substr($bug->openedDate, 5, 11);
break;
case 'openedBuild':
$builds = array_flip($builds);
foreach(explode(',', $bug->openedBuild) as $build)
{
$buildID = zget($builds, $build, '');
if($buildID == 'trunk')
{
echo $build;
}
elseif($buildID and common::hasPriv('build', 'view'))
{
echo html::a(helper::createLink('build', 'view', "buildID=$buildID"), $build, '', "title='$bug->openedBuild'");
}
else
{
echo $build;
}
}
break;
case 'assignedTo':
$this->printAssignedHtml($bug, $users);
break;
case 'assignedDate':
echo substr($bug->assignedDate, 5, 11);
break;
case 'deadline':
echo $bug->deadline;
break;
case 'resolvedBy':
echo zget($users, $bug->resolvedBy, $bug->resolvedBy);
break;
case 'resolution':
echo zget($this->lang->bug->resolutionList, $bug->resolution);
break;
case 'resolvedDate':
echo substr($bug->resolvedDate, 5, 11);
break;
case 'resolvedBuild':
echo $bug->resolvedBuild;
break;
case 'closedBy':
echo zget($users, $bug->closedBy);
break;
case 'closedDate':
echo substr($bug->closedDate, 5, 11);
break;
case 'lastEditedBy':
echo zget($users, $bug->lastEditedBy);
break;
case 'lastEditedDate':
echo substr($bug->lastEditedDate, 5, 11);
break;
case 'actions':
$params = "bugID=$bug->id";
common::printIcon('bug', 'confirmBug', $params, $bug, 'list', 'confirm', '', 'iframe', true);
common::printIcon('bug', 'resolve', $params, $bug, 'list', 'checked', '', 'iframe', true);
common::printIcon('bug', 'close', $params, $bug, 'list', '', '', 'iframe', true);
common::printIcon('bug', 'edit', $params, $bug, 'list');
common::printIcon('bug', 'create', "product=$bug->product&branch=$bug->branch&extra=$params", $bug, 'list', 'copy');
break;
}
echo ' | ';
}
}
/**
* Print assigned html.
*
* @param object $bug
* @param array $users
* @access public
* @return void
*/
public function printAssignedHtml($bug, $users)
{
$btnTextClass = '';
$assignedToText = !empty($bug->assignedTo) ? zget($users, $bug->assignedTo) : $this->lang->bug->noAssigned;
$btnTextClass = 'text-primary';
if($bug->assignedTo == $this->app->user->account) $btnTextClass = 'text-red';
$btnClass = $bug->assignedTo == 'closed' ? ' disabled' : '';
$btnClass = "iframe btn btn-icon-left btn-sm {$btnClass}";
$assignToLink = helper::createLink('bug', 'assignTo', "bugID=$bug->id", '', true);
$assignToHtml = html::a($assignToLink, " {$assignedToText}", '', "class='$btnClass'");
echo !common::hasPriv('bug', 'assignTo', $bug) ? "{$assignedToText}" : $assignToHtml;
}
/**
* Send mail
*
* @param int $bugID
* @param int $actionID
* @access public
* @return void
*/
public function sendmail($bugID, $actionID)
{
$this->loadModel('mail');
$bug = $this->getByID($bugID);
$users = $this->loadModel('user')->getPairs('noletter');
/* Get action info. */
$action = $this->loadModel('action')->getById($actionID);
$history = $this->action->getHistory($actionID);
$action->history = isset($history[$actionID]) ? $history[$actionID] : array();
$action->appendLink = '';
if(strpos($action->extra, ':') !== false)
{
list($extra, $id) = explode(':', $action->extra);
$action->extra = $extra;
if($id)
{
$name = $this->dao->select('title')->from(TABLE_BUG)->where('id')->eq($id)->fetch('title');
if($name) $action->appendLink = html::a(zget($this->config->mail, 'domain', common::getSysURL()) . helper::createLink($action->objectType, 'view', "id=$id", 'html'), "#$id " . $name);
}
}
/* Get mail content. */
$modulePath = $this->app->getModulePath($appName = '', 'bug');
$oldcwd = getcwd();
$viewFile = $modulePath . 'view/sendmail.html.php';
chdir($modulePath . 'view');
if(file_exists($modulePath . 'ext/view/sendmail.html.php'))
{
$viewFile = $modulePath . 'ext/view/sendmail.html.php';
chdir($modulePath . 'ext/view');
}
ob_start();
include $viewFile;
foreach(glob($modulePath . 'ext/view/sendmail.*.html.hook.php') as $hookFile) include $hookFile;
$mailContent = ob_get_contents();
ob_end_clean();
chdir($oldcwd);
$sendUsers = $this->getToAndCcList($bug);
if(!$sendUsers) return;
list($toList, $ccList) = $sendUsers;
$subject = $this->getSubject($bug);
/* Send it. */
$this->mail->send($toList, $subject, $mailContent, $ccList);
if($this->mail->isError()) trigger_error(join("\n", $this->mail->getError()));
}
/**
* Get subject.
*
* @param object $bug
* @access public
* @return string
*/
public function getSubject($bug)
{
$productName = $this->loadModel('product')->getById($bug->product)->name;
return 'BUG #'. $bug->id . ' ' . $bug->title . ' - ' . $productName;
}
/**
* Get toList and ccList.
*
* @param object $bug
* @access public
* @return bool|array
*/
public function getToAndCcList($bug)
{
/* Set toList and ccList. */
$toList = $bug->assignedTo;
$ccList = trim($bug->mailto, ',');
if(empty($toList))
{
if(empty($ccList)) return false;
if(strpos($ccList, ',') === false)
{
$toList = $ccList;
$ccList = '';
}
else
{
$commaPos = strpos($ccList, ',');
$toList = substr($ccList, 0, $commaPos);
$ccList = substr($ccList, $commaPos + 1);
}
}
elseif(strtolower($toList) == 'closed')
{
$toList = $bug->resolvedBy;
}
return array($toList, $ccList);
}
public function summary($bugs)
{
$unresolved = 0;
foreach($bugs as $bug)
{
if($bug->status != 'resolved' && $bug->status != 'closed') $unresolved++;
}
return sprintf($this->lang->bug->summary, count($bugs), $unresolved);
}
}