PageRenderTime 47ms CodeModel.GetById 19ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/cubi/modules/menu/do/MenuTreeDO.php

http://openbiz-cubi.googlecode.com/
PHP | 293 lines | 217 code | 19 blank | 57 comment | 41 complexity | d4a0eea94a5b15f860a02b5090e30230 MD5 | raw file
  1<?PHP
  2/**
  3 * PHPOpenBiz Framework
  4 *
  5 * LICENSE
  6 *
  7 * This source file is subject to the BSD license that is bundled
  8 * with this package in the file LICENSE.txt.
  9 *
 10 * @package   openbiz.bin.data
 11 * @copyright Copyright (c) 2005-2011, Rocky Swen
 12 * @license   http://www.opensource.org/licenses/bsd-license.php
 13 * @link      http://www.phpopenbiz.org/
 14 * @version   $Id: MenuTreeDO.php 5171 2013-01-18 10:36:59Z rockyswen@gmail.com $
 15 */
 16
 17include_once(OPENBIZ_BIN.'data/BizDataObj.php');
 18include_once('MenuRecord.php');
 19
 20/**
 21 * BizDataTree class provide query for tree structured records
 22 *
 23 * @package openbiz.bin.data
 24 * @author Rocky Swen
 25 * @copyright Copyright (c) 2005-2009
 26 * @access public
 27 */
 28class MenuTreeDO extends BizDataObj
 29{
 30	protected $rootNodes;
 31	protected $depth;
 32	static protected $m_BreadCrumb = null; 
 33	static protected $fullMenuTree = null; 
 34
 35	public function fetchTree($rootSearchRule, $depth)
 36	{				
 37		$this->fetchTreeBySearchRule($rootSearchRule, $depth);
 38	}
 39	
 40	public function fetchTreeByName($menuName, $depth)
 41	{
 42		return $this->fetchTreeBySearchRule("[name]='$menuName'", $depth);
 43	}
 44	
 45	/**
 46     * Fetch records in tree structure
 47     *
 48     * @return <type>
 49     */
 50	public function fetchTreeBySearchRule($rootSearchRule, $depth, $globalSearchRule=null )
 51	{
 52		$url = $_SERVER['REQUEST_URI'];
 53		$this->depth = $depth;
 54		// query on given search rule
 55		if($globalSearchRule){
 56			$searchRule = $rootSearchRule." AND ".$globalSearchRule;
 57		}else{
 58			$searchRule = $rootSearchRule;
 59		}
 60        $recordList = $this->directFetch($searchRule);
 61        if (!$recordList)
 62        {
 63            $this->rootNodes = array();
 64            return;
 65        }
 66        $i = 0;
 67        foreach ($recordList as $rec)
 68        {
 69            $menuRec = new MenuRecord($rec);
 70            if ($menuRec->allowAccess()) {  // check access with role
 71                $this->rootNodes[$i] = $menuRec;
 72                if ($this->rootNodes[$i]->m_URL == $url)
 73                    $this->rootNodes[$i]->m_Current = 1;
 74                $i++;
 75            }
 76        }
 77        if ($this->depth <= 1)
 78            return $this->rootNodes;
 79        if (!$this->rootNodes) return array();
 80        foreach ($this->rootNodes as $node)
 81        {
 82            $this->_getChildrenNodes($node, 1, $globalSearchRule);
 83        }
 84        //print_r($this->rootNodes);
 85        return $this->rootNodes;
 86    }
 87
 88    public function fetchNodePath($nodeSearchRule, &$pathArray)
 89    {
 90    	//echo "fetchNodePath($nodeSearchRule)";
 91		$recordList = $this->directFetch($nodeSearchRule);
 92		//print_r($recordList); exit;
 93    	if(count($recordList)>=1){
 94			$i=0;
 95    		// find the record whose parent are not empty
 96			if (count($recordList)>1) {
 97				for ($i=0; $i<count($recordList); $i++) {
 98					if ($recordList[$i]['PId']!='') break;
 99				}
100			}
101    		if($recordList[$i]['PId']!='' && $recordList[$i]['PId']!='0'){
102    			$searchRule = "[Id]='".$recordList[$i]['PId']."'";
103    			$this->fetchNodePath($searchRule, $pathArray);
104    		}
105    		$node = new MenuRecord($recordList[$i]);
106    		array_push ($pathArray,$node);
107    		return $pathArray;
108    	}
109    }
110    
111	public function getBreadCrumb()
112	{
113    	if (self::$m_BreadCrumb != null)
114    		return self::$m_BreadCrumb;
115    	
116    	self::$m_BreadCrumb = array();
117		$uri = $_SERVER['REQUEST_URI'];
118		if (empty($uri))
119			return array();
120    	$matchUri = $this->_getMatchUri($uri);
121    	$uri = str_replace("//","/",str_replace(APP_INDEX,'',$uri));
122    	
123    	$pathArray = array();
124    	//global $g_BizSystem;
125    	//$currentView = $g_BizSystem->getCurrentViewName();
126		//$this->fetchNodePath("[link]='$uri' OR [view]='$currentView'", $pathArray);
127
128    	// first find the exact uri match
129    	$this->fetchNodePath("[link]='$uri'", $pathArray);
130    	if (count($pathArray)>0) {
131    		self::$m_BreadCrumb = $pathArray;
132    		return $pathArray;
133    	}
134
135    	// then find partial match uri
136		$this->fetchNodePath("[url_match] LIKE '%$matchUri%'", $pathArray);	
137		if (count($pathArray)>0) {	
138			self::$m_BreadCrumb = $pathArray;
139			return $pathArray;
140		}
141    	
142    	// then find partial match uri
143		$this->fetchNodePath("[link] LIKE '%$matchUri%'", $pathArray);		
144		self::$m_BreadCrumb = $pathArray;
145		return $pathArray;
146    }
147    
148    private function _getMatchUri($uri)
149    {
150    	$matchUri = str_replace(APP_INDEX,'',$uri);
151    	// only count first 2 parts
152    	$_matchUris = explode('/',$matchUri);
153    	if (count($_matchUris)>=2) {
154    		if ($_matchUris[0]=='')
155    			if (count($_matchUris)>=3)
156    				$matchUri = '/'.$_matchUris[1].'/'.$_matchUris[2];
157    		else
158    			$matchUri = $_matchUris[0].'/'.$_matchUris[1];
159    	}
160    	return $matchUri;
161    }
162    
163    /**
164     * List all children records of a given record
165     *
166     * @return void
167     */
168    private function _getChildrenNodes(&$node, $depth, $globalSearchRule=null)
169    {
170        $url = $_SERVER['REQUEST_URI'];
171    	$pid = $node->m_Id;
172        //echo "<br>in _getChildrenNodes";
173        if($globalSearchRule){
174        	$searchRule = "[PId]='$pid' AND $globalSearchRule";
175        }else{
176    		$searchRule = "[PId]='$pid'";
177        }
178        $recordList = $this->directFetch($searchRule);
179        $i = 0;
180        foreach ($recordList as $rec)
181        {
182            // TODO: check access with role
183            $menuRec = new MenuRecord($rec);
184            if ($menuRec->allowAccess()) {
185                $node->m_ChildNodes[$i] = $menuRec;
186                $i++;
187            }
188        }
189        //print_r($node->m_ChildNodes);
190        // reach leave node
191        if ($node->m_ChildNodes == null) {
192            return;
193        }
194        $depth++;
195        // reach given depth
196        if ($depth >= $this->depth)
197            return;
198        else
199        {
200            foreach ($node->m_ChildNodes as $node_c)
201            {
202                $this->_getChildrenNodes($node_c, $depth, $globalSearchRule);
203            }
204        }
205    }
206    
207    public function recordCount($sql)
208    {
209    	$counter = 0;
210    	$rs = $this->directFetch($sql);
211    	foreach($rs as $record)
212    	{
213    		$access = $record['access'];
214    		if(empty($access) || BizSystem::allowUserAccess($access))
215    		{
216				$counter++;
217    		}
218    	}
219    	return $counter;
220    }
221	
222	public function directFetch($searchRule="", $count=-1, $offset=0,$sortRule="")
223	{
224		//return parent::directFetch($searchRule);
225		// use menu tree cache
226		$this->loadFullMenuTree();
227		
228		// search menu tree
229		$searchRule = str_replace(' = ','=',$searchRule);
230		if (!preg_match_all("/\[([a-zA-Z0-9_]+)\]=([^ ]+)/",$searchRule,$m)) {
231			return parent::directFetch($searchRule);
232		}
233		//echo "MenuTreeDO search rule is $searchRule";
234		//print_r($m); exit;
235		$n = count($m[1]);
236		$hasPId = 0;
237		$keyvals = array();
238		for($i=0; $i<$n; $i++) {
239			if ($m[1][$i]=='PId'){ $hasPId=1; $PId = str_replace("'","",$m[2][$i]); }
240			else $keyvals[$m[1][$i]] = str_replace("'","",$m[2][$i]);
241		}
242		if (!$hasPId) {
243			return parent::directFetch($searchRule);
244		}
245		if (!$PId) $PId = "__root__";
246		$menuItemIds = self::$fullMenuTree[$PId]['children'];
247		$rs = array();
248		if (empty($menuItemIds)) return $rs;
249		foreach ($menuItemIds as $mId) {
250			$rec = self::$fullMenuTree[$mId];
251			$matched = true;
252			foreach ($keyvals as $k=>$v) {
253				if ($rec[$k] != $v) { $matched = false; break; }
254			}
255			if ($matched) $rs[] = self::$fullMenuTree[$mId];
256		}
257		//print_r($rs);
258		return $rs;
259	}
260	
261	protected function loadFullMenuTree()
262	{
263		if (self::$fullMenuTree != null) return;
264		$cache_id = 'FULL_MENU_LIST';
265		$cacheSvc = BizSystem::getService(CACHE_SERVICE,1);
266		$cacheSvc->init($this->m_Name, 600);	// cache for 10 mins
267		if($cacheSvc->test($cache_id))
268		{
269			self::$fullMenuTree = $cacheSvc->load($cache_id);
270			return;
271		}
272		$rs = parent::directFetch();
273		foreach($rs as $record)
274		{
275			if (empty($record['PId'])) $record['PId'] = "__root__";
276			unset($record['create_by']);
277			unset($record['create_time']);
278			unset($record['update_by']);
279			unset($record['update_time']);
280			unset($record['name']); unset($record['parent']);
281			self::$fullMenuTree[$record['Id']] = $record;
282		}
283		foreach(self::$fullMenuTree as $mId=>$record)
284		{
285			self::$fullMenuTree[$record['PId']]['children'][] = $mId;
286		}
287		//print_r(self::$fullMenuTree);
288		$cacheSvc->save(self::$fullMenuTree,$cache_id);
289		// put it in apc or file cache
290	}
291}
292
293?>