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