PageRenderTime 46ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/webgets/menu.php

https://bitbucket.org/navigatecms/navigatecms
PHP | 637 lines | 460 code | 108 blank | 69 comment | 97 complexity | 63117a5ff5f65c50221f077d4608714b MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-2.1, BSD-3-Clause, AGPL-3.0, Apache-2.0
  1. <?php
  2. nvweb_webget_load('properties');
  3. function nvweb_menu($vars=array())
  4. {
  5. global $website;
  6. global $DB;
  7. global $structure;
  8. global $current;
  9. $out = '';
  10. nvweb_menu_load_dictionary();
  11. nvweb_menu_load_routes();
  12. nvweb_menu_load_structure();
  13. nvweb_menu_load_actions();
  14. $parent = intval(@$vars['parent']) + 0;
  15. $from = intval(@$vars['from']) + 0;
  16. $of = intval(@$vars['of']) + 0;
  17. if(isset($vars['parent']) && !is_numeric($vars['parent']))
  18. {
  19. // assume parent attribute contains a property_id which has the category value
  20. $parent_property = nvweb_properties(array(
  21. 'property' => $vars['parent']
  22. ));
  23. if(!empty($parent_property))
  24. $parent = $parent_property;
  25. }
  26. if($of > 0)
  27. {
  28. // get options of the parent x in the order of the structure
  29. // example:
  30. // Home [5] Products [6] Contact [7]
  31. // |
  32. // -- Computers [8] Mobile Phones [9]
  33. // |
  34. // -- Apple [10] Dell [11]
  35. //
  36. // we want the categories under Products [6]: "Computers" [8] and "Mobile Phones" [9]
  37. // of: 2 (second item in the main structure)
  38. // <nv object="nvweb" name="menu" of="2" />
  39. $parent = $structure['cat-0'][intval($of)-1]->id;
  40. }
  41. if(empty($current['hierarchy'])) // calculate
  42. {
  43. $inverse_hierarchy = array();
  44. // discover the parent from which get the menu
  45. if(!empty($current['category']))
  46. {
  47. $inverse_hierarchy[] = $current['category'];
  48. $last = $current['category'];
  49. }
  50. else
  51. {
  52. $inverse_hierarchy[] = $current['object']->category;
  53. $last = $current['object']->category;
  54. }
  55. // get category parents until root (to know how many levels count from)
  56. while($last > 0)
  57. {
  58. $last = $DB->query_single('parent', 'nv_structure', ' id = '.protect($last));
  59. $inverse_hierarchy[] = $last;
  60. }
  61. $current['hierarchy'] = array_reverse($inverse_hierarchy);
  62. }
  63. if($from > 0)
  64. {
  65. // get a certain level of the menu based on the path to current item category with offset
  66. // example:
  67. // Home [5] Products [6] Contact [7]
  68. // |
  69. // -- Computers [8] Mobile Phones [9]
  70. // |
  71. // -- Apple [10] Dell [11]
  72. //
  73. // current item is a Dell computer (category = 11)
  74. // we want the menu from level 1
  75. // from: 1 --> 8, 9
  76. $parent = $current['hierarchy'][$from];
  77. if(is_null($parent)) return ''; // the requested level of menu does not exist under the current category
  78. }
  79. $option = -1;
  80. if(isset($vars['option']))
  81. $option = intval($vars['option']);
  82. if($vars['mode']=='next' || $vars['mode']=='previous')
  83. $out = nvweb_menu_render_arrow($vars);
  84. else
  85. {
  86. $out = nvweb_menu_generate($vars['mode'], $vars['levels'], $parent, 0, $option, $vars['class']);
  87. if($vars['mode'] == 'select')
  88. {
  89. nvweb_after_body('js', '
  90. // jQuery required
  91. $("select.menu_level_0").off("change").on("change", function()
  92. {
  93. var option = $(this).find("option[value=" + $(this).val() + "]");
  94. if($(option).attr("target") == "_blank")
  95. window.open($(option).attr("href"));
  96. else
  97. {
  98. if($(option).attr("href")=="#")
  99. window.location.replace($(option).attr("href") + "sid_" + $(option).attr("value"));
  100. else
  101. window.location.replace($(option).attr("href"));
  102. }
  103. });
  104. ');
  105. }
  106. }
  107. return $out;
  108. }
  109. function nvweb_menu_generate($mode='ul', $levels=0, $parent=0, $level=0, $option=-1, $class='')
  110. {
  111. global $structure;
  112. global $current;
  113. $out = '';
  114. if($level >= $levels && $levels > 0)
  115. return '';
  116. nvweb_menu_load_structure($parent);
  117. if(!empty($structure['cat-'.$parent]))
  118. {
  119. switch($mode)
  120. {
  121. case 'category_title':
  122. case 'current_title':
  123. if($current['type']=='structure')
  124. $out = $structure['dictionary'][$current['category']];
  125. else if($current['type']=='item')
  126. $out = $structure['dictionary'][$current['object']->category];
  127. break;
  128. case 'category_link':
  129. case 'category_url':
  130. if($current['type']=='structure')
  131. $out = nvweb_source_url('structure', $current['category']);
  132. else if($current['type']=='item')
  133. $out = nvweb_source_url('structure', $current['object']->category);
  134. else
  135. $out = '#';
  136. break;
  137. case 'a':
  138. $out[] = '<div class="menu_level_'.$level.' '.$class.'">';
  139. for($m=0; $m < count($structure['cat-'.$parent]); $m++)
  140. {
  141. if(!nvweb_object_enabled($structure['cat-'.$parent][$m]))
  142. continue;
  143. if($structure['cat-'.$parent][$m]->visible == 0)
  144. continue;
  145. $mid = $structure['cat-'.$parent][$m]->id;
  146. // hide menu items without a title
  147. if(empty($structure['dictionary'][$mid]))
  148. continue;
  149. $aclass = '';
  150. if(in_array($mid, $current['hierarchy']))
  151. $aclass = ' class="menu_option_active"';
  152. $out[] = '<a'.$aclass.' '.nvweb_menu_action($mid).'>'.$structure['dictionary'][$mid].'</a>';
  153. if($option==$m)
  154. return array_pop($out);
  155. $out[] = nvweb_menu_generate($mode, $levels, $mid, $level+1);
  156. }
  157. $out[] = '</div>';
  158. $out = implode("\n", $out);
  159. break;
  160. case 'select':
  161. $out[] = '<select class="menu_level_'.$level.' '.$class.'">';
  162. for($m=0; $m < count($structure['cat-'.$parent]); $m++)
  163. {
  164. if(!nvweb_object_enabled($structure['cat-'.$parent][$m]))
  165. continue;
  166. if($structure['cat-'.$parent][$m]->visible == 0)
  167. continue;
  168. $mid = $structure['cat-'.$parent][$m]->id;
  169. // hide menu items without a title
  170. if(empty($structure['dictionary'][$mid]))
  171. continue;
  172. $aclass = '';
  173. if(in_array($mid, $current['hierarchy']))
  174. $aclass = ' class="menu_option_active" selected="selected"';
  175. $target = '';
  176. $act = nvweb_menu_action($mid, NULL, false, false);
  177. if(strpos($act, 'target="_blank"')!==false)
  178. $target = 'target="_blank"';
  179. if(strpos($act, 'onclick')!==false)
  180. $act = '#';
  181. $act = str_replace('target="_blank"', '', $act);
  182. $act = str_replace('data-sid', 'data_sid', $act);
  183. $act = str_replace('href="', '', $act);
  184. $act = str_replace('"', '', $act);
  185. $act = trim($act);
  186. $out[] = '<option'.$aclass.' value="'.$mid.'" href="'.$act.'" '.$target.'>'
  187. .$structure['dictionary'][$mid]
  188. .'</option>';
  189. if($option==$m)
  190. return array_pop($out);
  191. $submenu = nvweb_menu_generate($mode, $levels, $mid, $level+1);
  192. $submenu = strip_tags($submenu, '<option>');
  193. $parts = explode('>', $submenu);
  194. $submenu = '';
  195. for($p=0; $p < count($parts); $p++)
  196. {
  197. if(strpos($parts[$p], '</option')!==false)
  198. $parts[$p] = '&ndash;&nbsp;'.$parts[$p];
  199. }
  200. $submenu = implode('>', $parts);
  201. $out[] = $submenu;
  202. }
  203. $out[] = '</select>';
  204. $out = implode("\n", $out);
  205. break;
  206. default:
  207. case 'ul':
  208. $ul_items = 0;
  209. $out[] = '<ul class="menu_level_'.$level.' '.$class.'">';
  210. for($m=0; $m < count($structure['cat-'.$parent]); $m++)
  211. {
  212. if(!nvweb_object_enabled($structure['cat-'.$parent][$m]))
  213. continue;
  214. if($structure['cat-'.$parent][$m]->visible == 0)
  215. continue;
  216. $mid = $structure['cat-'.$parent][$m]->id;
  217. // hide menu items without a title
  218. if(empty($structure['dictionary'][$mid]))
  219. continue;
  220. $aclass = '';
  221. if(in_array($mid, $current['hierarchy']))
  222. $aclass = ' class="menu_option_active"';
  223. $out[] = '<li'.$aclass.'>';
  224. $out[] = '<a'.$aclass.' '.nvweb_menu_action($mid).'>'.$structure['dictionary'][$mid].'</a>';
  225. if($option==$m)
  226. return array_pop($out);
  227. $out[] = nvweb_menu_generate($mode, $levels, $mid, $level+1);
  228. $out[] = '</li>';
  229. $ul_items++;
  230. }
  231. $out[] = '</ul>';
  232. if($ul_items==0) // no option found, remove the last two lines (<ul> and </ul>)
  233. {
  234. array_pop($out);
  235. array_pop($out);
  236. }
  237. $out = implode("\n", $out);
  238. break;
  239. }
  240. }
  241. return $out;
  242. }
  243. function nvweb_menu_action($id, $force_type=NULL, $use_javascript=true, $include_datasid=true)
  244. {
  245. global $structure;
  246. global $current;
  247. $type = $structure['actions'][$id]['action-type'];
  248. if(!empty($force_type))
  249. $type = $force_type;
  250. switch($type)
  251. {
  252. case 'url':
  253. $url = $structure['routes'][$id];
  254. if(empty($url))
  255. {
  256. if($use_javascript)
  257. $url = 'javascript: return false;';
  258. else
  259. $url = '#';
  260. }
  261. else
  262. $url = nvweb_prepare_link($url);
  263. $action = ' href="'.$url.'" ';
  264. if($include_datasid)
  265. $action.= ' data-sid="'.$id.'" ';
  266. break;
  267. case 'jump-branch':
  268. // we force only one jump to avoid infinite loops (caused by user mistake)
  269. $action = nvweb_menu_action($structure['actions'][$id]['action-jump-branch'], 'url');
  270. break;
  271. case 'jump-item':
  272. $url = nvweb_source_url('item', $structure['actions'][$id]['action-jump-item'], $current['lang']);
  273. if(empty($url))
  274. {
  275. if($use_javascript)
  276. $url = 'javascript: return false;';
  277. else
  278. $url = '#';
  279. }
  280. else
  281. $url = nvweb_prepare_link($url);
  282. $action = ' href="'.$url.'" ';
  283. if($include_datasid)
  284. $action.= ' data-sid="'.$id.'" ';
  285. break;
  286. case 'do-nothing':
  287. $action = ' href="#" onclick="javascript: return false;" ';
  288. if($include_datasid)
  289. $action.= ' data-sid="'.$id.'" ';
  290. break;
  291. default:
  292. // Navigate CMS < 1.6.5 compatibility [deprecated]
  293. // will be removed by 1.7
  294. $url = $structure['routes'][$id];
  295. if(substr($url, 0, 7)=='http://' || substr($url, 0, 7)=='https://')
  296. {
  297. $action = ' href="'.$url.'" target="_blank" ';
  298. if($include_datasid)
  299. $action.= ' data-sid="'.$id.'" ';
  300. return $action; // ;)
  301. }
  302. else if(empty($url))
  303. {
  304. $action = ' href="#" onclick="return false;" ';
  305. if($include_datasid)
  306. $action.= ' data-sid="'.$id.'" ';
  307. return $action;
  308. }
  309. else
  310. {
  311. $action = ' href="'.NVWEB_ABSOLUTE.$url.'"';
  312. if($include_datasid)
  313. $action.= ' data-sid="'.$id.'" ';
  314. return $action;
  315. }
  316. break;
  317. }
  318. if($structure['actions'][$id]['action-new-window']=='1' && $type!='do-nothing')
  319. $action .= ' target="_blank"';
  320. return $action;
  321. }
  322. function nvweb_menu_load_dictionary()
  323. {
  324. global $DB;
  325. global $structure;
  326. global $current;
  327. global $website;
  328. if(empty($structure['dictionary']))
  329. {
  330. $structure['dictionary'] = array();
  331. $DB->query('SELECT node_id, text
  332. FROM nv_webdictionary
  333. WHERE node_type = "structure"
  334. AND subtype = "title"
  335. AND lang = '.protect($current['lang']).'
  336. AND website = '.$website->id);
  337. $data = $DB->result();
  338. if(!is_array($data)) $data = array();
  339. $dictionary = array();
  340. foreach($data as $item)
  341. {
  342. $structure['dictionary'][$item->node_id] = $item->text;
  343. }
  344. }
  345. }
  346. function nvweb_menu_load_routes()
  347. {
  348. global $DB;
  349. global $structure;
  350. global $current;
  351. global $website;
  352. if(empty($structure['routes']))
  353. {
  354. $structure['routes'] = array();
  355. $DB->query('SELECT object_id, path
  356. FROM nv_paths
  357. WHERE type = "structure"
  358. AND lang = '.protect($current['lang']).'
  359. AND website = '.$website->id);
  360. $data = $DB->result();
  361. if(!is_array($data)) $data = array();
  362. $dictionary = array();
  363. foreach($data as $item)
  364. {
  365. $structure['routes'][$item->object_id] = $item->path;
  366. }
  367. }
  368. }
  369. function nvweb_menu_load_actions()
  370. {
  371. global $DB;
  372. global $structure;
  373. global $current;
  374. global $website;
  375. if(empty($structure['actions']))
  376. {
  377. $structure['actions'] = array();
  378. $DB->query('SELECT node_id, subtype, text
  379. FROM nv_webdictionary
  380. WHERE node_type = "structure"
  381. AND lang = '.protect($current['lang']).'
  382. AND subtype IN("action-type", "action-jump-item", "action-jump-branch", "action-new-window")
  383. AND website = '.$website->id);
  384. $data = $DB->result();
  385. if(!is_array($data)) $data = array();
  386. $dictionary = array();
  387. foreach($data as $row)
  388. {
  389. $structure['actions'][$row->node_id][$row->subtype] = $row->text;
  390. }
  391. }
  392. }
  393. function nvweb_menu_load_structure($parent=0)
  394. {
  395. global $DB;
  396. global $structure;
  397. global $website;
  398. if(!isset($structure['cat-'.$parent]))
  399. {
  400. $structure['cat-'.$parent] = array();
  401. $DB->query('SELECT *
  402. FROM nv_structure
  403. WHERE parent = '.protect($parent).'
  404. AND website = '.$website->id.'
  405. ORDER BY position ASC');
  406. $structure['cat-'.$parent] = $DB->result();
  407. // parse some result values
  408. foreach($structure['cat-'.$parent] as $key => $value)
  409. {
  410. $value->groups = str_replace('g', '', $value->groups);
  411. $value->groups = array_filter(explode(',', $value->groups));
  412. $structure[$key] = clone $value;
  413. }
  414. }
  415. }
  416. function nvweb_menu_get_children($categories=array(), $sublevels=NULL)
  417. {
  418. global $structure;
  419. // get all leafs from all categories that are child of the selected ones
  420. $categories_count = count($categories);
  421. $depth = array();
  422. for($c=0; $c < $categories_count; $c++)
  423. {
  424. $categories[$c] = trim($categories[$c]);
  425. if(empty($categories[$c]) && $categories[$c]!='0')
  426. continue;
  427. if(!isset($depth[$categories[$c]]))
  428. $depth[$categories[$c]] = 0;
  429. nvweb_menu_load_structure($categories[$c]);
  430. for($s=0; $s < count($structure['cat-'.$categories[$c]]); $s++)
  431. {
  432. $depth[$structure['cat-'.$categories[$c]][$s]->id] = $depth[$categories[$c]] + 1;
  433. // the current category is beyond the allowed number of sublevels on hierarchy?
  434. if(isset($sublevels) && $depth[$structure['cat-'.$categories[$c]][$s]->id] > $sublevels)
  435. continue;
  436. array_push($categories, $structure['cat-'.$categories[$c]][$s]->id);
  437. }
  438. $categories = array_unique($categories); // remove duplicates
  439. $categories_count = count($categories); // recount elements
  440. }
  441. return $categories;
  442. }
  443. function nvweb_menu_render_arrow($vars=array())
  444. {
  445. global $DB;
  446. global $structure;
  447. global $current;
  448. global $website;
  449. $out = '';
  450. $char = $vars['character'];
  451. $link = '';
  452. $title = '';
  453. $previous = null;
  454. $next = null;
  455. $parent = null;
  456. // look for the category before and after the current one
  457. if($current['type']=='structure')
  458. $parent = $current['object']->parent;
  459. else if($current['category'] > 0)
  460. $parent = $current['hierarchy'][count($current['category'])-1];
  461. // if we have found the parent
  462. // AND
  463. // if the "from" option is not empty AND the number of levels until the current category is greater than "from"
  464. if( $parent >= 0 &&
  465. (!empty($vars['from']) && count($current['hierarchy']) >= $vars['from']))
  466. {
  467. nvweb_menu_load_structure($parent);
  468. for($c=0; $c < count($structure['cat-'.$parent]); $c++)
  469. {
  470. if($structure['cat-'.$parent][$c]->id == $current['category'])
  471. {
  472. if(isset($structure['cat-'.$parent][$c-1]))
  473. $previous = $structure['cat-'.$parent][$c-1]->id;
  474. if(isset($structure['cat-'.$parent][$c+1]))
  475. $next = $structure['cat-'.$parent][$c+1]->id;
  476. break;
  477. }
  478. }
  479. // TO DO: look for previous and next categories from the parent's brothers
  480. /*
  481. if(empty($previous))
  482. {
  483. // we have not found a PREVIOUS structure entry in the same level of the current category
  484. // we may look for the last child of the parent brother... example
  485. /*
  486. * ROOT
  487. * 1
  488. * 2
  489. * 2.1
  490. * 2.1.1
  491. * 2.1.2
  492. * 2.2
  493. * 2.2.1 <- current category
  494. * 2.2.2
  495. * 2.3
  496. * 2.3.1
  497. * 3
  498. *
  499. * in this example, the previous category of 2.2.1 is 2.1.2
  500. * if the current category is 2.2.2, the next one will be the children of the next parent, so, 2.3.1
  501. */
  502. /*
  503. }
  504. /*
  505. if(empty($next))
  506. {
  507. }
  508. */
  509. if($vars['mode']=='next' && !empty($next))
  510. {
  511. if(empty($char))
  512. $char = '&gt;';
  513. $link = $structure['routes'][$next];
  514. $title = $structure['dictionary'][$next];
  515. }
  516. else if($vars['mode']=='previous' && !empty($previous))
  517. {
  518. if(empty($char))
  519. $char = '&lt;';
  520. $link = $structure['routes'][$previous];
  521. $title = $structure['dictionary'][$previous];
  522. }
  523. if(!empty($link))
  524. $out = '<a href="'.$link.'" title="'.$title.'">'.$char.'</a>';
  525. }
  526. return $out;
  527. }
  528. ?>