PageRenderTime 71ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/html/AppCode/expressionengine/third_party/structure/mod.structure.php

https://github.com/w3bg/www.hsifin.com
PHP | 3653 lines | 3190 code | 262 blank | 201 comment | 250 complexity | 035d48e9d548e1b2fa2c013355fec5a0 MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. error_reporting(0);
  3. ini_set('display_errors', FALSE);
  4. /**
  5. * Control Panel (MCP) File for Structure
  6. *
  7. * This file must be in your /system/third_party/structure directory of your ExpressionEngine installation
  8. *
  9. * @package Structure 2 for EE2 (Build 20100824)
  10. * @author Jack McDade (jack@jackmcdade.com)
  11. * @author Travis Schmeisser (travis@rockthenroll.com)
  12. * @copyright Copyright (c) 2010 Travis Schmeisser
  13. * @version Release: 2.1.5
  14. * @link http://buildwithstructure.com
  15. */
  16. // Thanks also to Tom Jaeger, Jeremy Messenger, Brian Litzinger and Adam Leder for their code contributions.
  17. require('libraries/nestedset/structure_nestedset.php');
  18. require('libraries/nestedset/structure_nestedset_adapter_ee.php');
  19. class Structure
  20. {
  21. var $nset;
  22. var $channel_type = '';
  23. function Structure()
  24. {
  25. $this->EE =& get_instance();
  26. $adapter = new Structure_Nestedset_Adapter_Ee('exp_structure', 'lft', 'rgt', 'entry_id');
  27. $this->nset = new Structure_Nestedset($adapter);
  28. }
  29. /** -------------------------------------
  30. /** Tag: nav_main
  31. /** -------------------------------------*/
  32. function nav_main()
  33. {
  34. $html = "";
  35. $site_id = $this->EE->config->item('site_id');
  36. // get current uri path
  37. $uri = $this->EE->uri->uri_string;
  38. $separator = $this->EE->config->item('word_separator') != 'dash' ? '_' : '-';
  39. $css_id = $this->EE->TMPL->fetch_param('css_id');
  40. // Set unique id prefix
  41. if ($css_id == NULL)
  42. $unique_prefix = 'nav';
  43. else
  44. $unique_prefix = $css_id;
  45. // Remove the id tag if set to "none"
  46. if ($css_id == "")
  47. $css_id = ' id="nav"';
  48. elseif ($css_id == "none")
  49. $css_id = NULL;
  50. else
  51. $css_id = ' id="'.$css_id.'"';
  52. $add_unique_id = $this->EE->TMPL->fetch_param('add_unique_id');
  53. $add_unique_id = $add_unique_id ? strtolower($add_unique_id) : 'no';
  54. $add_unique_to = ($this->EE->TMPL->fetch_param('add_unique_to')) ? $this->EE->TMPL->fetch_param('nav_class') : 'li';
  55. $current_class = ($this->EE->TMPL->fetch_param('current_class')) ? $this->EE->TMPL->fetch_param('current_class') : 'here';
  56. $include_ul = ($this->EE->TMPL->fetch_param('include_ul')) ? $this->EE->TMPL->fetch_param('include_ul') : 'yes';
  57. $add_span = ($this->EE->TMPL->fetch_param('add_span')) ? $this->EE->TMPL->fetch_param('add_span') : 'no';
  58. // CSS class
  59. $css_class = $this->EE->TMPL->fetch_param('css_class');
  60. $css_class = $css_class ? $css_class : '';
  61. // exclude and include entry_ids
  62. $exclude = explode("|", $this->EE->TMPL->fetch_param('exclude'));
  63. $include = ($this->EE->TMPL->fetch_param('include')) ? " AND `node`.`entry_id` IN(".str_replace("|", ",", $this->EE->TMPL->fetch_param('include')).") " : "";
  64. // DEPRECIATED SUPPORT for exclude_status and include_status
  65. $include_status = strtolower($this->EE->TMPL->fetch_param('include_status'));
  66. $exclude_status = strtolower($this->EE->TMPL->fetch_param('exclude_status'));
  67. // New, native EE status mode
  68. $status = $this->EE->TMPL->fetch_param('status');
  69. $status = $status == '' ? array() : explode('|', $status);
  70. $status = array_map('strtolower', $status); // match MySQL's case-insensitivity
  71. $status_state = 'positive';
  72. // Check for "not "
  73. if (substr($status[0], 0, 4) == 'not ')
  74. {
  75. $status_state = 'negative';
  76. $status[0] = trim(substr($status[0], 3));
  77. $status[] = 'closed';
  78. }
  79. else
  80. {
  81. $status[] = 'open';
  82. }
  83. $include_status_list = explode('|', $include_status);
  84. $exclude_status_list = explode('|', $exclude_status);
  85. // Remove the default "open" status if explicitely set
  86. if (in_array('open', $exclude_status_list))
  87. $status = array_filter($status, create_function('$v', 'return $v != "open";'));
  88. if ($status_state == 'positive')
  89. $status = array_merge($status, $include_status_list);
  90. elseif ($status_state == 'negative')
  91. $status = array_merge($status, $exclude_status_list);
  92. // get site pages data
  93. $site_pages = $this->get_site_pages();
  94. // get structure data from DB
  95. $sql = "SELECT node.*, expt.title, expt.status
  96. FROM exp_structure AS node
  97. INNER JOIN exp_channel_titles AS expt
  98. ON node.entry_id = expt.entry_id
  99. WHERE node.parent_id = 0
  100. AND node.site_id = $site_id {$include}
  101. GROUP BY node.entry_id
  102. ORDER BY node.lft";
  103. $result = $this->EE->db->query($sql);
  104. // Remove anything to be excluded from the results array
  105. foreach ($result->result_array() as $key => $entry_data)
  106. {
  107. if ($status_state == 'negative' && in_array(strtolower($entry_data['status']), $status)
  108. || ($status_state == 'positive' && ! in_array(strtolower($entry_data['status']), $status))
  109. || in_array($entry_data['entry_id'], $exclude))
  110. {
  111. unset($result->result_array[$key]);
  112. }
  113. }
  114. // Make sure array indices are incremental (0..X)
  115. // $result->result_array() = array_values($result->result_array());
  116. $segment_1 = $this->EE->uri->segment('1');
  117. if (count($result->num_rows()) > 0)
  118. {
  119. foreach ($result->result_array() as $entry_data)
  120. {
  121. // out entry uri of this loop instance
  122. $euri = $site_pages['uris'][$entry_data['entry_id']];
  123. $slug = $this->page_slug($entry_data['entry_id']);
  124. if ($slug == '')
  125. $slug = 'home';
  126. if ($separator == '_')
  127. {
  128. $slug = str_replace('-', $separator, $slug);
  129. }
  130. elseif ($separator == '-')
  131. {
  132. $slug = str_replace('_', $separator, $slug);
  133. }
  134. $a_class = '';
  135. $li_class = '';
  136. $list_item_id = '';
  137. // if we are adding the unique slug to the anchor
  138. // *!*!*!*!*!*!* Possibly Remove This
  139. if ($add_unique_to == 'a')
  140. {
  141. $a_class .= 'nav' . $separator . $slug;
  142. }
  143. // else
  144. else
  145. {
  146. // $li_class .= 'nav' . $separator . $slug;
  147. }
  148. if ($uri === $euri OR ($uri == '' && $euri == '/') OR $segment_1 === trim($euri, '/'))
  149. {
  150. $here = TRUE;
  151. $current_entry = $entry_data['entry_id'];
  152. $li_class .= ' ' . $current_class;
  153. }
  154. if ($entry_data == end($result->result_array()))
  155. {
  156. $li_class .= ' last';
  157. }
  158. $li_class = empty($li_class) ? '' : " class=\"".trim($li_class)."\"";
  159. $a_class = empty($a_class) ? "" : " class=\"".trim($a_class)."\"";
  160. // Make sure we have the site_url path in case we're operating in a subdirectory
  161. // If site_index is set then add it to URIs, otherwise leave it blank
  162. $site_url = $this->EE->functions->fetch_site_index();
  163. $the_uri = parse_url($this->EE->db->escape_str($site_url));
  164. $root_uri = $the_uri['path'];
  165. $index_uri = $site_url;
  166. $home = trim($this->EE->functions->fetch_site_index(0, 0), '/');
  167. $item_uri = $this->EE->functions->remove_double_slashes($home . $euri);
  168. if ($add_unique_id == 'yes')
  169. {
  170. $list_item_id = ' id="'. $unique_prefix . $separator . $slug .'"';
  171. }
  172. $title = htmlspecialchars($entry_data['title']);
  173. // Add a <span> wrapper inside the <a> tags
  174. if ($add_span == 'yes')
  175. {
  176. $html .= "\n<li{$li_class}{$list_item_id}><a href=\"" . $item_uri . "\"{$a_class}><span>" . $title."</span></a></li>";
  177. }
  178. else
  179. {
  180. $html .= "\n<li{$li_class}{$list_item_id}><a href=\"" . $item_uri . "\"{$a_class}>" . $title."</a></li>";
  181. }
  182. }
  183. $css_class = ($this->EE->TMPL->fetch_param('css_class')) ? " class=\"" . $this->EE->TMPL->fetch_param('css_class') . "\"" : "";
  184. // Add or remove the <ul> wrapper
  185. if ($include_ul == 'yes')
  186. {
  187. $html = "<ul{$css_id}{$css_class}>" . $html . "\n</ul>";
  188. }
  189. }
  190. return $html;
  191. }
  192. /** -------------------------------------
  193. /** Tag: nav_sub
  194. /** -------------------------------------*/
  195. function nav_sub()
  196. {
  197. $html = '';
  198. // get site pages data
  199. $site_pages = $this->get_site_pages();
  200. if ( ! $site_pages) return FALSE;
  201. /** -------------------------------------
  202. /** The Parameters
  203. /** -------------------------------------*/
  204. $separator = $this->EE->config->item('word_separator') != 'dash' ? '_' : '-';
  205. $exclude = explode('|', $this->EE->TMPL->fetch_param('exclude'));
  206. // DEPRECIATED SUPPORT for exclude_status and include_status
  207. $include_status = strtolower($this->EE->TMPL->fetch_param('include_status'));
  208. $exclude_status = strtolower($this->EE->TMPL->fetch_param('exclude_status'));
  209. // New, native EE status mode
  210. $status = $this->EE->TMPL->fetch_param('status');
  211. $status = $status == '' ? array() : explode('|', $status);
  212. $status = array_map('strtolower', $status); // match MySQL's case-insensitivity
  213. $status_state = 'positive';
  214. // Check for "not "
  215. if (substr($status[0], 0, 4) == 'not ')
  216. {
  217. $status_state = 'negative';
  218. $status[0] = trim(substr($status[0], 3));
  219. $status[] = 'closed';
  220. }
  221. else
  222. {
  223. $status[] = 'open';
  224. }
  225. $include_status_list = explode('|', $include_status);
  226. $exclude_status_list = explode('|', $exclude_status);
  227. // Remove the default "open" status if explicitely set
  228. if (in_array('open', $exclude_status_list))
  229. $status = array_filter($status, create_function('$v', 'return $v != "open";'));
  230. if ($status_state == 'positive')
  231. $status = array_merge($status, $include_status_list);
  232. elseif ($status_state == 'negative')
  233. $status = array_merge($status, $exclude_status_list);
  234. $include_ul = ($this->EE->TMPL->fetch_param('include_ul')) ? $this->EE->TMPL->fetch_param('include_ul') : 'yes';
  235. $add_span = ($this->EE->TMPL->fetch_param('add_span')) ? $this->EE->TMPL->fetch_param('add_span') : 'no';
  236. $css_id = $this->EE->TMPL->fetch_param('css_id') ? $this->EE->TMPL->fetch_param('css_id') : '';
  237. if ($css_id == '')
  238. {
  239. $css_id = 'nav'.$separator.'sub';
  240. }
  241. elseif ($css_id == 'none')
  242. {
  243. $css_id = NULL;
  244. }
  245. else
  246. {
  247. $css_id = $css_id;
  248. }
  249. // CSS class
  250. $css_class = $this->EE->TMPL->fetch_param('css_class');
  251. $css_class = $css_class ? $css_class : '';
  252. // Current CSS class
  253. $current_class = ($this->EE->TMPL->fetch_param('current_class')) ? $this->EE->TMPL->fetch_param('current_class') : 'here';
  254. // show_level_classes
  255. $show_level_classes = $this->EE->TMPL->fetch_param('show_level_classes');
  256. $show_level_classes = $show_level_classes ? strtolower($show_level_classes) : 'yes';
  257. // show_overview_link
  258. $show_overview_link = $this->EE->TMPL->fetch_param('show_overview_link');
  259. $show_overview_link = $show_overview_link ? strtolower($show_overview_link) : 'no';
  260. // Custom View Text
  261. $overview_text_title = $this->EE->TMPL->fetch_param('show_overview_link');
  262. $overview_text_title = $overview_text_title ? strtolower($overview_text_title) : 'no';
  263. // Rename Overview parameter
  264. $overview_link_text = $this->EE->TMPL->fetch_param('rename_overview');
  265. $overview_link_text = $overview_link_text ? $overview_link_text : 'Overview';
  266. // Add CSS ids based on the URI to all <li> elements
  267. $add_unique_id = $this->EE->TMPL->fetch_param('add_unique_id');
  268. $add_unique_id = $add_unique_id ? strtolower($add_unique_id) : 'no';
  269. // Add CSS ids based on the entry_id to all <li> elements
  270. $add_unique_entry_id = $this->EE->TMPL->fetch_param('add_unique_entry_id');
  271. $add_unique_entry_id = $add_unique_entry_id ? strtolower($add_unique_entry_id) : 'no';
  272. $wrap_start = $this->EE->TMPL->fetch_param('wrap_start');
  273. $wrap_start = $wrap_start ? $wrap_start : 'no';
  274. $wrap_end = $this->EE->TMPL->fetch_param('wrap_end');
  275. $wrap_end = $wrap_end ? $wrap_end : 'no';
  276. // Hide the entire sub nav if there are no children of the current page
  277. $hide_if_no_children = ($this->EE->TMPL->fetch_param('hide_if_no_children')) ? $this->EE->TMPL->fetch_param('hide_if_no_children') : 'no';
  278. $initiate_children_hiding = 'no';
  279. // depth to limit, never expand past this depth
  280. $depth_limit = $this->EE->TMPL->fetch_param('limit_depth');
  281. $depth_limit = $depth_limit ? $depth_limit : '';
  282. // depth to show, show all of tree up to specified depth
  283. $show_n_deep = $this->EE->TMPL->fetch_param('show_depth');
  284. $show_n_deep = ($show_n_deep != '') ? $show_n_deep : '';
  285. // special case to make the math work, if passing 0 then calculate based on -1
  286. if ($show_n_deep <= 0 && $show_n_deep != '')
  287. {
  288. $show_n_deep = -1;
  289. }
  290. // Retrieve start_from URL
  291. $start_from = $this->EE->TMPL->fetch_param('start_from');
  292. $start_from = $start_from ? $start_from : '';
  293. /** -------------------------------------
  294. /** The Logic
  295. /** -------------------------------------*/
  296. $fixed = false;
  297. if ($start_from != '')
  298. {
  299. $start_from = html_entity_decode($start_from);
  300. // Make sure passed URL starts with a '/'
  301. if (substr($start_from, 0, 1) != '/')
  302. {
  303. $start_from = '/' . $start_from;
  304. }
  305. // Make sure passed URL ends with a '/'
  306. if (substr($start_from, -1, 1) != '/')
  307. {
  308. $start_from .= '/';
  309. }
  310. $fixed = true;
  311. }
  312. $uri = '/'.$this->EE->uri->uri_string().'/';
  313. // get entry id + node of the start entry
  314. $entry_id = $start_from ? array_search($start_from, $site_pages['uris']) : array_search($uri, $site_pages['uris']);
  315. $node = $entry_id ? $this->nset->getNode($entry_id) : false;
  316. // get entry id + node of the current entry
  317. $current_entry_id = array_search($uri, $site_pages['uris']);
  318. $current_node = $current_entry_id ? $this->nset->getNode($current_entry_id) : false;
  319. // if current_node is a leaf then current_node should be parent
  320. if ($current_node == '' && $current_entry_id)
  321. {
  322. // get entry's parent id
  323. $pid = $this->get_pid_for_listing_entry($current_entry_id);
  324. $current_node = $this->nset->getNode($pid);
  325. }
  326. // If current location is a leaf then use parent as starting point for top + current
  327. if ($node['isLeaf'])
  328. {
  329. $leaf_node = $current_node;
  330. $node = $this->nset->getNode($node['parent_id']);
  331. $current_node = $this->nset->getNode($current_node['parent_id']);
  332. if ($hide_if_no_children == 'yes')
  333. {
  334. $initiate_children_hiding = 'yes';
  335. }
  336. elseif ($hide_if_no_children == 'conditional')
  337. {
  338. $initiate_children_hiding = 'conditional';
  339. }
  340. }
  341. // if start_from + show_depth then make sure top is treated as current
  342. if ($show_n_deep != '')
  343. {
  344. $actual_current = $current_node;
  345. $current_node = $node;
  346. }
  347. // get all pages/tree
  348. $pages = $this->get_data();
  349. // Get current parent's URI
  350. if (isset($site_pages['uris'][$node['id']]))
  351. {
  352. $top_uri = $site_pages['uris'][$node['id']];
  353. }
  354. else
  355. {
  356. $top_uri = '';
  357. }
  358. // Get current page URI
  359. if (isset($site_pages['uris'][$current_node['id']]))
  360. {
  361. $current_page_uri = $site_pages['uris'][$current_node['id']];
  362. }
  363. else
  364. {
  365. $current_page_uri = '';
  366. }
  367. $current_top_uri = $top_uri;
  368. // trim tree of uneeded branches + leaves
  369. foreach ($pages as $key => $entry_data)
  370. {
  371. // If not top level && not child of current
  372. if ($entry_data['parent_id'] != $node['id'] && $entry_data['parent_id'] != 0)
  373. {
  374. // Does entry's URI start with our current top URI
  375. if (preg_match("~^" . $current_top_uri . "~", $site_pages['uris'][$entry_data['entry_id']]))
  376. {
  377. // Only show immediate children
  378. // if the entry has depth greater than the current entry and it's parent isn't the current entry then we don't want it
  379. // if show_depth then check that items to be included are left alone
  380. if (($show_n_deep != '' && (($entry_data['depth'] - $current_node['depth']) > ($show_n_deep + 1)) && $entry_data['parent_id'] != $current_node['id'])
  381. || ($show_n_deep == '' && $entry_data['depth'] > ($current_node['depth']) && $entry_data['parent_id'] != $current_node['id'])
  382. || ($entry_data['depth'] == ($current_node['depth']) && $entry_data['parent_id'] != $current_node['parent_id']))
  383. {
  384. // Hide pages in the same branch group but at same depth. This only really applies to leaves on the end.
  385. unset($pages[$key]);
  386. }
  387. }
  388. elseif ($entry_data['parent_id'] != $current_node['parent_id'])
  389. {
  390. unset($pages[$key]);
  391. }
  392. elseif ($entry_data['parent_id'] != $current_node['id'])
  393. {
  394. // Possibly thowing errors, one way or the other. Keep flagged.
  395. unset($pages[$key]);
  396. }
  397. }
  398. elseif ($entry_data['parent_id'] == 0)
  399. {
  400. unset($pages[$key]);
  401. }
  402. $adjust_depth = $fixed ? 1 : 0;
  403. if (isset($pages[$key]) && array_key_exists('entry_id', $pages[$key]))
  404. {
  405. $pages[$key]['depth'] -= ($node['depth'] + $adjust_depth);
  406. }
  407. }
  408. // Discover the tree of the current page
  409. // Clean up items that aren't part of the current branch
  410. $tree = array();
  411. if ($fixed && $current_node['parent_id'] != 0)
  412. {
  413. $next_id = $current_node['id'];
  414. for($x = 0; $x < $current_node['depth']; $x++)
  415. {
  416. // Build the tree for the branch
  417. foreach ($pages as $key => $page)
  418. {
  419. if ($page['entry_id'] == $next_id)
  420. {
  421. $tree[] = $page['entry_id'];
  422. $next_id = $page['parent_id'];
  423. }
  424. }
  425. }
  426. // Remove the items that aren't part of the branch
  427. // If the items parent isn't part of the tree, and the item itself isn't part of the tree, and the items parent isn't the root of the tree
  428. foreach ($pages as $key => $page)
  429. {
  430. if (($page['depth'] < 0)
  431. || ( ! in_array($page['parent_id'], $tree
  432. && ! in_array($page['entry_id'], $tree)
  433. && $page['parent_id'] != $node['id'])))
  434. {
  435. unset($pages[$key]);
  436. }
  437. }
  438. }
  439. $closed_parents = array();
  440. // Remove anything to be excluded from the results array
  441. foreach ($pages as $key => $entry_data)
  442. {
  443. if ($status_state == 'negative' && in_array(strtolower($entry_data['status']), $status)
  444. || ($status_state == 'positive' && ! in_array(strtolower($entry_data['status']), $status))
  445. || in_array($entry_data['parent_id'], $closed_parents)
  446. || in_array($entry_data['entry_id'], $exclude))
  447. {
  448. $closed_parents[] = $entry_data['entry_id'];
  449. unset($pages[$key]);
  450. }
  451. }
  452. // Make sure array indices are incremental (0..X)
  453. $pages = array_values($pages);
  454. // If our first item is not depth 0 bring everything down accordingly
  455. if (isset($pages[0]['depth']) && $pages[0]['depth'] > 0)
  456. {
  457. $adjust_depth = $pages[0]['depth'] - $node['depth'];
  458. foreach ($pages as $key => $page)
  459. {
  460. $pages[$key]['depth'] -= $adjust_depth;
  461. }
  462. }
  463. // Clean up if we have a depth parameter, remove anything deeper than the requested depth
  464. if ($depth_limit != '')
  465. {
  466. foreach ($pages as $key => $page)
  467. {
  468. if ($page['depth'] > $depth_limit)
  469. {
  470. unset($pages[$key]);
  471. }
  472. }
  473. }
  474. // Make sure array indices are incremental (0..X)
  475. $pages = array_values($pages);
  476. // If show_overview_link is true then
  477. // check if parent is top level, if true then show overview link
  478. // Get the parent of the first page. Allows us to check if it's parent is top level for the Overview link
  479. if ( ! $fixed)
  480. {
  481. $parent_node = $this->nset->getNode(@$pages[0]['parent_id']);
  482. }
  483. else
  484. {
  485. $parent_node = array('parent_id' => '');
  486. }
  487. if ($show_overview_link == "yes" && ($node['parent_id'] == 0 OR $parent_node['parent_id'] == 0))
  488. {
  489. $overview_data = ($parent_node['parent_id'] != '') ? $parent_node : $node;
  490. // Apply custom Overview title if set
  491. if ($overview_link_text)
  492. {
  493. $overview_data['title'] = $overview_link_text;
  494. }
  495. elseif ($overview_text_title)
  496. {
  497. $parent_id = $overview_data['id'];
  498. $sql = "SELECT title
  499. FROM exp_channel_titles
  500. WHERE entry_id = '".$parent_id."'";
  501. $result = $this->EE->db->query($sql);
  502. $overview_data['title'] = $result->result_array[0]['title'];
  503. }
  504. $overview_data['entry_id'] = $overview_data['id'];
  505. $overview_data['depth'] = 0;
  506. $overview_data['overview'] = "yes";
  507. array_unshift($pages, $overview_data);
  508. }
  509. // If show_depth then set the current_node back to what it should be (actual_current)
  510. if ($show_n_deep != '')
  511. {
  512. $current_node = $actual_current;
  513. }
  514. $ul_open = false;
  515. $last_page_depth = 0;
  516. $last = "";
  517. // Begin building out the tree
  518. foreach ($pages as $page)
  519. {
  520. //@@@ PHP Notice: Triggered from (assuming) empty array key. [Undefined index: 0]
  521. @$page_uri = $site_pages['uris'][$page['entry_id']];
  522. //Create unique CSS ID based on the URIs
  523. $css_uri = substr_replace(str_replace("/", "_", $page_uri) ,"",-1);
  524. $home = trim($this->EE->functions->fetch_site_index(0, 0), '/');
  525. $item_uri = $this->EE->functions->remove_double_slashes($home . $page_uri);
  526. $page['class'] = "";
  527. // Start a sub nav
  528. if ($page['depth'] > $last_page_depth)
  529. {
  530. $html = substr($html, 0, -6);
  531. $html .= "\n<ul>\n";
  532. $ul_open = true;
  533. }
  534. // Close a sub nav
  535. if ($page['depth'] < $last_page_depth)
  536. {
  537. // Calculate how many levels back I need to go
  538. $back_to = $last_page_depth - $page['depth'];
  539. $html .= str_repeat("</ul>\n</li>\n", $back_to);
  540. $ul_open = false;
  541. }
  542. $here = '';
  543. // CURRENT CLASS DETECTION
  544. // If current location/leaf is within the left/right limits of the item then this is a "here" parent item
  545. if (($current_node['left'] > @$page['lft'] && $current_node['right'] < @$page['rgt']) OR (@$leaf_node['left'] > @$page['lft'] && @$leaf_node['right'] < @$page['rgt']))
  546. {
  547. $page['class'] .= ' parent' . $separator . $current_class;
  548. }
  549. elseif ($current_node['left'] == @$page['lft'] && $current_node['right'] == @$page['rgt'] && $page['entry_id'] != $current_entry_id && $page['entry_id'] != @$leaf_node['id'])
  550. {
  551. $page['class'] .= " ".$current_class;
  552. }
  553. elseif ($page['entry_id'] == $current_entry_id OR $page['entry_id'] == @$leaf_node['id'])
  554. {
  555. $page['class'] .= " ".$current_class;
  556. }
  557. // LAST CLASS DETECTION
  558. // Grab parent item's data
  559. $upper_node = $this->nset->getNode($page['parent_id']);
  560. // If an entry's RIGHT is one less than the parent's RIGHT, is the last item in a <ul>.
  561. if ((@$page['rgt']+1) == $upper_node['right'])
  562. {
  563. $page['class'] .= " last";
  564. }
  565. // elseif ($page == end($pages))
  566. // {
  567. // $last = 'last';
  568. // }
  569. // If show_level_classes then build level class name
  570. $level = "";
  571. if ($show_level_classes == 'yes')
  572. {
  573. $page['class'] .= ' sub' . $separator . 'level' . $separator . $page['depth'];
  574. }
  575. if (isset($page['overview']) && strtolower($page['overview']) == 'yes')
  576. {
  577. $page['class'] .= ' overview';
  578. }
  579. // Build classes string
  580. $classes = array($level, $here, $last);
  581. $classes_string = '';
  582. $classes_string = trim($page['class']);
  583. $list_item_class = '';
  584. // Set current class (Don't pass an empty class)
  585. if ($classes_string != '')
  586. {
  587. $list_item_class = " class=\"$classes_string\"";
  588. }
  589. $list_item_id = "";
  590. // Add unique id to <li> elements
  591. if ($add_unique_entry_id == "yes")
  592. {
  593. $list_item_id .= ' id="'.$css_id.$separator.$page['entry_id'].'"';
  594. }
  595. if ($add_unique_id == "yes")
  596. {
  597. $list_id_contents = explode ("/", $page_uri);
  598. array_pop($list_id_contents);
  599. array_shift($list_id_contents);
  600. $seg_1 = reset($list_id_contents);
  601. $seg_2 = end($list_id_contents);
  602. $list_item_id .= ' id="'.$seg_1.$separator.$seg_2.'"';
  603. }
  604. // The IDs and Classes
  605. $li_contents = $list_item_id.''.$list_item_class;
  606. $page_title = htmlspecialchars($page['title']);
  607. if ($add_span == "yes")
  608. {
  609. $page_title = "<span>".$page_title."</span>";
  610. }
  611. // THE BIG LIST OUTPUT
  612. $list_item = '<li'.$li_contents.'><a href="'.$item_uri.'">'.$page_title.'</a></li>'."\n";
  613. $html .= $list_item;
  614. $last_page_depth = $page['depth'];
  615. }
  616. // Close any open UL + LI combos
  617. if ($ul_open)
  618. {
  619. $html .= str_repeat("</ul></li>\n", $last_page_depth);
  620. $ul_open = false;
  621. $last_page_depth--;
  622. }
  623. // Make sure all the ULs are closed
  624. if ($last_page_depth > 0)
  625. {
  626. //$html .= str_repeat("</ul>\n", $last_page_depth + 1);
  627. $html .= "</ul>\n";
  628. }
  629. elseif ($include_ul == "no")
  630. {
  631. $html .= $ul_open ? "</ul>\n</li>\n" : "\n";
  632. }
  633. else
  634. {
  635. $html .= $ul_open ? "</ul>\n</li>\n</ul>" : "</ul>\n";
  636. }
  637. // Assign classes
  638. $css_class = ($this->EE->TMPL->fetch_param('css_class')) ? " class=\"" . $this->EE->TMPL->fetch_param('css_class') . "\"" : "";
  639. // Turn on or off the <ul>
  640. if ($include_ul == "yes")
  641. {
  642. if($css_id && $css_class)
  643. {
  644. $html = "\n<ul id=\"$css_id\"{$css_class}>\n" . $html;
  645. }
  646. else if($css_id)
  647. {
  648. $html = "\n<ul id=\"$css_id\"{$css_class}>\n" . $html;
  649. }
  650. else
  651. {
  652. $html = "\n<ul{$css_class}>\n" . $html;
  653. }
  654. }
  655. if ($initiate_children_hiding == "yes")
  656. {
  657. $html = NULL;
  658. }
  659. elseif ($initiate_children_hiding == "conditional")
  660. {
  661. $html = "empty";
  662. }
  663. if ($html != "" && $wrap_start != "no" && $wrap_end != "no")
  664. {
  665. $html = $wrap_start.$html.$wrap_end;
  666. }
  667. return $html;
  668. }
  669. /** -------------------------------------
  670. /** Tag: nav_full
  671. /** -------------------------------------*/
  672. function nav_full()
  673. {
  674. $html = '';
  675. /** -------------------------------------
  676. /** PARAMETERS: HTML/CSS Based
  677. /** -------------------------------------*/
  678. $separator = $this->EE->config->item('word_separator') != 'dash' ? '_' : '-';
  679. $css_id = ($this->EE->TMPL->fetch_param('css_id')) ? "".$this->EE->TMPL->fetch_param('css_id')."" : "";
  680. $css_class = ($this->EE->TMPL->fetch_param('css_class')) ? " class=\"" . $this->EE->TMPL->fetch_param('css_class') . "\"" : "";
  681. $current_class = ($this->EE->TMPL->fetch_param('current_class')) ? $this->EE->TMPL->fetch_param('current_class') : "here";
  682. $add_span = ($this->EE->TMPL->fetch_param('add_span')) ? $this->EE->TMPL->fetch_param('add_span') : "no";
  683. $add_unique_id = $this->EE->TMPL->fetch_param('add_unique_id');
  684. $add_unique_id = $add_unique_id ? strtolower($add_unique_id) : 'no';
  685. /** -------------------------------------
  686. /** PARAMETERS: Output and Behavior
  687. /** -------------------------------------*/
  688. // DEPRECIATED SUPPORT for exclude_status and include_status
  689. $include_status = strtolower($this->EE->TMPL->fetch_param('include_status'));
  690. $exclude_status = strtolower($this->EE->TMPL->fetch_param('exclude_status'));
  691. // New, native EE status mode
  692. $status = $this->EE->TMPL->fetch_param('status');
  693. $status = $status == '' ? array() : explode('|', $status);
  694. $status = array_map('strtolower', $status); // match MySQL's case-insensitivity
  695. $status_state = 'positive';
  696. // Check for "not "
  697. if (substr($status[0], 0, 4) == 'not ')
  698. {
  699. $status_state = 'negative';
  700. $status[0] = trim(substr($status[0], 3));
  701. $status[] = 'closed';
  702. }
  703. else
  704. {
  705. $status[] = 'open';
  706. }
  707. $include_status_list = explode('|', $include_status);
  708. $exclude_status_list = explode('|', $exclude_status);
  709. // Remove the default "open" status if explicitely set
  710. if (in_array('open', $exclude_status_list))
  711. $status = array_filter($status, create_function('$v', 'return $v != "open";'));
  712. if ($status_state == 'positive')
  713. $status = array_merge($status, $include_status_list);
  714. elseif ($status_state == 'negative')
  715. $status = array_merge($status, $exclude_status_list);
  716. // Retrieve entry_ids to exclude
  717. $exclude = explode('|', $this->EE->TMPL->fetch_param('exclude'));
  718. // get site pages data
  719. $site_pages = $this->get_site_pages();
  720. $segment_1 = $this->EE->uri->segment('1');
  721. $segment_2 = $this->EE->uri->segment('2');
  722. /** -------------------------------------
  723. /** Function Logic
  724. /** -------------------------------------*/
  725. // get all pages
  726. $pages = $this->get_data();
  727. // Remove anything to be excluded from the results array
  728. $closed_parents = array();
  729. foreach ($pages as $key => $entry_data)
  730. {
  731. if ($status_state == 'negative' && in_array(strtolower($entry_data['status']), $status)
  732. || ($status_state == 'positive' && ! in_array(strtolower($entry_data['status']), $status))
  733. || in_array($entry_data['parent_id'], $closed_parents)
  734. || in_array($entry_data['entry_id'], $exclude))
  735. {
  736. $closed_parents[] = $entry_data['entry_id'];
  737. unset($pages[$key]);
  738. }
  739. }
  740. // Make sure array indices are incremental (0..X)
  741. $pages = array_values($pages);
  742. if ($css_id == "")
  743. {
  744. $css_id = ' id="nav"';
  745. }
  746. elseif (strtolower($css_id) == 'none')
  747. {
  748. $css_id = NULL;
  749. }
  750. else
  751. {
  752. $css_id = ' id="'.$css_id.'"';
  753. }
  754. // Start building the navigation
  755. $html = "<ul{$css_id}{$css_class}>\n";
  756. $ul_open = false;
  757. $last_page_depth = 0;
  758. foreach ($pages as $page)
  759. {
  760. $page_uri = $site_pages['uris'][$page['entry_id']];
  761. $uri = $this->EE->functions->fetch_current_uri();
  762. // Make sure we have the site_url path in case we're operating in a subdirectory
  763. $home = trim($this->EE->functions->fetch_site_index(0, 0), '/');
  764. $item_uri = $this->EE->functions->remove_double_slashes($home . $page_uri);
  765. // Start a sub nav
  766. if ($page['depth'] > $last_page_depth)
  767. {
  768. $html = substr($html, 0, -6);
  769. $html .= "\n<ul>\n";
  770. $ul_open = true;
  771. }
  772. // Close a sub nav
  773. if ($page['depth'] < $last_page_depth)
  774. {
  775. // Calculate how many levels back to go
  776. $back_to = $last_page_depth - $page['depth'];
  777. $html .= str_repeat("</ul>\n</li>\n", $back_to);
  778. $ul_open = false;
  779. }
  780. // if ($page == end($pages))
  781. // {
  782. // $back_to = $last_page_depth - $page['depth'];
  783. // $html .= str_repeat("</ul>\n</li>\n", $back_to);
  784. // }
  785. // get entry id + node of the start entry
  786. $uri = '/'.$this->EE->uri->uri_string().'/';
  787. $entry_id = array_search($uri, $site_pages['uris']);
  788. $node = $entry_id ? $this->nset->getNode($entry_id) : false;
  789. // get entry id + node of the current entry
  790. $current_entry_id = array_search($uri, $site_pages['uris']);
  791. $current_node = $current_entry_id ? $this->nset->getNode($current_entry_id) : false;
  792. // if current_node is a leaf then current_node should be parent
  793. if ($current_node == '' && $current_entry_id)
  794. {
  795. // get entry's parent id
  796. $pid = $this->get_pid_for_listing_entry($current_entry_id);
  797. $current_node = $this->nset->getNode($pid);
  798. }
  799. $li_class = '';
  800. // if (($current_node['left'] > $page['lft'] && $current_node['right'] < $page['rgt']) OR (@$leaf_node['left'] > $page['lft'] && @$leaf_node['right'] < $page['rgt']))
  801. if (($current_node['left'] > $page['lft'] && $current_node['right'] < $page['rgt']))
  802. {
  803. $li_class .= 'parent' . $separator . $current_class;
  804. }
  805. elseif ($uri === $page_uri OR ($uri == '' && $page_uri == '/') OR $segment_1 == trim($page_uri, '/') && $segment_2 == "")
  806. {
  807. $here = TRUE;
  808. $current_entry = $entry_data['entry_id'];
  809. $li_class .= " ".$current_class;
  810. }
  811. /** -------------------------------------
  812. /** Last class detection
  813. /** -------------------------------------*/
  814. $upper_node = $this->nset->getNode($page['parent_id']);
  815. $last = "";
  816. // If an entry's RIGHT is one less than the parent's, is the last in a <ul>.
  817. if (($page['rgt']+1) == $upper_node['right'])
  818. {
  819. $last = ' last';
  820. }
  821. $li_class .= $last;
  822. // Check if the class is empty.
  823. if (empty($li_class))
  824. {
  825. $li_class = "";
  826. }
  827. else
  828. {
  829. $li_class=' class="'.trim($li_class).'"';
  830. }
  831. $page_title = ($page['title']);
  832. if ($add_span == "yes")
  833. {
  834. $page_title = "<span>".$page_title."</span>";
  835. }
  836. /** -------------------------------------
  837. /** Add Unique ID
  838. /** -------------------------------------*/
  839. $unique_prefix = "nav";
  840. $list_item_id = "";
  841. $slug = str_replace("/", $separator, $page_uri);
  842. $slug = substr($slug,1,-1);
  843. if ($separator == "_")
  844. {
  845. $slug = str_replace("-", $separator, $slug);
  846. }
  847. elseif ($separator == "-")
  848. {
  849. $slug = str_replace("_", $separator, $slug);
  850. }
  851. if ($slug == "")
  852. {
  853. $slug = "home";
  854. }
  855. if ($add_unique_id == "yes")
  856. {
  857. $list_item_id = ' id="'. $unique_prefix . $separator . $slug .'"';
  858. }
  859. // THE BIG LIST OUTPUT
  860. $list_item = '<li'.$li_class.''.$list_item_id.'><a href="'.$item_uri.'">'.$page_title.'</a></li>'."\n";
  861. // $list_item = '<li'.$li_class.''.$list_item_id.'><a href="'.$item_uri.'">'.$page_title.'</a> - Page Depth:'.$page['depth'].' ///// Last Page Depth: '.$last_page_depth.'</li>'."\n";
  862. // $list_item = '<li'.$li_class.''.$list_item_id.'><a href="'.$item_uri.'">'.$page_title.'</a> - Page Left:'.$page['lft'].' ///// Node Left:: '.$current_node['left'].'</li>'."\n";
  863. $html .= $list_item;
  864. $last_page_depth = $page['depth'];
  865. }
  866. // Make sure all the ULs are closed
  867. // This WAS > 0, didn't close properly. >1 looks like it solves it.
  868. if ($last_page_depth > 1)
  869. {
  870. $html .= "</ul>\n";
  871. $html .= str_repeat("</li>\n</ul>\n", $last_page_depth);
  872. }
  873. else
  874. {
  875. $html .= $ul_open ? "</ul>\n</li>\n</ul>" : "</ul>\n";
  876. }
  877. return $html;
  878. }
  879. /** -------------------------------------
  880. /** Tag: sitemap
  881. /**
  882. /** Returns a full tree of all site
  883. /** pages in <ul>, <xml> or text format.
  884. /** -------------------------------------*/
  885. function sitemap()
  886. {
  887. $html = "";
  888. $css_id = $this->EE->TMPL->fetch_param('css_id');
  889. $css_id = $css_id ? strtolower($css_id) : "sitemap";
  890. if ($css_id == "none")
  891. {
  892. $css_id = '';
  893. }
  894. $css_class = $this->EE->TMPL->fetch_param('css_class');
  895. $css_class = $css_class ? strtolower($css_class) : '';
  896. // DEPRECIATED SUPPORT for exclude_status and include_status
  897. $include_status = strtolower($this->EE->TMPL->fetch_param('include_status'));
  898. $exclude_status = strtolower($this->EE->TMPL->fetch_param('exclude_status'));
  899. // New, native EE status mode
  900. $status = $this->EE->TMPL->fetch_param('status');
  901. $status = $status == '' ? array() : explode('|', $status);
  902. $status = array_map('strtolower', $status); // match MySQL's case-insensitivity
  903. $status_state = 'positive';
  904. // Check for "not "
  905. if (substr($status[0], 0, 4) == 'not ')
  906. {
  907. $status_state = 'negative';
  908. $status[0] = trim(substr($status[0], 3));
  909. $status[] = 'closed';
  910. }
  911. else
  912. {
  913. $status[] = 'open';
  914. }
  915. $include_status_list = explode('|', $include_status);
  916. $exclude_status_list = explode('|', $exclude_status);
  917. // Remove the default "open" status if explicitely set
  918. if (in_array('open', $exclude_status_list))
  919. $status = array_filter($status, create_function('$v', 'return $v != "open";'));
  920. if ($status_state == 'positive')
  921. $status = array_merge($status, $include_status_list);
  922. elseif ($status_state == 'negative')
  923. $status = array_merge($status, $exclude_status_list);
  924. // Retrieve entry_ids to exclude
  925. $exclude = explode("|", $this->EE->TMPL->fetch_param('exclude'));
  926. // Sitemap mode -- Completely alternate output
  927. $mode = strtolower($this->EE->TMPL->fetch_param('mode'));
  928. if ($mode == "")
  929. {
  930. $mode = "html";
  931. }
  932. // Get site pages data
  933. $site_pages = $this->get_site_pages();
  934. // Get all pages
  935. $pages = $this->get_data();
  936. // Remove anything to be excluded from the results array
  937. $closed_parents = array();
  938. foreach ($pages as $key => $entry_data)
  939. {
  940. if ($status_state == 'negative' && in_array(strtolower($entry_data['status']), $status)
  941. || ($status_state == 'positive' && ! in_array(strtolower($entry_data['status']), $status))
  942. || in_array($entry_data['parent_id'], $closed_parents)
  943. || in_array($entry_data['entry_id'], $exclude))
  944. {
  945. $closed_parents[] = $entry_data['entry_id'];
  946. unset($pages[$key]);
  947. }
  948. }
  949. // Make sure array indices are incremental (0..X)
  950. $pages = array_values($pages);
  951. $home = $this->EE->functions->fetch_site_index(0,0);
  952. /** --------------------------------
  953. /** XML Sitemap Output
  954. /** --------------------------------*/
  955. if ($mode == "xml")
  956. {
  957. $html .= '<?xml version="1.0" encoding="UTF-8"?>'."\n".'<urlset'."\n\t".'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"'."\n\t".'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'."\n\t".'xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">'."\n".'<!-- Created with Structure for ExpressionEngine (http://buildwithstructure.com) -->'."\n";
  958. foreach ($pages as $page)
  959. {
  960. $page_uri = $site_pages['uris'][$page['entry_id']];
  961. $item_uri = $this->EE->functions->remove_double_slashes($home . $page_uri);
  962. $xml_item = '<url>'."\n\t".'<loc>'.$item_uri.'</loc>'."\n\t".'<priority>1.00</priority>'."\n".'</url>'."\n";
  963. $html .= $xml_item;
  964. }
  965. $html .= '</urlset>';
  966. }
  967. elseif ($mode == "text")
  968. {
  969. foreach ($pages as $page)
  970. {
  971. $page_uri = $site_pages['uris'][$page['entry_id']];
  972. $item_uri = $this->EE->functions->remove_double_slashes($home.$page_uri);
  973. $xml_item = $item_uri."\n";
  974. $html .= $xml_item;
  975. }
  976. }
  977. /** --------------------------------
  978. /** HTML Sitemap Output
  979. /** --------------------------------*/
  980. else
  981. {
  982. $html .= "<ul id=\"$css_id\"" . ($css_class != '' ? " class=\"$css_class\"" : '') . ">\n";
  983. $ul_open = false;
  984. $last_page_depth = 0;
  985. foreach ($pages as $page)
  986. {
  987. $page_uri = $site_pages['uris'][$page['entry_id']];
  988. $item_uri = $this->EE->functions->remove_double_slashes($home . $page_uri);
  989. // Start a sub nav
  990. if ($page['depth'] > $last_page_depth)
  991. {
  992. $html = substr($html, 0, -6);
  993. $html .= "\n<ul>\n";
  994. $ul_open = true;
  995. }
  996. // Close a sub nav
  997. if ($page['depth'] < $last_page_depth)
  998. {
  999. // Finds the previous entry
  1000. preg_match("~\<li( class=\".+?\"){0,1}>(\<.+?\</.+?>)~", $list_item, $matches);
  1001. // Creates the new class entry
  1002. if ($matches[1])
  1003. {
  1004. $last_item_class = substr($matches[1], 0, -1) . " last\"";
  1005. }
  1006. else
  1007. {
  1008. $last_item_class = " class=\"last\"";
  1009. }
  1010. // Stores the inner of the <li>
  1011. $last_item_inner = $matches[2];
  1012. // Replace the string
  1013. $html = str_replace($list_item, "<li$last_item_class>$last_item_inner</li>\n", $html);
  1014. // Calculate how many levels back I need to go
  1015. $back_to = $last_page_depth - $page['depth'];
  1016. $html .= str_repeat("</ul>\n</li>\n", $back_to);
  1017. $ul_open = false;
  1018. }
  1019. // Is this the last in the list?
  1020. $classes = '';
  1021. $page_title = "";
  1022. if ($page == end($pages))
  1023. {
  1024. $classes = ' class="last"';
  1025. }
  1026. if ($this->EE->config->item('auto_convert_high_ascii') != 'n')
  1027. {
  1028. $page_title = $page['title'];
  1029. }
  1030. else
  1031. {
  1032. $page_title = htmlspecialchars($page['title']);
  1033. }
  1034. $list_item = "<li$classes><a href='$item_uri'>".$page_title."</a></li>\n";
  1035. $html .= $list_item;
  1036. $last_page_depth = $page['depth'];
  1037. }
  1038. // Make sure all the ULs are closed
  1039. if ($last_page_depth > 1)
  1040. {
  1041. $html .= "</ul>\n";
  1042. $html .= str_repeat("</li>\n</ul>\n", $last_page_depth);
  1043. }
  1044. else
  1045. {
  1046. $html .= $ul_open ? "</ul>\n</li>\n</ul>" : "</ul>\n";
  1047. }
  1048. }
  1049. return $html;
  1050. }
  1051. /** -------------------------------------
  1052. /** Create a Breadcrumb Trail
  1053. /** -------------------------------------*/
  1054. function breadcrumb()
  1055. {
  1056. $site_pages = $this->get_site_pages();
  1057. if ( ! $site_pages) return FALSE;
  1058. // Get parameters
  1059. $separator = $this->EE->TMPL->fetch_param('separator');
  1060. $separator = $separator ? $separator : '&raquo;';
  1061. $inc_separator = $this->EE->TMPL->fetch_param('inc_separator');
  1062. $separator = $inc_separator === 'no' ? '' : $separator;
  1063. $inc_home = $this->EE->TMPL->fetch_param('inc_home');
  1064. $inc_home = $inc_home === 'no' ? false : true;
  1065. $inc_here = $this->EE->TMPL->fetch_param('inc_here');
  1066. $inc_here = $inc_here === 'no' ? false : true;
  1067. $here_as_title = $this->EE->TMPL->fetch_param('here_as_title');
  1068. $here_as_title = $here_as_title === 'yes' ? true : false;
  1069. $wrap_each = $this->EE->TMPL->fetch_param('wrap_each');
  1070. $wrap_each = $wrap_each ? $wrap_each : '';
  1071. $wrap_here = $this->EE->TMPL->fetch_param('wrap_here');
  1072. $wrap_here = $wrap_here ? $wrap_here : '';
  1073. $wrap_separator = $this->EE->TMPL->fetch_param('wrap_separator');
  1074. $wrap_separator = $wrap_separator ? $wrap_separator : '';
  1075. $separator = $wrap_separator ? "<{$wrap_separator}>{$separator}</{$wrap_separator}>" : $separator;
  1076. // Are we passed a URI to work from? If not use current URI
  1077. $uri = $this->EE->TMPL->fetch_param('uri');
  1078. $uri = $uri ? $uri : '/'.$this->EE->uri->uri_string().'/';
  1079. $uri = html_entity_decode($uri);
  1080. // get current entry id
  1081. $entry_id = array_search($uri, $site_pages['uris']);
  1082. // get node of the current entry
  1083. $node = $entry_id ? $this->nset->getNode($entry_id) : false;
  1084. // node does not have any structure data we return nothing to prevent errors
  1085. if ($node === false && ! $entry_id)
  1086. {
  1087. return '';
  1088. }
  1089. // if we have an entry id but no node, we have listing entry
  1090. if ($entry_id && ! $node)
  1091. {
  1092. // get entry's parent id
  1093. $pid = $this->get_pid_for_listing_entry($entry_id);
  1094. // get node of parent entry
  1095. $node = $this->nset->getNode($pid);
  1096. }
  1097. $right = $node['right'];
  1098. $inc_current = isset($pid) ? '=' : '';
  1099. $sql = "SELECT node.*, expt.title
  1100. FROM exp_structure AS node
  1101. INNER JOIN exp_channel_titles AS expt
  1102. ON node.entry_id = expt.entry_id
  1103. WHERE node.lft > 1
  1104. AND node.lft < $right
  1105. AND node.rgt >$inc_current $right
  1106. ORDER BY node.lft";
  1107. $result = $this->EE->db->query($sql);
  1108. $home = trim($this->EE->functions->fetch_site_index(0, 0), '/');
  1109. $crumbs = array();
  1110. if ($inc_home)
  1111. {
  1112. $crumbs[] = '<a href="' . $home . '">Home</a>';
  1113. }
  1114. foreach ($result->result_array() as $entry)
  1115. {
  1116. $crumbs[] = '<a href="' . $home . $site_pages['uris'][$entry['entry_id']] . '">' . $entry['title'] . '</a>';
  1117. }
  1118. // If inc_here param is yes/true then show the here name
  1119. if ($inc_here)
  1120. {
  1121. // If here_as_title is yes/true then show here as page title
  1122. if ($here_as_title)
  1123. {
  1124. $sql2 = "SELECT title
  1125. FROM exp_channel_titles
  1126. WHERE entry_id = $entry_id";
  1127. $result2 = $this->EE->db->query($sql2);
  1128. $result2 = $result2->result_array();
  1129. $crumbs[] = !empty($wrap_here) ? "<{$wrap_here}>{$result2[0]['title']}</{$wrap_here}>" : $result2[0]['title'];
  1130. }
  1131. else
  1132. {
  1133. $crumbs[] = !empty($wrap_here) ? "<{$wrap_here}>Here</{$wrap_here}>" : "Here";
  1134. }
  1135. }
  1136. for ($i=0, $count=count($crumbs); $i < $count; $i++)
  1137. {
  1138. if ( ! empty( $separator) && $i != ($count-1))
  1139. {
  1140. $crumbs[$i] = "{$crumbs[$i]} {$separator} ";
  1141. }
  1142. if ( ! empty($wrap_each))
  1143. {
  1144. $crumbs[$i] = "<{$wrap_each}>{$crumbs[$i]}</{$wrap_each}>";
  1145. }
  1146. }
  1147. return implode('', $crumbs);
  1148. }
  1149. /** -------------------------------------
  1150. /** Tag: titletrail
  1151. /** -------------------------------------*/
  1152. function titletrail()
  1153. {
  1154. // get site pages data
  1155. $site_pages = $this->get_site_pages();
  1156. if (!$site_pages) return FALSE;
  1157. // get current uri path
  1158. $uri = '/'.$this->EE->uri->uri_string().'/';
  1159. // get current entry id
  1160. $entry_id = array_search($uri, $site_pages['uris']);
  1161. // get node of the current entry
  1162. $node = $entry_id ? $this->nset->getNode($entry_id) : false;
  1163. // node does not have any structure data we return site_name to prevent errors
  1164. if ($node === false && !$entry_id)
  1165. {
  1166. return stripslashes($this->EE->config->item('site_name'));
  1167. }
  1168. // if we have an entry id but no node, we have listing entry
  1169. if ($entry_id && ! $node)
  1170. {
  1171. // get entry's parent id
  1172. $pid = $this->get_pid_for_listing_entry($entry_id);
  1173. // get node of parent entry
  1174. // because we will be showing nav sub from its view point
  1175. $node = $this->nset->getNode($pid);
  1176. }
  1177. // Fetch params
  1178. $separator = $this->EE->TMPL->fetch_param('separator');
  1179. $separator = $separator ? " " . $separator . " " : ' | ';
  1180. $reverse = $this->EE->TMPL->fetch_param('reverse');
  1181. $reverse = ($reverse == 'yes') ? true : false;
  1182. $right = $node['right'];
  1183. $inc_current = isset($pid) ? '=' : '';
  1184. $sql = "SELECT node.*, expt.title
  1185. FROM exp_structure AS node
  1186. INNER JOIN exp_channel_titles AS expt
  1187. ON node.entry_id = expt.entry_id
  1188. WHERE node.lft > 1
  1189. AND node.lft < $right
  1190. AND node.rgt >$inc_current $right
  1191. ORDER BY node.lft DESC";
  1192. $result = $this->EE->db->query($sql);
  1193. $sql2 = "SELECT title
  1194. FROM exp_channel_titles
  1195. WHERE entry_id = $entry_id";
  1196. $result2 = $this->EE->db->query($sql2);
  1197. // Create an array of the page titles and site name
  1198. // If reverse param is true then flip it prior to output
  1199. $title_row = $result2->result_array();
  1200. $title_row = $title_row[0]['title'];
  1201. $title_array = array();
  1202. $title_array[] = $title_row;
  1203. foreach ($result->result_array() as $entry)
  1204. {
  1205. $title_array[] = $entry['title'];
  1206. }
  1207. $title_array[] = stripslashes($this->EE->config->item('site_name'));
  1208. if ($reverse === true)
  1209. {
  1210. $title_array = array_reverse($title_array);
  1211. }
  1212. $html = implode($separator, $title_array);
  1213. return $html;
  1214. }
  1215. /** -------------------------------------
  1216. /** Tag: top_level_title
  1217. /** Outputs the first segment's title
  1218. /** -------------------------------------*/
  1219. function top_level_title()
  1220. {
  1221. $site_pages = $this->get_site_pages(); // get site pages data
  1222. if ( ! $site_pages)
  1223. return FALSE;
  1224. $seg1 = '/'.$this->EE->uri->segment(1).'/'; // get segment 1 value
  1225. $top_id = array_search($seg1, $site_pages['uris']);
  1226. if ($top_id)
  1227. {
  1228. $this->EE->db->where('entry_id', $top_id);
  1229. $this->EE->db->limit(1);
  1230. $query=$this->EE->db->get('exp_channel_titles');
  1231. if ($query->num_rows() == 1)
  1232. {
  1233. $row = $query->row();
  1234. return $row->title;
  1235. }
  1236. }
  1237. return '';
  1238. }
  1239. /** -------------------------------------
  1240. /** Tag: parent_title
  1241. /** -------------------------------------*/
  1242. function parent_title($entry_id = NULL)
  1243. {
  1244. $html = "";
  1245. // get site pages data
  1246. $site_pages = $this->get_site_pages();
  1247. if (!$site_pages) return FALSE;
  1248. // get current uri path
  1249. $uri = '/'.$this->EE->uri->uri_string().'/';
  1250. // get current entry id
  1251. $entry_id = $entry_id ? $entry_id : array_search($uri, $site_pages['uris']);
  1252. // get node of the current entry
  1253. $node = $entry_id ? $this->nset->getNode($entry_id) : false;
  1254. // node does not have any structure data we return site_name to prevent errors
  1255. if ($node === false && ! $entry_id)
  1256. {
  1257. return stripslashes($this->EE->config->item('site_name'));
  1258. }
  1259. // if we have an entry id but no node, we have listing entry
  1260. if ($entry_id && ! $node)
  1261. {
  1262. // get entry's parent id
  1263. $pid = $this->get_pid_for_listing_entry($entry_id);
  1264. // get node of parent entry
  1265. // because we will be showing nav sub from its view point
  1266. $node = $this->nset->getNode($pid);
  1267. }
  1268. $right = $node['right'];
  1269. $inc_current = isset($pid) ? '=' : '';
  1270. $sql = "SELECT node.*, expt.title
  1271. FROM exp_structure AS node
  1272. INNER JOIN exp_channel_titles AS expt
  1273. ON node.entry_id = expt.entry_id
  1274. WHERE node.lft > 1
  1275. AND node.lft < $right
  1276. AND node.rgt >$inc_current $right
  1277. ORDER BY node.lft DESC";
  1278. $result = $this->EE->db->query($sql);
  1279. $html = $result->result_array();
  1280. $html = @$html[0]['title'];
  1281. return $html;
  1282. }
  1283. /** -------------------------------------
  1284. /** Tag: page_slug
  1285. /** -------------------------------------*/
  1286. function page_slug($entry_id = NULL)
  1287. {
  1288. $slug = "";
  1289. $uri = "";
  1290. // get site pages data
  1291. $site_pages = $this->get_site_pages();
  1292. if (!$site_pages) return FALSE;
  1293. $uri = '/'.$this->EE->uri->uri_string().'/';
  1294. if ($entry_id == NULL)
  1295. {
  1296. // get current entry id
  1297. $current_page_entry_id = array_search($uri, $site_pages['uris']);
  1298. // Fetch params
  1299. $entry_id = $this->EE->TMPL->fetch_param('entry_id');
  1300. $entry_id = $entry_id ? $entry_id : $current_page_entry_id;
  1301. }
  1302. // get page uri slug without parents
  1303. @$uri = $site_pages['uris'][$entry_id];
  1304. // if there are no / then we have a root slug already, else get the end
  1305. $slug .= trim($uri, '/');
  1306. if (strpos($slug, '/'))
  1307. {
  1308. $slug = substr(strrchr($slug, '/'), 1);
  1309. }
  1310. return $slug;
  1311. }
  1312. /** -------------------------------------
  1313. /** Tag: page_id
  1314. /** -------------------------------------*/
  1315. function page_id($entry_uri = NULL)
  1316. {
  1317. $slug = "";
  1318. // get site pages data
  1319. $site_pages = $this->get_site_pages();
  1320. if ( ! $site_pages) return FALSE;
  1321. // Fetch params
  1322. $entry_uri = $this->EE->TMPL->fetch_param('entry_uri');
  1323. // echo $entry_uri;
  1324. if ($entry_uri == NULL || $entry_uri == '')
  1325. {
  1326. $entry_uri = '/'.$this->EE->uri->uri_string().'/';
  1327. }
  1328. // get current entry id
  1329. $current_page_entry_id = array_search($entry_uri, $site_pages['uris']);
  1330. return $current_page_entry_id;
  1331. }
  1332. // --------------------------------------------------------------------
  1333. // Child IDs function
  1334. // Returns a string of IDs for a given parent
  1335. function child_ids()
  1336. {
  1337. $site_pages = $this->get_site_pages();
  1338. if (!$site_pages) return FALSE;
  1339. // Fetch our parent ID, or if none default to the current page
  1340. $parent = $this->EE->TMPL->fetch_param('entry_id');
  1341. $start_from = $this->EE->TMPL->fetch_param('start_from') ? $this->EE->TMPL->fetch_param('start_from') : false;
  1342. // Only do an automatic lookup if we're not requiring a parent ID, and no entry_id was defined.
  1343. if ( ! $parent AND ! $start_from)
  1344. {
  1345. // Find the parent in the site pages array using URL
  1346. $current_uri = implode('/', $this->EE->uri->segment_array());
  1347. $parent = array_search("/$current_uri/", $site_pages['uris']);
  1348. }
  1349. elseif($start_from)
  1350. {
  1351. $start_from = trim($start_from, '/');
  1352. $parent = array_search("/$start_from/", $site_pages['uris']);
  1353. }
  1354. // If nothing was found, return empty, otherwise the query below will return all child pages.
  1355. if( ! $parent)
  1356. return;
  1357. // Grab the delimiter, or default to a pipe
  1358. $delimiter = $this->EE->TMPL->fetch_param('delimiter');
  1359. $delimiter = $delimiter ? $delimiter : '|';
  1360. $results = $this->EE->db->query("SELECT entry_id FROM exp_structure WHERE parent_id = '{$parent}' AND entry_id != '0' ORDER BY lft ASC");
  1361. $entries = array();
  1362. if ($results->num_rows() > 0)
  1363. {
  1364. foreach ($results->result_array() as $row)
  1365. {
  1366. $entries[] = $row['entry_id'];
  1367. }
  1368. }
  1369. $values = implode($delimiter, $entries);
  1370. if ($values == "")
  1371. {
  1372. $values = "0";
  1373. }
  1374. return $values;
  1375. }
  1376. // Show a current page's listing channel_id or listing channel short name
  1377. function child_listing()
  1378. {
  1379. $site_pages = $this->get_site_pages();
  1380. if (!$site_pages)
  1381. return FALSE;
  1382. $data = $this->get_data();
  1383. $value = "";
  1384. $show = $this->EE->TMPL->fetch_param('show'); // defaults to "listing_cid"
  1385. $entry_id = $this->EE->TMPL->fetch_param('entry_id'); // defaults to "listing_cid"
  1386. $current_id = array_search('/'.$this->EE->uri->uri_string().'/', $site_pages['uris']);
  1387. $entry_id = $entry_id ? $entry_id : $current_id;
  1388. if ($entry_id == 0 || $entry_id == "")
  1389. return FALSE;
  1390. $listing_cid = isset($data[$entry_id]['listing_cid']) ? $data[$entry_id]['listing_cid'] : 0;
  1391. if ($listing_cid != 0)
  1392. {
  1393. // Use zee switch so possible future additions are easier to add.
  1394. switch($show)
  1395. {
  1396. case "channel_name":
  1397. $result = $this->EE->db->query("SELECT * FROM exp_channels WHERE channel_id = {$listing_cid}");
  1398. $value = $result->row('channel_name');
  1399. break;
  1400. case "channel_title":
  1401. $result = $this->EE->db->query("SELECT * FROM exp_channels WHERE channel_id = {$listing_cid}");
  1402. $value = $result->row('channel_title');
  1403. break;
  1404. default:
  1405. $value = isset($data[$entry_id]['listing_cid']) ? $data[$entry_id]['listing_cid'] : "";
  1406. break;
  1407. }
  1408. }
  1409. return $value;
  1410. }
  1411. /** -------------------------------------
  1412. /** Tag: first_child_redirect
  1413. /** -------------------------------------*/
  1414. function first_child_redirect()
  1415. {
  1416. $first_child_id = 0;
  1417. $site_id = $this->EE->config->item('site_id');
  1418. $site_pages = $this->get_site_pages();
  1419. $site_url = trim($this->EE->functions->fetch_site_index(0, 0), '/');
  1420. $site_index = trim($this->EE->functions->fetch_site_index(0, 0), '/') !== '' ? trim($this->EE->functions->fetch_site_index(0, 0), '/') : '';
  1421. // get the current entry id
  1422. $current_uri = '/'.implode('/', $this->EE->uri->segment_array()).'/';
  1423. $current_entry_id = array_search($current_uri, $site_pages['uris']);
  1424. if ($current_entry_id !== FALSE)
  1425. {
  1426. // get the first child of the current entry
  1427. $sql = "SELECT node.entry_id
  1428. FROM exp_structure AS node
  1429. INNER JOIN exp_structure AS parent ON node.lft
  1430. BETWEEN parent.lft AND parent.rgt
  1431. WHERE parent.lft >1
  1432. AND node.site_id = {$this->EE->db->escape_str($site_id)}
  1433. AND node.parent_id = {$this->EE->db->escape_str($current_entry_id)}
  1434. GROUP BY node.entry_id
  1435. ORDER BY node.lft
  1436. LIMIT 0,1";
  1437. $query = $this->EE->db->query($sql);
  1438. if ($query->num_rows > 0)
  1439. {
  1440. $first_child_id = $query->row('entry_id');
  1441. }
  1442. $first_child_uri = $first_child_id > 0 ? $site_pages['uris'][$first_child_id] : '';
  1443. // do the redirect
  1444. if ($first_child_uri !== '' && $site_url !== '')
  1445. {
  1446. header( "Location:".$site_index.$first_child_uri);
  1447. }
  1448. }
  1449. exit();
  1450. }
  1451. function entry_linking()
  1452. {
  1453. $site_pages = $this->get_site_pages();
  1454. if ( ! $site_pages)
  1455. return FALSE;
  1456. $html = $pid = "";
  1457. $html = ( ! $this->EE->TMPL->tagdata) ? '' : $this->EE->TMPL->tagdata;
  1458. if (strtolower($this->EE->TMPL->fetch_param('type')) == "next")
  1459. {
  1460. $type = 'ASC';
  1461. }
  1462. elseif (strtolower($this->EE->TMPL->fetch_param('type') ) == "previous")
  1463. {
  1464. $type = 'DESC';
  1465. }
  1466. else
  1467. {
  1468. return "";
  1469. }
  1470. $uri = $this->EE->TMPL->fetch_param('uri');
  1471. $uri = $uri ? $uri : '/'.$this->EE->uri->uri_string().'/';
  1472. $entry_id = array_search($uri, $site_pages['uris']);
  1473. $node = $entry_id ? $this->nset->getNode($entry_id) : false;
  1474. // node does not have any structure data we return nothing to prevent errors
  1475. if ($node === false && ! $entry_id)
  1476. {
  1477. return '';
  1478. }
  1479. // if we have an entry id but no node, we have listing entry
  1480. if ($entry_id && ! $node)
  1481. {
  1482. $pid = $this->get_pid_for_listing_entry($entry_id);
  1483. // get node of parent entry
  1484. $node = $this->nset->getNode($pid);
  1485. }
  1486. $channel_id = $node['listing_cid'];
  1487. $sql = "SELECT entry_id, title
  1488. FROM exp_channel_titles
  1489. WHERE channel_id = $channel_id
  1490. AND status = 'open'
  1491. ORDER BY entry_date $type";
  1492. $result = $this->EE->db->query($sql);
  1493. $count = 0;
  1494. $r_id = 0;
  1495. $row = array();
  1496. if ($result->num_rows > 0)
  1497. {
  1498. foreach($result->result_array() AS $row)
  1499. {
  1500. if ($row['entry_id'] == $entry_id) $r_id = $count+1;
  1501. $count++;
  1502. }
  1503. }
  1504. $array_vals = $result->result_array();
  1505. @$eid = $array_vals[$r_id]['entry_id'];
  1506. // Might need to pull left and right data to make this work
  1507. if ( ! empty($array_vals) && $array_vals[$r_id]['title'] != "")
  1508. {
  1509. $row['linking_title'] = $array_vals[$r_id]['title'];
  1510. $row['linking_page_url'] = $site_pages['uris'][$eid];
  1511. }
  1512. else
  1513. {
  1514. return "";
  1515. }
  1516. foreach ($this->EE->TMPL->var_single as $key => $val)
  1517. {
  1518. if (isset($row[$val]))
  1519. {
  1520. $html = $this->EE->TMPL->swap_var_single($val, $row[$val], $html);
  1521. }
  1522. }
  1523. return $html;
  1524. }
  1525. // --------------------------------------------------------------------
  1526. function order_entries()
  1527. {
  1528. // Grab the delimiter, or default to a pipe
  1529. $delimiter = $this->EE->TMPL->fetch_param('delimiter');
  1530. $delimiter = $delimiter ? $delimiter : '|';
  1531. // Start building out Start From and Limit Depth Features here
  1532. // get all pages
  1533. $pages = $this->get_data();
  1534. $entries = "";
  1535. // Check if any data before preceeding
  1536. if (isset($pages))
  1537. {
  1538. foreach ($pages as $key => $entry_data)
  1539. {
  1540. // Add entries in order
  1541. $entries .= $entry_data['entry_id'] . $delimiter;
  1542. }
  1543. }
  1544. $entries = substr_replace($entries ,"",-1);
  1545. return $entries;
  1546. }
  1547. function paginate()
  1548. {
  1549. $site_id = $this->EE->config->item('site_id');
  1550. if ( ! isset($_GET['page']))
  1551. {
  1552. $req_uri = $_SERVER['REQUEST_URI'];
  1553. if (preg_match("~page=(.*)$~", $req_uri, $found_page_num))
  1554. {
  1555. $current_page = $found_page_num[1];
  1556. }
  1557. else
  1558. {
  1559. $current_page = 1;
  1560. }
  1561. }
  1562. else
  1563. {
  1564. $current_page = $this->EE->input->get_post('page') ? $this->EE->input->get_post('page') : 1;
  1565. }
  1566. //
  1567. $separator = $this->EE->config->item('word_separator') != "dash" ? '_' : '-';
  1568. // Where to place pagination code
  1569. $location = $this->EE->TMPL->fetch_param('location');
  1570. // Do we show first and last links
  1571. $show_first_last = $this->EE->TMPL->fetch_param('show_first_last');
  1572. // Do we show next and previous links
  1573. $show_next_previous = $this->EE->TMPL->fetch_param('show_next_previous');
  1574. // Do we show page total (Page 1 of 99)
  1575. $show_page_total = $this->EE->TMPL->fetch_param('show_page_total');
  1576. // How many page links do we show at a time
  1577. $show_num_pages = $this->EE->TMPL->fetch_param('show_num_pages');
  1578. // Get pagination mode
  1579. $pagination_mode = $this->EE->TMPL->fetch_param('mode');
  1580. if ( ! $pagination_mode)
  1581. {
  1582. $pagination_mode = 'sliding';
  1583. }
  1584. // Get pagination chars/content for first/last/next/previous
  1585. $first_content = $this->EE->TMPL->fetch_param('first');
  1586. $first_content = $first_content ? $first_content : 'First';
  1587. $last_content = $this->EE->TMPL->fetch_param('last');
  1588. $last_content = $last_content ? $last_content : 'Last';
  1589. $next_content = $this->EE->TMPL->fetch_param('next');
  1590. $next_content = $next_content ? $next_content : 'Next';
  1591. $previous_content = $this->EE->TMPL->fetch_param('previous');
  1592. $previous_content = $previous_content ? $previous_content : 'Previous';
  1593. $tag_content = $tagdata = $this->EE->TMPL->tagdata;
  1594. $params = array();
  1595. foreach ($this->EE->TMPL->var_pair as $pkey => $pval)
  1596. {
  1597. // Find channel:entries tag
  1598. if (ereg("^exp:channel:entries", $pkey))
  1599. {
  1600. $params = $pval;
  1601. $params['offset'] = $params['limit'] * ($current_page - 1);
  1602. // Replace the offset value with the calculated one
  1603. // if offset value present
  1604. if (ereg("offset=\"([0-9]+)\"", $pkey))
  1605. {
  1606. $tagdata = preg_replace('/(\{exp:channel:entries)(.+)offset="([0-9]+)"(.*\})/', '$1$2offset="' . $params['offset'] . '"$4', $tagdata);
  1607. }
  1608. else
  1609. {
  1610. $tagdata = preg_replace('/(\{exp:channel:entries)(.+)(.*\})/', '$1$2 offset="' . $params['offset'] . '"$3', $tagdata);
  1611. }
  1612. }
  1613. }
  1614. $cat_not = "";
  1615. $status_not = "";
  1616. $where_clause = '';
  1617. // $where_clause .= " && (FROM_UNIXTIME(entries.expiration_date) > UTC_TIMESTAMP() OR entries.expiration_date = '')";
  1618. // Limit by channel(s)
  1619. $channel_not = "";
  1620. if (isset($params['channel']))
  1621. {
  1622. $channel_ids = explode(" ", $params['channel']);
  1623. if ($channel_ids[0] == "not")
  1624. {
  1625. $channel_ids = $channel_ids[1];
  1626. $channel_not = 'NOT';
  1627. }
  1628. else
  1629. {
  1630. $channel_ids = $channel_ids[0];
  1631. }
  1632. $channel_ids = explode("|", $channel_ids);
  1633. $channel_temp = array();
  1634. foreach ($channel_ids as $item)
  1635. {
  1636. $channel_temp[] = "'" . $item . "'";
  1637. }
  1638. $channel_ids = $channel_temp;
  1639. $channel_ids = implode(",", $channel_ids);
  1640. $where_clause .= " AND channels.channel_name $channel_not IN ($channel_ids)";
  1641. }
  1642. // Limit by author_id(s)
  1643. if (isset($params['author_id']))
  1644. {
  1645. if ($params['author_id'] == 'CURRENT_USER')
  1646. {
  1647. $where_clause .= "AND members.member_id = '" . $this->EE->sessions->userdata('member_id')."' ";
  1648. }
  1649. elseif ($params['author_id'] == 'NOT_CURRENT_USER')
  1650. {
  1651. $where_clause .= "AND members.member_id != '" . $this->EE->sessions->userdata('member_id')."' ";
  1652. }
  1653. else
  1654. {
  1655. $where_clause .= $this->EE->functions->sql_andor_string($params['author_id'], 'members.member_id');
  1656. }
  1657. }
  1658. // Limit by username
  1659. if (isset($params['username']))
  1660. {
  1661. if ($params['username'] == 'CURRENT_USER')
  1662. {
  1663. $where_clause .= "AND members.member_id = '".$this->EE->sessions->userdata('member_id')."' ";
  1664. }
  1665. elseif ($params['username'] == 'NOT_CURRENT_USER')
  1666. {
  1667. $where_clause .= "AND members.member_id != '".$this->EE->sessions->userdata('member_id')."' ";
  1668. }
  1669. else
  1670. {
  1671. $where_clause .= $this->EE->functions->sql_andor_string($params['username'], 'members.username');
  1672. }
  1673. }
  1674. // Limit by entry_id(s)
  1675. if (isset($params['entry_id']))
  1676. {
  1677. $entry_ids = explode(" ", $params['entry_id']);
  1678. if ($entry_ids[0] == "not")
  1679. {
  1680. $entry_ids = $entry_ids[1];
  1681. $entry_not = 'NOT';
  1682. }
  1683. else
  1684. {
  1685. $entry_ids = $entry_ids[0];
  1686. }
  1687. $entry_ids = explode("|", $entry_ids);
  1688. $entry_ids = implode(",", $entry_ids);
  1689. $where_clause .= " AND entries.entry_id $entry_not IN ($entry_ids)";
  1690. }
  1691. // Limit by entry_id_from
  1692. if (isset($params['entry_id_from']))
  1693. {
  1694. $where_clause .= " AND entries.entry_id >= " . $params['entry_id_from'];
  1695. }
  1696. // Limit by entry_id_to
  1697. if (isset($params['entry_id_to']))
  1698. {
  1699. $where_clause .= " AND entries.entry_id <= " . $params['entry_id_to'];
  1700. }
  1701. // Limit by group_id(s)
  1702. if (isset($params['group_id']))
  1703. {
  1704. $group_ids = explode(" ", $params['group_id']);
  1705. if ($group_ids[0] == "not")
  1706. {
  1707. $group_ids = $group_ids[1];
  1708. $group_not = 'NOT';
  1709. }
  1710. else
  1711. {
  1712. $group_ids = $group_ids[0];
  1713. }
  1714. $group_ids = explode("|", $group_ids);
  1715. $group_ids = implode(",", $group_ids);
  1716. $where_clause .= " AND members.group_id $group_not IN ($group_ids)";
  1717. }
  1718. // Limit by show_future_entries
  1719. if ( ! (isset($params['show_future_entries']) && $params['show_future_entries'] == 'yes'))
  1720. {
  1721. $where_clause .= " AND FROM_UNIXTIME(entries.entry_date) < UTC_TIMESTAMP()";
  1722. }
  1723. // Limit by show_expired
  1724. if ( ! (isset($params['show_expired']) && $params['show_expired'] == 'yes'))
  1725. {
  1726. $where_clause .= " AND (FROM_UNIXTIME(entries.expiration_date) > UTC_TIMESTAMP() OR entries.expiration_date=0)";
  1727. }
  1728. // Limit by start_on
  1729. if (isset($params['start_on']))
  1730. {
  1731. $where_clause .= "AND entries.entry_date >= '" . $this->EE->localize->convert_human_date_to_gmt($params['start_on']) . "' ";
  1732. }
  1733. // Limit by stop_before
  1734. if (isset($params['stop_before']))
  1735. {
  1736. $where_clause .= "AND entries.entry_date < '" . $this->EE->localize->convert_human_date_to_gmt($params['stop_before']) . "' ";
  1737. }
  1738. // Limit by year/month/day
  1739. if (isset($params['year']))
  1740. {
  1741. $year = (! $params['year']) ? date('Y') : $params['year'];
  1742. $smonth = (! @$params['month']) ? '01' : $params['month'];
  1743. $emonth = (! @$params['month']) ? '12': $params['month'];
  1744. $day = (! @$params['day']) ? '' : $params['day'];
  1745. if ($day != '' && ! $params['month'])
  1746. {
  1747. $smonth = date('m');
  1748. $emonth = date('m');
  1749. }
  1750. if (strlen($smonth) == 1) $smonth = '0' . $smonth;
  1751. if (strlen($emonth) == 1) $emonth = '0' . $emonth;
  1752. if ($day == '')
  1753. {
  1754. $sday = 1;
  1755. $eday = $this->EE->localize->fetch_days_in_month($emonth, $year);
  1756. }
  1757. else
  1758. {
  1759. $sday = $day;
  1760. $eday = $day;
  1761. }
  1762. $stime = $this->EE->localize->set_gmt(mktime(0, 0, 0, $smonth, $sday, $year));
  1763. $etime = $this->EE->localize->set_gmt(mktime(23, 59, 59, $emonth, $eday, $year));
  1764. $where_clause .= " AND entries.entry_date >= ".$stime." AND entries.entry_date <= ".$etime." ";
  1765. }
  1766. // Limit by status
  1767. if (isset($params['status']))
  1768. {
  1769. $status_ids = explode(" ", $params['status']);
  1770. if ($status_ids[0] == "not")
  1771. {
  1772. $status_ids = $status_ids[1];
  1773. $status_not = 'NOT';
  1774. }
  1775. else
  1776. {
  1777. $status_ids = $status_ids[0];
  1778. }
  1779. $status_ids = explode("|", $status_ids);
  1780. $status_temp = array();
  1781. foreach ($status_ids as $item)
  1782. {
  1783. if ($item == 'IS_EMPTY')
  1784. {
  1785. $item = '';
  1786. }
  1787. $status_temp[] = "'" . $item . "'";
  1788. }
  1789. $status_ids = $status_temp;
  1790. $status_ids = implode(",", $status_ids);
  1791. $where_clause .= " AND entries.status $status_not IN ($status_ids)";
  1792. }
  1793. // Limit by url_title(s)
  1794. if (isset($params['url_title']))
  1795. {
  1796. $url_title_ids = explode(" ", $params['url_title']);
  1797. if ($url_title_ids[0] == "not") {
  1798. $url_title_ids = $url_title_ids[1];
  1799. $url_title_not = 'NOT';
  1800. }
  1801. else
  1802. {
  1803. $url_title_ids = $url_title_ids[0];
  1804. }
  1805. $url_title_ids = explode("|", $url_title_ids);
  1806. $url_title_temp = array();
  1807. foreach ($url_title_ids as $item)
  1808. {
  1809. $url_title_temp[] = "'" . $item . "'";
  1810. }
  1811. $url_title_ids = $url_title_temp;
  1812. $url_title_ids = implode(",", $url_title_ids);
  1813. $where_clause .= " AND entries.url_title $url_title_not IN ($url_title_ids)";
  1814. }
  1815. // Limit by search:
  1816. foreach ($params as $param_k => $param_v)
  1817. {
  1818. if (ereg("^search:", $param_k))
  1819. {
  1820. $search_temp = explode(":", $param_k);
  1821. // determine if we have an OR search or an AND search
  1822. if (strpos($param_v, "|"))
  1823. {
  1824. $split_on = "|";
  1825. $search_link = " OR ";
  1826. }
  1827. else
  1828. {
  1829. $split_on = "&&";
  1830. $search_link = " AND ";
  1831. }
  1832. // determine if we have an EXACT or FUZZY search
  1833. if (strpos($param_v, "=") === 0)
  1834. {
  1835. $search_type = 'exact';
  1836. }
  1837. // Remove = symbol for parsing
  1838. $param_v = trim($param_v, "=");
  1839. // Determine if we have a NOT search
  1840. $param_temp = explode(" ", $param_v);
  1841. if ($param_temp[0] == "not")
  1842. {
  1843. $param_v = $param_temp[1];
  1844. $search_not = 'NOT';
  1845. }
  1846. $search_ids = explode($split_on, $param_v);
  1847. $params['search'][$search_temp[1]] = $search_ids;
  1848. $params['search_link'][$search_temp[1]] = $search_link;
  1849. $params['search_type'][$search_temp[1]] = $search_type;
  1850. $params['search_not'][$search_temp[1]] = $search_not . " ";
  1851. }
  1852. }
  1853. if (isset($params['search']))
  1854. {
  1855. foreach ($params['search'] as $skey => $sval)
  1856. {
  1857. $query = "SELECT field_id FROM exp_channel_fields WHERE field_name = '$skey' AND site_id = $site_id";
  1858. $result = $this->EE->db->query($query);
  1859. $where_clause .= " AND (";
  1860. foreach ($sval as $term)
  1861. {
  1862. if (ereg("(.*)\W$", $term))
  1863. {
  1864. $comparison = "REGEXP";
  1865. }
  1866. else
  1867. {
  1868. $comparison = "LIKE";
  1869. }
  1870. $where_clause .= "wlog.field_id_" . $result->row['field_id'] . " " . $params['search_not'][$skey] . $comparison . " '";
  1871. if ($comparison == "REGEXP")
  1872. {
  1873. $where_clause .= "[[:<:]]" . substr($term, 0, -2) . "[[:>:]]";
  1874. }
  1875. else
  1876. {
  1877. // exact search or fuzzy search
  1878. if ($params['search_type'][$skey] == 'exact')
  1879. {
  1880. $where_clause .= "$term";
  1881. }
  1882. else
  1883. {
  1884. $where_clause .= "%$term%";
  1885. }
  1886. }
  1887. $where_clause .= "'";
  1888. if ($term != end($sval))
  1889. {
  1890. $where_clause .= $params['search_link'][$skey];
  1891. }
  1892. }
  1893. $where_clause .= ")";
  1894. }
  1895. }
  1896. // Limit by categories
  1897. if (isset($params['category']) && $params['category'] != "")
  1898. {
  1899. $cat_ids = explode(" ", $params['category']);
  1900. if ($cat_ids[0] == "not")
  1901. {
  1902. $cat_ids = $cat_ids[1];
  1903. $cat_not = 'NOT';
  1904. }
  1905. else
  1906. {
  1907. $cat_ids = $cat_ids[0];
  1908. }
  1909. if (strstr($cat_ids,'&'))
  1910. {
  1911. $cat_ids = explode("&", $cat_ids);
  1912. $cat_id_str = implode(",", $cat_ids);
  1913. # fetch a list of entry ids that appear in ALL categories listed
  1914. $sql = "SELECT entry_id
  1915. FROM exp_category_posts
  1916. WHERE cat_id IN ({$cat_id_str})
  1917. GROUP BY entry_id
  1918. HAVING (COUNT(entry_id) = ".count($cat_ids).")";
  1919. #echo $sql;
  1920. $query = $this->EE->db->query($sql);
  1921. if ($query->num_rows > 0)
  1922. {
  1923. $found_ids = array();
  1924. foreach ($query->result_array() as $row)
  1925. {
  1926. $found_ids[] = $row['entry_id'];
  1927. }
  1928. $where_clause .= " AND entries.entry_id $cat_not IN (".implode(',',$found_ids).")";
  1929. }
  1930. else
  1931. {
  1932. return; // no matches so do nothing
  1933. }
  1934. }
  1935. else
  1936. {
  1937. $cat_ids = explode("|", $cat_ids);
  1938. $cat_ids = implode(",", $cat_ids);
  1939. $where_clause .= " AND categories.cat_id $cat_not IN ($cat_ids)";
  1940. }
  1941. }
  1942. // Limit by category_group
  1943. if (isset($params['category_group']))
  1944. {
  1945. $cat_group_ids = explode(" ", $params['category_group']);
  1946. if ($cat_group_ids[0] == "not")
  1947. {
  1948. $cat_group_ids = $cat_group_ids[1];
  1949. $cat_group_not = 'NOT';
  1950. }
  1951. else
  1952. {
  1953. $cat_group_ids = $cat_group_ids[0];
  1954. }
  1955. $cat_group_ids = explode("|", $cat_group_ids);
  1956. $cat_group_ids = implode(",", $cat_group_ids);
  1957. $where_clause .= " AND categories.group_id $cat_group_not IN ($cat_group_ids)";
  1958. }
  1959. // Build base for SQL query
  1960. $sql = "SELECT COUNT(DISTINCT(entries.entry_id)) AS c" .
  1961. " FROM exp_channel_titles AS entries" .
  1962. " LEFT JOIN exp_channels AS channels ON entries.channel_id = channels.channel_id" .
  1963. " LEFT JOIN exp_channel_data AS channel ON entries.entry_id = channel.entry_id" .
  1964. " LEFT JOIN exp_members AS members ON members.member_id = entries.author_id";
  1965. // Limit on category or category_group
  1966. if (isset($params['category']) OR isset($params['category_group']))
  1967. {
  1968. $sql .= " LEFT JOIN exp_category_posts ON entries.entry_id = exp_category_posts.entry_id
  1969. LEFT JOIN exp_categories AS categories ON exp_category_posts.cat_id = categories.cat_id";
  1970. }
  1971. /** ----------------------------------------------
  1972. /** Execute Query
  1973. /** ----------------------------------------------*/
  1974. $sql .= " WHERE entries.site_id = " . $site_id;
  1975. if ($where_clause)
  1976. {
  1977. $sql = $sql.$where_clause;
  1978. }
  1979. $result = $this->EE->db->query($sql);
  1980. $per_page = @$params['limit'];
  1981. $total_entries = $result->result_array();
  1982. $total_entries = $total_entries[0]['c'];
  1983. @$total_pages = ceil($total_entries / $per_page);
  1984. $last_page = $total_pages;
  1985. $html = '';
  1986. // If more than one page, show pagination links
  1987. if ($total_pages > 1)
  1988. {
  1989. $additional_params = $this->EE->TMPL->fetch_param('additional_params') ? '&'.$this->EE->TMPL->fetch_param('additional_params') : '';
  1990. $html .= "<ul class=\"pagination\">";
  1991. // If not on first page, show the previous and first links
  1992. if ($current_page > 1)
  1993. {
  1994. $previous_page = $current_page - 1;
  1995. if ($show_first_last != 'no')
  1996. {
  1997. $html .= "<li class=\"beginning\"><a href=\"?page=1{$additional_params}\">$first_content</a></li>";
  1998. }
  1999. if ($show_next_previous != 'no')
  2000. {
  2001. $html .= "<li class=\"previous\"><a href=\"?page={$previous_page}{$additional_params}\">$previous_content</a></li>";
  2002. }
  2003. }
  2004. //
  2005. // Show page links
  2006. // If jumping page mode
  2007. if ($pagination_mode == 'jumping')
  2008. {
  2009. $total_page_groups = ceil($total_pages / $show_num_pages);
  2010. $page_group = ceil($current_page / $show_num_pages);
  2011. $start_at = (($page_group - 1) * $show_num_pages) + 1;
  2012. $end_at = $page_group * $show_num_pages;
  2013. if ($end_at > $last_page)
  2014. {
  2015. $end_at = $last_page;
  2016. }
  2017. }
  2018. if ($pagination_mode == 'sliding')
  2019. {
  2020. $start_at = $current_page - $show_num_pages;
  2021. $end_at = $current_page + $show_num_pages;
  2022. // If at beginning or end
  2023. if ($start_at < 1)
  2024. {
  2025. $start_at = 1;
  2026. }
  2027. if ($end_at > $last_page)
  2028. {
  2029. $end_at = $last_page;
  2030. }
  2031. }
  2032. for ($x = $start_at; $x <= $end_at; $x++)
  2033. {
  2034. $html .= "<li";
  2035. if ($x == $current_page)
  2036. {
  2037. // If current page
  2038. $html .= " class=\"here\"";
  2039. }
  2040. $html .= "><a href=\"?page={$x}{$additional_params}\">" . $x . "</a></li>";
  2041. }
  2042. // If not last page, show next and last link
  2043. if ($current_page != $last_page)
  2044. {
  2045. $next_page = $current_page + 1;
  2046. if ($show_next_previous != 'no')
  2047. {
  2048. $html .= "<li class=\"next\"><a href=\"?page={$next_page}{$additional_params}\">$next_content</a></li>";
  2049. }
  2050. if ($show_first_last != 'no')
  2051. {
  2052. $html .= "<li class=\"end\"><a href=\"?page={$last_page}{$additional_params}\">$last_content</a></li>";
  2053. }
  2054. }
  2055. if ($show_page_total == 'yes')
  2056. {
  2057. $html .= "<li class=\"page" . $separator . "total\">Page $current_page of $total_pages</li>";
  2058. }
  2059. $html .= "</ul>";
  2060. }
  2061. // Decide where to show pagination links
  2062. switch($location)
  2063. {
  2064. case 'top':
  2065. $html = $html . $tagdata;
  2066. break;
  2067. case 'bottom':
  2068. default:
  2069. $html = $tagdata . $html;
  2070. break;
  2071. case 'both':
  2072. $html = $html . $tagdata . $html;
  2073. break;
  2074. }
  2075. return $html;
  2076. }
  2077. // --------------------------------------------------------------------
  2078. function set_data($data)
  2079. {
  2080. $site_id = $this->EE->config->item('site_id');
  2081. $site_pages = $this->get_site_pages();
  2082. extract($data);
  2083. $channel_type = $this->get_channel_type($channel_id);
  2084. // If this is called, it should always be a static channel, but keeping here for now just incase
  2085. if($channel_type === 'static')
  2086. {
  2087. // get existing node if any out of the database
  2088. $node = $this->nset->getNode($entry_id);
  2089. $parentNode = $this->nset->getNode($parent_id);
  2090. if ($node === false)
  2091. {
  2092. // all fields except left and right which is handled by the nestedset library
  2093. $extra = array(
  2094. 'site_id' => $site_id,
  2095. 'entry_id' => $entry_id,
  2096. 'parent_id' => $parent_id,
  2097. 'channel_id' => $channel_id,
  2098. 'listing_cid' => $listing_cid,
  2099. 'dead' => ''
  2100. );
  2101. // create new node
  2102. $this->nset->newLastChild($parentNode['right'], $extra);
  2103. // fetch newly created node to keep working with
  2104. $node = $this->nset->getNode($entry_id);
  2105. }
  2106. $this->EE->load->helper('url');
  2107. // set uri entries
  2108. $node['uri'] = isset($site_pages['uris'][$entry_id]) ? $site_pages['uris'][$entry_id] : strtolower(url_title($uri));
  2109. $parentNode['uri'] = $parent_id ? $site_pages['uris'][$parent_id] : '';
  2110. // existing node
  2111. $changed = $this->has_changed($node, $data);
  2112. if ($changed)
  2113. {
  2114. // Retrieve previous listing channel id
  2115. $prev_lcid_result = $this->EE->db->query("SELECT * FROM exp_structure WHERE entry_id = " . $entry_id);
  2116. $prev_lcid = $prev_lcid_result->row('listing_cid');
  2117. $listing = "";
  2118. $lcid = $listing_cid ? $listing_cid : 0;
  2119. $sql = "UPDATE exp_structure
  2120. SET parent_id = $parent_id, listing_cid = $lcid
  2121. WHERE entry_id = $entry_id";
  2122. $this->EE->db->query($sql);
  2123. // Listing Channel option in tab was changed TO "Unmanaged"
  2124. if($prev_lcid != 0 && $lcid == 0)
  2125. {
  2126. // Retrieve all entries for channel
  2127. $listing_entries = $this->EE->db->query("SELECT * FROM exp_channel_titles WHERE channel_id = " . $prev_lcid);
  2128. // Go through list of entries to be removed from Structure
  2129. foreach ($listing_entries->result_array() as $listing_entry)
  2130. {
  2131. $listing_id = $listing_entry['entry_id'];
  2132. // Remove from site_pages
  2133. if (isset($site_pages['uris'][$listing_id]))
  2134. {
  2135. unset($site_pages['uris'][$listing_id]);
  2136. unset($site_pages['templates'][$listing_id]);
  2137. }
  2138. }
  2139. // Remove from our table too
  2140. $this->EE->db->delete('structure_listings', array('channel_id' => $prev_lcid));
  2141. }
  2142. else
  2143. {
  2144. $listing_data = array();
  2145. $l_template_id = false;
  2146. $l_uri = false;
  2147. // Listing channel is the same, and we already have listing data so just update parent data if needed.
  2148. if($prev_lcid == $lcid AND $prev_lcid != 0 AND $lcid != 0)
  2149. {
  2150. // Retrieve all entries for channel
  2151. $listing_entries = $this->EE->db->query("SELECT * FROM exp_structure_listings WHERE channel_id = " . $lcid);
  2152. }
  2153. // First time listing creation
  2154. else
  2155. {
  2156. // Retrieve all entries for channel
  2157. $listing_entries = $this->EE->db->query("SELECT * FROM exp_channel_titles WHERE channel_id = " . $lcid);
  2158. // Retrieve template setting for channel
  2159. $query = $this->EE->db->query("SELECT template_id FROM exp_structure_channels WHERE channel_id = $channel_id");
  2160. $l_template_id = $query->row('template_id');
  2161. // Create URIs for each entry
  2162. $this->EE->load->helper('url');
  2163. }
  2164. foreach ($listing_entries->result_array() as $l_entry)
  2165. {
  2166. $listing_data = array(
  2167. 'site_id' => $site_id,
  2168. 'channel_id' => $l_entry['channel_id'],
  2169. 'parent_id' => $entry_id,
  2170. 'entry_id' => $l_entry['entry_id'],
  2171. 'template_id' => isset($l_entry['template_id']) ? $l_entry['template_id'] : $l_template_id,
  2172. 'parent_uri' => $site_pages['uris'][$entry_id],
  2173. 'uri' => isset($l_entry['uri']) ? $l_entry['uri'] : strtolower(url_title($l_entry['title']))
  2174. );
  2175. // Update structure_listings table, and site_pages array with proper data
  2176. $this->set_listing_data($listing_data);
  2177. }
  2178. // Fetch newly updated site_pages array
  2179. $site_pages = $this->get_site_pages();
  2180. }
  2181. if ($changed !== true)
  2182. {
  2183. $prevUri = $node['uri'];
  2184. // Modify only if previous URI is root slash, allows to only affect the single page and it's entries & children
  2185. if($prevUri == "/")
  2186. {
  2187. $site_pages['uris'][$entry_id] = $uri;
  2188. // find out if there are children by retrieving the tree
  2189. // if has children then modify those and their children if they exist
  2190. $tree = $this->nset->getTree($entry_id);
  2191. if (count($tree) > 1)
  2192. {
  2193. foreach ($tree as $child)
  2194. {
  2195. $child_id = $child['entry_id'];
  2196. // replaces only first occurrence of $prevUri, makes sure only initial slash is replaced
  2197. $site_pages['uris'][$child_id] = preg_replace("#" . $prevUri . "#", $uri, $site_pages['uris'][$child_id], 1);
  2198. }
  2199. }
  2200. // if has entries then modify those as well
  2201. if ($listing_cid != 0)
  2202. {
  2203. // TODO: UPDATE?
  2204. $sql_listings = "SELECT entry_id
  2205. FROM exp_channel_data
  2206. WHERE channel_id = $listing_cid";
  2207. $listings = $this->EE->db->query($sql_listings);
  2208. foreach ($listings->result_array() as $listing)
  2209. {
  2210. $listing_id = $listing['entry_id'];
  2211. // replaces only first occurrence of $prevUri, makes sure only initial slash is replaced
  2212. $site_pages['uris'][$listing_id] = preg_replace("#" . $prevUri . "#", $uri, $site_pages['uris'][$listing_id], 1);
  2213. }
  2214. }
  2215. }
  2216. else
  2217. {
  2218. if(isset($site_pages['uris']))
  2219. {
  2220. foreach ($site_pages['uris'] as &$path)
  2221. {
  2222. // if path is not root slash then modify as usual
  2223. if ($path != "/")
  2224. {
  2225. $path = str_replace($prevUri, $uri, $path);
  2226. }
  2227. }
  2228. }
  2229. }
  2230. if ($changed === 'parent')
  2231. {
  2232. $this->nset->moveToLastChild($node, $parentNode);
  2233. }
  2234. }
  2235. }
  2236. }
  2237. // set site_pages to be compatible with EE core
  2238. $site_pages['uris'][$entry_id] = $uri;
  2239. $site_pages['templates'][$entry_id] = $template_id;
  2240. $site_id = $this->EE->config->item('site_id');
  2241. $this->set_site_pages($site_id, $site_pages);
  2242. }
  2243. /*
  2244. @ param
  2245. $data = array(
  2246. 'site_id' => $site_id,
  2247. 'entry_id' => $entry_id,
  2248. 'parent_id' => $pid,
  2249. 'channel_id' => $channel_id,
  2250. 'template_id' => $template_id,
  2251. 'uri' => $slug
  2252. );
  2253. */
  2254. function set_listing_data($data)
  2255. {
  2256. $entry_id = $data['entry_id'];
  2257. $site_pages = $this->get_site_pages();
  2258. // Update the entry for our listing item in site_pages
  2259. $site_pages['uris'][$data['entry_id']] = $this->create_full_uri($data['parent_uri'], $data['uri']);
  2260. $site_pages['templates'][$data['entry_id']] = $data['template_id'];
  2261. $site_id = $this->EE->config->item('site_id');
  2262. $this->set_site_pages($site_id, $site_pages);
  2263. // Our listing table doesn't need this anymore, so remove it.
  2264. unset($data['listing_cid']);
  2265. unset($data['parent_uri']);
  2266. // See if row exists first
  2267. $query = $this->EE->db->get_where('structure_listings', array('entry_id' => $data['entry_id']));
  2268. // We have an entry, so we're modifying existing data
  2269. if($query->num_rows() == 1)
  2270. {
  2271. unset($data['entry_id']);
  2272. $sql = $this->EE->db->update_string('structure_listings', $data, "entry_id = $entry_id");
  2273. }
  2274. // This is a new entry
  2275. else
  2276. {
  2277. $sql = $this->EE->db->insert_string('structure_listings', $data);
  2278. }
  2279. // Update our listing table
  2280. $this->EE->db->query($sql);
  2281. }
  2282. function get_listing_data($entry_id)
  2283. {
  2284. $query = $this->EE->db->get_where('structure_listings', array('entry_id' => $entry_id));
  2285. return $query->row();
  2286. }
  2287. /*
  2288. * @param parent_uri
  2289. * @param listing_uri/slug
  2290. */
  2291. function create_full_uri($parent_uri, $listing_uri)
  2292. {
  2293. $uri = $this->create_uri($listing_uri);
  2294. // prepend the parent uri
  2295. $uri = $parent_uri . $uri;
  2296. // ensure beginning and ending slash
  2297. $uri = '/' . trim($uri, '/') . '/';
  2298. // if double slash, reduce to one
  2299. return str_replace('//', '/', $uri);
  2300. }
  2301. /*
  2302. * @param parent_uri
  2303. * @param page_uri/slug
  2304. */
  2305. function create_page_uri($parent_uri, $page_uri = '')
  2306. {
  2307. // prepend the parent uri
  2308. $uri = $parent_uri . $page_uri . '/';
  2309. // ensure beginning and ending slash
  2310. $uri = '/' . trim($uri, '/') . '/';
  2311. // if double slash, reduce to one
  2312. return str_replace('//', '/', $uri);
  2313. }
  2314. /*
  2315. * @param submitted_uri
  2316. * @param default_uri
  2317. */
  2318. function create_uri($uri, $url_title = '')
  2319. {
  2320. // if structure_uri is not entered use url_title
  2321. $uri = $uri ? $uri : $url_title;
  2322. // Clean it up TODO replace with EE create URL TITLE?
  2323. $uri = preg_replace("#[^a-zA-Z0-9_\-]+#i", '', $uri);
  2324. // Make sure there are no "_" underscores at the beginning or end
  2325. return trim($uri, "_");
  2326. }
  2327. // --------------------------------------------------------------------
  2328. /**
  2329. * Converts the jQuery NestedSortables Serialized array
  2330. * To a format which is similar to Structure->get_data()
  2331. * @param $sortable Array of array('id' => #, ['children' => subsortable])
  2332. * @param $data Working array similar to Structure->get_data()
  2333. * @param $lft Working left pointer
  2334. * @param $crumb Working bread-crumb to parents
  2335. * @return array data array similar to Structure->get_data()
  2336. */
  2337. function nestedsortable_to_nestedset($sortable, &$data = array(), &$lft = 2, $crumb = array())
  2338. {
  2339. $depth = count($crumb);
  2340. foreach($sortable as $key => $subitem)
  2341. {
  2342. $crumb[$depth] = $subitem['id'];
  2343. $data[$subitem['id']] = array(
  2344. 'lft' => $lft,
  2345. 'rgt' => NULL,
  2346. 'crumb' => $crumb
  2347. );
  2348. $lft++;
  2349. if(array_key_exists('children', $subitem))
  2350. {
  2351. $this->nestedsortable_to_nestedset($subitem['children'], $data, $lft, $crumb);
  2352. }
  2353. $data[$subitem['id']]['rgt'] = $lft;
  2354. $lft++;
  2355. unset($crumb[$depth]);
  2356. }
  2357. return $data;
  2358. }
  2359. function ajax_move_set_data()
  2360. {
  2361. // Grab the AJAX post
  2362. $sortable = $_POST['page-ui'];
  2363. $site_id = $this->EE->config->item('site_id');
  2364. // Convert the array to php
  2365. $data = $this->nestedsortable_to_nestedset($sortable);
  2366. $titles = array();
  2367. $site_pages = $this->get_site_pages();
  2368. $structure_data = $this->get_data();
  2369. $uris = $site_pages['uris'];
  2370. // Get Page Slugs
  2371. foreach ($uris as $key => $uri)
  2372. {
  2373. $slug = trim($uri, '/');
  2374. if (strpos($slug, '/'))
  2375. $slug = substr(strrchr($slug, '/'), 1);
  2376. if ($uri == "/")
  2377. $slug = $uri;
  2378. @$titles[$key] .= $slug;
  2379. }
  2380. // Build an array with all current channel_ids
  2381. $results = $this->EE->db->query("SELECT * FROM exp_channel_data");
  2382. $channel_data = array();
  2383. if ($results->num_rows() > 0)
  2384. {
  2385. foreach($results->result_array() as $row)
  2386. {
  2387. $channel_data[$row['entry_id']] = $row['channel_id'];
  2388. }
  2389. }
  2390. $row_insert = $page_uris = array();
  2391. foreach($data as $key => $row)
  2392. {
  2393. $depth = count($row['crumb']);
  2394. $row['site_id'] = $site_id;
  2395. $row['entry_id'] = $entry_id = $row['crumb'][$depth - 1];
  2396. $row['parent_id'] = $depth < 2 ? 0 : $row['crumb'][$depth - 2];
  2397. // $row['channel_id'] = $structure_data[$entry_id]['channel_id'];
  2398. $row['channel_id'] = $channel_data[$entry_id];
  2399. $row['listing_cid'] = $structure_data[$entry_id]['listing_cid'];
  2400. $row['dead'] = '';
  2401. // build URI path for pages
  2402. $uri_titles = array();
  2403. foreach($data[$key]['crumb'] as $entry_id)
  2404. {
  2405. $uri_titles[] = $titles[$entry_id];
  2406. }
  2407. // Remove invalid row fields
  2408. unset($row['depth']);
  2409. unset($row['crumb']);
  2410. // Build pages URI
  2411. $page_uris[$key] = trim(implode('/', $uri_titles), '/');
  2412. // Account for "/" home page
  2413. $page_uris[$key] = $page_uris[$key] == '' ? '/' : '/'.$page_uris[$key].'/';
  2414. // be sanitary
  2415. foreach($row as $field => $value)
  2416. {
  2417. $row[$field] = $this->EE->db->escape_str($value);
  2418. }
  2419. // build insert rows
  2420. $row_insert[] = "('".implode("','", $row)."')";
  2421. }
  2422. // Update Structure Data
  2423. $sql = ("DELETE FROM exp_structure WHERE site_id = '".$this->EE->db->escape_str($site_id)."'");
  2424. $this->EE->db->query($sql);
  2425. // Multi-line insert of all Structure Data
  2426. $sql = "INSERT INTO exp_structure (".implode(', ', array_keys($row)).") VALUES \r\n".implode(",\r\n", $row_insert);
  2427. $this->EE->db->query($sql);
  2428. // Update Site Pages
  2429. $site_pages['uris'] = $page_uris;
  2430. // And save this moved page to the array
  2431. $this->set_site_pages($site_id, $site_pages);
  2432. // Sorting pages blows away the listing data, so all URL's for listing items
  2433. // are no longer in the site_pages array... lets fix that.
  2434. foreach($site_pages['uris'] as $entry_id => $uri)
  2435. {
  2436. // Retrieve previous listing channel id
  2437. $lcid_result = $this->EE->db->query("SELECT * FROM exp_structure WHERE entry_id = " . $entry_id);
  2438. $listing_cid = $lcid_result->row('listing_cid');
  2439. $lcid = $listing_cid ? $listing_cid : false;
  2440. if($lcid)
  2441. {
  2442. // Retrieve all entries for channel
  2443. $listing_entries = $this->EE->db->query("SELECT * FROM exp_structure_listings WHERE channel_id = " . $lcid);
  2444. foreach ($listing_entries->result_array() as $l_entry)
  2445. {
  2446. $listing_data = array(
  2447. 'site_id' => $site_id,
  2448. 'channel_id' => $l_entry['channel_id'],
  2449. 'parent_id' => $l_entry['parent_id'],
  2450. 'entry_id' => $l_entry['entry_id'],
  2451. 'template_id' => $l_entry['template_id'],
  2452. 'parent_uri' => $site_pages['uris'][$entry_id],
  2453. 'uri' => $l_entry['uri']
  2454. );
  2455. // Update structure_listings table, and site_pages array with proper data
  2456. $this->set_listing_data($listing_data);
  2457. }
  2458. }
  2459. }
  2460. }
  2461. // --------------------------------------------------------------------
  2462. function get_data($channel_ids = false)
  2463. {
  2464. $site_id = $this->EE->config->item('site_id');
  2465. $sql = "SELECT node.*, (COUNT(parent.entry_id) - 1) AS depth, expt.title, expt.status
  2466. FROM exp_structure AS node
  2467. INNER JOIN exp_structure AS parent
  2468. ON node.lft BETWEEN parent.lft AND parent.rgt
  2469. INNER JOIN exp_channel_titles AS expt
  2470. ON node.entry_id = expt.entry_id
  2471. WHERE parent.lft > 1
  2472. AND node.site_id = $site_id
  2473. GROUP BY node.entry_id
  2474. ORDER BY node.lft";
  2475. $result = $this->EE->db->query($sql);
  2476. $data = array();
  2477. if ($result->num_rows() == 0)
  2478. {
  2479. return $data;
  2480. }
  2481. $cids = array();
  2482. $lcids = array();
  2483. foreach ($result->result_array() as $row)
  2484. {
  2485. $data[$row['entry_id']] = $row;
  2486. if ($channel_ids)
  2487. {
  2488. $cids[$row['entry_id']] = $row['channel_id'];
  2489. if ($row['listing_cid'] != 0)
  2490. {
  2491. $lcids[$row['entry_id']] = $row['listing_cid'];
  2492. }
  2493. }
  2494. }
  2495. if ($channel_ids)
  2496. {
  2497. $data = array(
  2498. 'data' => $data,
  2499. 'channel_ids' => $cids,
  2500. 'listing_cids' => $lcids
  2501. );
  2502. }
  2503. return $data;
  2504. }
  2505. function get_asset_data()
  2506. {
  2507. $return_array = array();
  2508. $asset_channels = $this->get_channels_by_type('asset');
  2509. // if ($asset_channels)
  2510. // {
  2511. // $sql = "SELECT *
  2512. // FROM exp_channels
  2513. // WHERE channel_id IN (" . implode(",", $asset_channels) . ")
  2514. // ORDER BY channel_title ASC";
  2515. // $result = $this->EE->db->query($sql);
  2516. //
  2517. // foreach ($result->result_array() as $row)
  2518. // {
  2519. // $return_array[] = array(
  2520. // 'channel_id' => $row['channel_id'],
  2521. // 'channel_title' => $row['channel_title']
  2522. // );
  2523. // }
  2524. // }
  2525. return $return_array;
  2526. }
  2527. function get_settings()
  2528. {
  2529. $site_id = '0,'.$this->EE->config->item('site_id');
  2530. $settings = array();
  2531. $sql = "SELECT var_value, var
  2532. FROM exp_structure_settings
  2533. WHERE
  2534. site_id IN ($site_id)";
  2535. $result = $this->EE->db->query($sql);
  2536. if ($result->num_rows() > 0)
  2537. {
  2538. foreach ($result->result_array() as $row)
  2539. {
  2540. $settings[$row['var']] = $row['var_value'];
  2541. }
  2542. }
  2543. $results = $this->EE->db->query("SELECT module_id FROM exp_modules WHERE module_name = 'Structure'");
  2544. $module_id = $results->row('module_id');
  2545. return $settings;
  2546. }
  2547. function channels_by_type($type = 'structure')
  2548. {
  2549. $valid = array();
  2550. // get site ID
  2551. $site_id = $this->EE->config->item('site_id');
  2552. // retrieve lists of type_channel variables from structure_settings table
  2553. $sql = "SELECT *
  2554. FROM exp_structure_settings
  2555. WHERE site_id = $site_id
  2556. AND var LIKE 'type_channel_%'
  2557. ORDER BY var ASC";
  2558. $results = $this->EE->db->query($sql);
  2559. foreach ($results->result_array() as $channel)
  2560. {
  2561. if ($channel['var_value'] == $type)
  2562. {
  2563. $valid[] = preg_replace('/type_channel_/', '', $channel['var']);
  2564. }
  2565. }
  2566. return $valid;
  2567. }
  2568. function get_site_pages()
  2569. {
  2570. $this->EE->db->select('site_pages');
  2571. $this->EE->db->where('site_id', $this->EE->config->item('site_id'));
  2572. $query = $this->EE->db->get('sites');
  2573. // Load the string helper
  2574. $this->EE->load->helper('string');
  2575. $site_pages = unserialize(base64_decode($query->row('site_pages')));
  2576. return $site_pages[$this->EE->config->item('site_id')];
  2577. }
  2578. function get_site_pages_query()
  2579. {
  2580. $this->EE->db->select('site_pages');
  2581. $this->EE->db->where('site_id', $this->EE->config->item('site_id'));
  2582. $query = $this->EE->db->get('sites');
  2583. $this->EE->load->helper('string');
  2584. $site_pages = unserialize(base64_decode($query->row('site_pages')));
  2585. return $site_pages[$this->EE->config->item('site_id')];
  2586. // $site_id =$this->EE->config->item('site_id');
  2587. // $query_pages = $this->EE->db->query("SELECT site_pages FROM exp_sites WHERE site_id = $site_id");
  2588. // $with_site_id = unserialize($query_pages->row('site_pages'));
  2589. // $site_pages = $with_site_id[$site_id];
  2590. // return $site_pages;
  2591. }
  2592. function get_channel_type($channel_id = 0)
  2593. {
  2594. if ($this->channel_type === '')
  2595. {
  2596. // $channel_id = $channel_type ? $channel_type : $this->EE->input->get_post('channel_id');
  2597. $channel_id = $this->EE->input->get_post('channel_id');
  2598. $listing_cids = $this->get_data_cids(true);
  2599. if (in_array($channel_id, $listing_cids))
  2600. {
  2601. $this->channel_type = 'listing';
  2602. }
  2603. else
  2604. {
  2605. $this->channel_type = 'static';
  2606. }
  2607. }
  2608. // Comment this out later
  2609. // $this->channel_type = 'static';
  2610. return $this->channel_type;
  2611. }
  2612. /**
  2613. * Get all data from the exp_structure_channels table
  2614. * @param $type|unmanaged|page|listing|asset
  2615. * @param $channel_id you can pass a channel_id to retreive it's data
  2616. * @return array An array of channel_ids and it's associated template_id, type and channel_title
  2617. */
  2618. function get_structure_channels($type = "", $channel_id = "")
  2619. {
  2620. $site_id = $this->EE->config->item('site_id');
  2621. // Get Structure Channel Data
  2622. $sql = "SELECT ec.channel_id, ec.channel_title, esc.template_id, esc.type
  2623. FROM exp_structure_channels AS esc
  2624. RIGHT JOIN exp_channels AS ec ON ec.channel_id = esc.channel_id";
  2625. if ($type != "") $sql .= " WHERE esc.type = '$type'";
  2626. if ($channel_id != "") $sql .= " WHERE esc.channel_id = '$channel_id'";
  2627. $results = $this->EE->db->query($sql);
  2628. // Format the array nicely
  2629. $channel_data = array();
  2630. foreach($results->result_array() as $key => $value)
  2631. {
  2632. $channel_data[$value['channel_id']] = $value;
  2633. unset($channel_data[$value['channel_id']]['channel_id']);
  2634. }
  2635. return $channel_data;
  2636. }
  2637. /**
  2638. * Get all channel_ids of the desired Structure type
  2639. * @param $type|unmanaged|page|listing|asset
  2640. * @return array An array of channel_ids in the specified type
  2641. */
  2642. function get_channels_by_type($type)
  2643. {
  2644. $results = $this->EE->db->get_where('exp_structure_channels', array('type' => $type));
  2645. $return = $results->result_array();
  2646. return $return;
  2647. }
  2648. function has_changed($node, $data)
  2649. {
  2650. $changed = false;
  2651. if ($data['entry_id'])
  2652. {
  2653. if ($node['channel_id'])
  2654. {
  2655. if ($node['channel_id'] != $data['listing_cid'])
  2656. {
  2657. $changed = true;
  2658. }
  2659. }
  2660. // check if path of entry has changed
  2661. if ($node['uri'] != $data['uri'])
  2662. {
  2663. $changed = 'self';
  2664. }
  2665. // check if parent has changed
  2666. // this overrides all other changed settings as it will do all update functions
  2667. if ($node['parent_id'] != $data['parent_id'])
  2668. {
  2669. $changed = 'parent';
  2670. }
  2671. }
  2672. return $changed;
  2673. }
  2674. function delete_data_by_channel($channel_id)
  2675. {
  2676. // Retrieve current site_id
  2677. $site_id =$this->EE->config->item('site_id');
  2678. // Retrieve entry IDs for current channel
  2679. $query = "SELECT *
  2680. FROM exp_channel_data
  2681. WHERE channel_id = " . $channel_id;
  2682. $entries = $this->EE->db->query($query);
  2683. // Retrieve site_pages data & unserialize it into an array
  2684. $site_pages = $this->get_site_pages_query();
  2685. // Go through list of entries to be removed from Structure
  2686. foreach ($entries->result_array() as $entry)
  2687. {
  2688. $entry_id = $entry['entry_id'];
  2689. // Remove from site_pages
  2690. if (isset($site_pages['uris'][$entry_id]))
  2691. {
  2692. unset($site_pages['uris'][$entry_id]);
  2693. unset($site_pages['templates'][$entry_id]);
  2694. }
  2695. // Remove from structure db table
  2696. $node = $this->nset->getNode($entry_id);
  2697. if ($node)
  2698. {
  2699. $this->nset->deleteNode($node);
  2700. }
  2701. }
  2702. // store new site_pages array to database
  2703. $this->set_site_pages($site_id, $site_pages);
  2704. // If channel is a listing channel associated with a page, unset it
  2705. $query_lcid = "UPDATE exp_structure SET listing_cid = 0 WHERE listing_cid = $channel_id";
  2706. $lcid = $this->EE->db->query($query_lcid);
  2707. return true;
  2708. }
  2709. // Delete Structure data
  2710. function delete_data($ids)
  2711. {
  2712. if (is_numeric($ids))
  2713. {
  2714. $ids = array($ids);
  2715. }
  2716. elseif ( ! is_array($ids))
  2717. {
  2718. return false;
  2719. }
  2720. // delete entries in the site_pages array
  2721. if (is_array($ids))
  2722. {
  2723. $usable_ids = implode(",", $ids);
  2724. }
  2725. else
  2726. {
  2727. $usable_ids = $ids;
  2728. }
  2729. // search for entries and get the site_id
  2730. $site_id = $this->EE->config->item('site_id');
  2731. $site_pages = $this->get_site_pages();
  2732. // Check all passed IDs for children/entries, gather IDs for all
  2733. // then remove Structure entries for anything with URI matching an entry
  2734. // search all ids then add IDs to a temp array if it's not already in the array
  2735. $ids_to_remove = array();
  2736. $l_ids = array();
  2737. foreach ($ids as $eid)
  2738. {
  2739. $node = $this->nset->getNode($eid);
  2740. $listing_cid = $node['listing_cid'];
  2741. // Check to see if we have a Structure node or just an entry
  2742. // if a node then get it's tree and affect the children
  2743. // otherwise just remove the entry
  2744. if ($node)
  2745. {
  2746. // find out if there are children by retrieving the tree
  2747. // if has children then modify those and their children if they exist
  2748. $tree = "";
  2749. $tree = $this->nset->getTree($eid);
  2750. if (count($tree) > 1)
  2751. {
  2752. foreach ($tree as $child)
  2753. {
  2754. $child_id = $child['entry_id'];
  2755. if ( ! in_array($child_id, $ids_to_remove))
  2756. {
  2757. array_push($ids_to_remove, $child_id);
  2758. }
  2759. }
  2760. }
  2761. // if has entries then modify those as well
  2762. if ($listing_cid != 0)
  2763. {
  2764. $sql_listings = "SELECT entry_id FROM exp_channel_data WHERE channel_id = $listing_cid";
  2765. $listings = $this->EE->db->query($sql_listings);
  2766. foreach ($listings->result_array() as $listing)
  2767. {
  2768. $listing_id = $listing['entry_id'];
  2769. array_push($l_ids, $listing_id);
  2770. if ( ! in_array($listing_id, $ids_to_remove))
  2771. {
  2772. array_push($ids_to_remove, $listing_id);
  2773. }
  2774. }
  2775. }
  2776. //
  2777. }
  2778. if ( ! in_array($eid, $ids_to_remove))
  2779. {
  2780. array_push($ids_to_remove, $eid);
  2781. }
  2782. }
  2783. // Go through list of items to be removed from Structure
  2784. foreach ($ids_to_remove as $entry_id)
  2785. {
  2786. if (isset($site_pages['uris'][$entry_id]))
  2787. {
  2788. unset($site_pages['uris'][$entry_id]);
  2789. unset($site_pages['templates'][$entry_id]);
  2790. if ( ! in_array($entry_id, $l_ids))
  2791. {
  2792. $this->set_status($entry_id, 'closed');
  2793. }
  2794. $node = $this->nset->getNode($entry_id);
  2795. if ($node)
  2796. {
  2797. $this->nset->deleteNode($node);
  2798. }
  2799. }
  2800. }
  2801. // Store new site_pages array to database
  2802. $this->set_site_pages($site_id, $site_pages);
  2803. return true;
  2804. }
  2805. function set_site_pages($site_id, $site_pages)
  2806. {
  2807. if(empty($site_id))
  2808. {
  2809. $site_id = $this->EE->config->item('site_id');
  2810. $pages[$site_id] = $site_pages;
  2811. }
  2812. else
  2813. {
  2814. $pages[$site_id] = $site_pages;
  2815. }
  2816. unset($site_pages);
  2817. $this->EE->db->query($this->EE->db->update_string('exp_sites',
  2818. array('site_pages' => base64_encode(serialize($pages))),
  2819. "site_id = '".$this->EE->db->escape_str($site_id)."'"));
  2820. }
  2821. function get_pid_for_listing_entry($entry_id)
  2822. {
  2823. //if (empty($this->EE->sessions->cache['structure']['lising_entry_pid'])) {
  2824. // get entry's channel id
  2825. $sql = "SELECT channel_id
  2826. FROM exp_channel_data
  2827. WHERE entry_id = $entry_id
  2828. LIMIT 1";
  2829. $result = $this->EE->db->query($sql);
  2830. $lcid = $result->row('channel_id');
  2831. // get entry's parent id
  2832. $sql = "SELECT entry_id
  2833. FROM exp_structure
  2834. WHERE listing_cid = $lcid
  2835. LIMIT 1";
  2836. $result = $this->EE->db->query($sql);
  2837. $pid = $result->row('entry_id');
  2838. // cache pid for later use
  2839. $this->EE->session->cache['structure']['lising_entry_pid'] = $pid;
  2840. //}
  2841. return $this->EE->session->cache['structure']['lising_entry_pid'];
  2842. }
  2843. function user_access($perm, $settings = array())
  2844. {
  2845. $ugid = $this->EE->session->userdata['group_id'];
  2846. // super admins always have access
  2847. if ($ugid == 1)
  2848. {
  2849. return true;
  2850. }
  2851. $admin_perm = 'perm_admin_structure_' . $ugid;
  2852. $this_perm = $perm . '_' . $ugid;
  2853. if ($settings !== array())
  2854. {
  2855. if ((isset($settings[$admin_perm]) OR isset($settings[$this_perm])))
  2856. {
  2857. return true;
  2858. }
  2859. else
  2860. {
  2861. return false;
  2862. }
  2863. }
  2864. // settings were not passed we have to go to the DB for the check
  2865. $sql = "SELECT var
  2866. FROM exp_structure_settings
  2867. WHERE var = '$admin_perm'
  2868. OR var = '$this_perm'";
  2869. $result = $this->EE->db->query($sql);
  2870. if ($result->num_rows() > 0)
  2871. {
  2872. return true;
  2873. }
  2874. return false;
  2875. }
  2876. // Mark an item with a status
  2877. function set_status($id, $status)
  2878. {
  2879. // Mark as closed entry in exp_channel_titles
  2880. $sql = "UPDATE exp_channel_titles SET status = '$status' WHERE status <> '$status' AND entry_id = $id";
  2881. $this->EE->db->query($sql);
  2882. }
  2883. function get_data_cids($listings = false)
  2884. {
  2885. $cid_field = $listings ? 'listing_cid' : 'channel_id';
  2886. $sql = "SELECT entry_id, $cid_field
  2887. FROM exp_structure";
  2888. $result = $this->EE->db->query($sql);
  2889. $cids = array();
  2890. foreach ($result->result_array() as $row)
  2891. {
  2892. if ($row[$cid_field] != 0)
  2893. {
  2894. $cids[$row['entry_id']] = $row[$cid_field];
  2895. }
  2896. }
  2897. return $cids;
  2898. }
  2899. function debug($data, $die = false)
  2900. {
  2901. echo '<pre>';
  2902. var_dump($data);
  2903. echo '</pre>';
  2904. if($die) die;
  2905. }
  2906. }
  2907. /* END Class */
  2908. /* End of file mod.structure.php */
  2909. /* Location: ./system/expressionengine/modules/structure/mod.structure.php */