* @package product * @version $Id$ * @link http://www.zentao.net */ ?> checkPriv($this->getById($productID))) { echo(js::alert($this->lang->product->accessDenied)); die(js::locate('back')); } $currentModule = $this->app->getModuleName(); $currentMethod = $this->app->getMethodName(); /* init currentModule and currentMethod for report*/ if($currentModule == 'story') $currentModule = 'product'; if($currentMethod == 'report') $currentMethod = 'browse'; $selectHtml = html::select('productID', $products, $productID, "onchange=\"switchProduct(this.value, '$currentModule', '$currentMethod', '$extra');\""); foreach($this->lang->product->menu as $key => $menu) { $replace = $key == 'list' ? $selectHtml . $this->lang->arrow : $productID; common::setMenuVars($this->lang->product->menu, $key, $replace); } } /** * Save the product id user last visited to session. * * @param int $productID * @param array $products * @access public * @return int */ public function saveState($productID, $products) { if($productID > 0) $this->session->set('product', (int)$productID); if($productID == 0 and $this->cookie->lastProduct) $this->session->set('product', (int)$this->cookie->lastProduct); if($productID == 0 and $this->session->product == '') $this->session->set('product', key($products)); if(!isset($products[$this->session->product])) $this->session->set('product', key($products)); return $this->session->product; } /** * Check privilege. * * @param int $product * @access public * @return bool */ public function checkPriv($product) { /* Is admin? */ $account = ',' . $this->app->user->account . ','; if(strpos($this->app->company->admins, $account) !== false) return true; /* Product is open, return true. */ if($product->acl == 'open') return true; /* Get team members. */ $teamMembers = $this->getTeamMemberPairs($product); /* Private. */ if($product->acl == 'private') { return isset($teamMembers[$this->app->user->account]); } /* Custom, check groups. */ if($product->acl == 'custom') { if(isset($teamMembers[$this->app->user->account])) return true; $userGroups = $this->loadModel('user')->getGroups($this->app->user->account); $productGroups = explode(',', $product->whitelist); foreach($userGroups as $groupID) { if(in_array($groupID, $productGroups)) return true; } return false; } } /** * Get product by id. * * @param int $productID * @access public * @return object */ public function getById($productID) { return $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); } /** * Get products. * * @param string $status * @param int $limit * @access public * @return array */ public function getList($status = 'all', $limit = 0) { return $this->dao->select('*')->from(TABLE_PRODUCT) ->where('deleted')->eq(0) ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() ->beginIF($limit > 0)->limit($limit)->fi() ->fetchAll('id'); } /** * Get product pairs. * * @access public * @return array */ public function getPairs() { $mode = $this->cookie->productMode ? $this->cookie->productMode : 'noclosed'; $products = $this->dao->select('*') ->from(TABLE_PRODUCT) ->where('deleted')->eq(0) ->beginIF($mode == 'noclosed')->andWhere('status')->ne('closed')->fi() ->fetchAll(); $pairs = array(); foreach($products as $product) { if($this->checkPriv($product)) $pairs[$product->id] = $product->name; } return $pairs; } /** * Get grouped products. * * @access public * @return void */ public function getStatusGroups() { $products = $this->dao->select('id, name, status')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->fetchGroup('status'); } /** * Create a product. * * @access public * @return int */ public function create() { $product = fixer::input('post') ->stripTags('name,code') ->setIF($this->post->acl != 'custom', 'whitelist', '') ->setDefault('status', 'normal') ->setDefault('createdBy', $this->app->user->account) ->setDefault('createdDate', helper::now()) ->join('whitelist', ',') ->get(); $this->dao->insert(TABLE_PRODUCT) ->data($product) ->autoCheck() ->batchCheck('name,code', 'notempty') ->check('name', 'unique') ->check('code', 'unique') ->exec(); return $this->dao->lastInsertID(); } /** * Update a product. * * @param int $productID * @access public * @return array */ public function update($productID) { $productID = (int)$productID; $oldProduct = $this->getById($productID); $product = fixer::input('post') ->stripTags('name,code') ->setIF($this->post->acl != 'custom', 'whitelist', '') ->join('whitelist', ',') ->get(); $this->dao->update(TABLE_PRODUCT) ->data($product) ->autoCheck() ->batchCheck('name,code', 'notempty') ->check('name', 'unique', "id != $productID") ->check('code', 'unique', "id != $productID") ->where('id')->eq($productID) ->exec(); if(!dao::isError()) return common::createChanges($oldProduct, $product); } /** * Get projects of a product in pairs. * * @param int $productID * @param string $param * @access public * @return array */ public function getProjectPairs($productID, $param = 'all') { $projects = $this->dao->select('t2.id, t2.name') ->from(TABLE_PROJECTPRODUCT)->alias('t1')->leftJoin(TABLE_PROJECT)->alias('t2') ->on('t1.project = t2.id') ->where('t1.product')->eq((int)$productID) ->beginIF($param == 'nodeleted')->andWhere('t2.deleted')->eq('0')->fi() ->orderBy('t1.project desc') ->fetchPairs(); $projects = array('' => '') + $projects; return $projects; } /** * Get roadmap of a proejct * * @param int $productID * @access public * @return array */ public function getRoadmap($productID) { $plans = $this->loadModel('productplan')->getList($productID); $releases = $this->loadModel('release')->getList($productID); $roadmap = array(); if(is_array($releases)) $releases = array_reverse($releases); foreach($releases as $release) { $year = substr($release->date, 0, 4); $roadmap[$year][] = $release; } foreach($plans as $plan) { if($plan->end != '0000-00-00' and strtotime($plan->end) - time() <= 0) continue; $year = substr($plan->end, 0, 4); $roadmap[$year][] = $plan; } ksort($roadmap); return $roadmap; } /** * Get team members of a product from projects. * * @param object $product * @access public * @return array */ public function getTeamMemberPairs($product) { $members[$product->PO] = $product->PO; $members[$product->QM] = $product->QM; $members[$product->RM] = $product->RM; $members[$product->createdBy] = $product->createdBy; $projects = $this->dao->select('project')->from(TABLE_PROJECTPRODUCT)->where('product')->eq($product->id)->fetchPairs(); if(!$projects) return $members; $projectTeams = $this->dao->select('account')->from(TABLE_TEAM)->where('project')->in($projects)->fetchPairs(); return array_merge($members, $projectTeams); } /** * Get product stats. * * @param int $counts * * @access public * @return array */ public function getStats($counts) { $this->loadModel('report'); $this->loadModel('story'); $products = $this->getList(',normal'); $stats = array(); $i = 1; $stories = $this->dao->select('product, status, count(status) AS count') ->from(TABLE_STORY) ->where('deleted')->eq(0) ->andWhere('product')->in(array_keys($products)) ->groupBy('product, status') ->fetchGroup('product', 'status'); /* Padding the stories to sure all products have records. */ $emptyStory = array_keys($this->lang->story->statusList); foreach(array_keys($products) as $productID) { if(!isset($stories[$productID])) $stories[$productID] = $emptyStory; } /* Padding the stories to sure all status have records. */ foreach($stories as $key => $story) { foreach(array_keys($this->lang->story->statusList) as $status) { $story[$status] = isset($story[$status]) ? $story[$status]->count : 0; } $stories[$key] = $story; } $plans = $this->dao->select('product, count(*) AS count') ->from(TABLE_PRODUCTPLAN) ->where('deleted')->eq(0) ->andWhere('product')->in(array_keys($products)) ->andWhere('end')->gt(helper::now()) ->groupBy('product') ->fetchPairs(); $releases = $this->dao->select('product, count(*) AS count') ->from(TABLE_RELEASE) ->where('deleted')->eq(0) ->andWhere('product')->in(array_keys($products)) ->groupBy('product') ->fetchPairs(); foreach($products as $key => $product) { if($this->checkPriv($product)) { if($i <= $counts and $product->status != 'closed') { $product->stories = $stories[$product->id]; $product->plans = isset($plans[$product->id]) ? $plans[$product->id] : 0; $product->releases= isset($releases[$product->id]) ? $releases[$product->id] : 0; $stats[] = $product; $i ++; } } else { unset($products[$key]); } } return $stats; } }