<?php
class I18nNavigationFrontend {
private static $pages = null;
public static function redirectIfLink() {
if (function_exists('return_custom_field')) {
if (function_exists('i18n_init')) i18n_init();
if (function_exists('i18n_get_custom_fields')) i18n_get_custom_fields();
$link = return_custom_field('link');
if ($link) {
header('Location: '.$link);
exit(0);
}
}
}
public static function getPages() {
if (self::$pages) return self::$pages;
$cachefile = GSDATAOTHERPATH . I18N_CACHE_FILE;
if (!I18N_USE_CACHE || !file_exists($cachefile)) {
// read pages into associative array
self::$pages = array();
$dir_handle = @opendir(GSDATAPAGESPATH) or die("Unable to open pages directory");
while ($filename = readdir($dir_handle)) {
if (strrpos($filename,'.xml') === strlen($filename)-4 && !is_dir(GSDATAPAGESPATH . $filename)) {
$data = getXML(GSDATAPAGESPATH . $filename);
if (strpos($filename,'_') !== false) {
$pos = strpos($data->url,'_');
$url = substr($data->url,0,$pos);
$lang = substr($data->url,$pos+1);
if (!isset(self::$pages[$url])) {
self::$pages[$url] = array('url' => $url);
}
$menu = ((string) $data->menu ? (string) $data->menu : (string) $data->title);
$title = ((string) $data->title ? (string) $data->title : (string) $data->menu);
if ($menu) self::$pages[$url]['menu_'.$lang] = stripslashes($menu);
if ($title) self::$pages[$url]['title_'.$lang] = stripslashes($title);
if (isset($data->link) && (string) $data->link) self::$pages[$url]['link_'.$lang] = (string) $data->link;
} else {
$url = (string) $data->url;
if (!isset(self::$pages[$url])) {
self::$pages[$url] = array('url' => $url);
}
self::$pages[$url]['menuStatus'] = (string) $data->menuStatus;
self::$pages[$url]['menuOrder'] = (int) $data->menuOrder;
self::$pages[$url]['menu'] = stripslashes($data->menu);
self::$pages[$url]['title'] = stripslashes($data->title);
self::$pages[$url]['parent'] = (string) $data->parent;
self::$pages[$url]['private'] = (string) $data->private;
self::$pages[$url]['tags'] = (string) stripslashes($data->meta);
if (isset($data->link) && (string) $data->link) self::$pages[$url]['link'] = (string) $data->link;
}
}
}
// sort pages
$urlsToDelete = array();
$sortedpages = array();
foreach (self::$pages as $url => $page) {
if (isset($page['parent']) && $page['private'] != 'Y') {
$sortedpages[] = array('url' => $url, 'parent' => $page['parent'],
'sort' => sprintf("%s%03s%s", $page['parent'], $page['menuOrder'], $url));
} else {
$urlsToDelete[] = $url;
}
}
$sortedpages = subval_sort($sortedpages,'sort');
if (count($urlsToDelete) > 0) foreach ($urlsToDelete as $url) unset(self::$pages[$url]);
// save cache file
if (I18N_USE_CACHE) {
$data = @new SimpleXMLExtended('<?xml version="1.0" encoding="UTF-8"?><pages></pages>');
foreach ($sortedpages as $sortedpage) {
$url = $sortedpage['url'];
$page = self::$pages[$url];
$pagedata = $data->addChild('page');
foreach ($page as $key => $value) {
$propdata = $pagedata->addChild($key);
$propdata->addCData($value);
}
}
XMLsave($data, $cachefile);
}
} else {
$sortedpages = array();
$data = getXML($cachefile);
foreach ($data->page as $pagedata) {
$url = '' . $pagedata->url;
self::$pages[$url] = array();
foreach ($pagedata as $propdata) {
self::$pages[$url][$propdata->getName()] = (string) $propdata;
}
$sortedpages[] = array('url' => $url, 'parent' => self::$pages[$url]['parent']);
}
}
// fill children
self::$pages[null] = array();
foreach ($sortedpages as $sortedpage) {
$parent = $sortedpage['parent'];
if (isset(self::$pages[$parent])) {
if (!isset(self::$pages[$parent]['children'])) self::$pages[$parent]['children'] = array();
self::$pages[$parent]['children'][] = $sortedpage['url'];
}
}
return self::$pages;
}
public static function getPageStructure($slug=null, $menuOnly=true, $slugToIgnore=null, $lang=null) {
$slug = '' . $slug;
$structure = array();
self::getPageStructureImpl($structure, $slug, $menuOnly, $slugToIgnore, $lang);
if ($lang) {
for ($i=count($structure)-1; $i>=0; $i--) {
if ($structure[$i]['title'] == '') {
if ($i+1 >= count($structure) || $structure[$i+1]['level'] <= $structure[$i]['level']) {
array_splice($structure, $i, 1);
} else {
$structure[$i]['title'] = $structure[$i]['menu'] = '-';
}
}
}
}
return $structure;
}
private static function getPageStructureImpl(&$structure, $slug, $menuOnly=true, $slugToIgnore=null, $lang=null) {
$pages = self::getPages();
if (!isset($pages[$slug])) return;
$level = (count($structure) > 0 ? $structure[count($structure)-1]['level'] + 1 : 0);
if (isset($pages[$slug]['children'])) {
foreach ($pages[$slug]['children'] as $childslug) {
if ($childslug != $slugToIgnore && (!$menuOnly || $pages[$childslug]['menuStatus'] == 'Y')) {
if (!$lang || isset($pages[$childslug]['title_'.$lang])) {
$title = $lang ? $pages[$childslug]['title_'.$lang] : $pages[$childslug]['title'];
$menu = $pages[$childslug]['menu'];
if ($lang && isset($pages[$childslug]['menu_'.$lang])) $menu = $pages[$childslug]['menu_'.$lang];
$structure[] = array(
'level' => $level,
'url' => $childslug,
'title' => $title,
'menuStatus' => $pages[$childslug]['menuStatus'],
'menu' => $menu,
'parent' => $pages[$childslug]['parent']
);
} else {
$structure[] = array(
'level' => $level,
'url' => $childslug,
'title' => '',
'menuStatus' => $pages[$childslug]['menuStatus'],
'menu' =>'',
'parent' => $pages[$childslug]['parent']
);
}
self::getPageStructureImpl($structure, $childslug, $menuOnly, $slugToIgnore, $lang);
}
}
}
}
public static function getMenu($slug, $minlevel=0, $maxlevel=0, $show=I18N_SHOW_NORMAL) {
$slug = '' . $slug;
$pages = self::getPages();
$breadcrumbs = array();
for ($url = $slug; $url && isset($pages[$url]); $url = $pages[$url]['parent']) {
array_unshift($breadcrumbs, $url);
}
array_unshift($breadcrumbs, null);
// find last page in breadcrumbs that is displayed in the menu
for ($icu = 0; $icu+1 < count($breadcrumbs) && $pages[$breadcrumbs[$icu+1]]['menuStatus'] == 'Y'; $icu++);
$currenturl = $breadcrumbs[$icu];
// menus to display
if ($minlevel < 0 || $maxlevel < $minlevel || $minlevel >= count($breadcrumbs)) {
return array();
} else {
return self::getMenuImpl($breadcrumbs, $currenturl, $breadcrumbs[$minlevel], $maxlevel-$minlevel+1, $show);
}
}
private static function getMenuImpl($breadcrumbs, $currenturl, $url, $levels, $show=I18N_SHOW_NORMAL) {
global $language; // only set if I18N base plugin is available
$pages = self::getPages();
if (!@$pages[$url] || $levels <= 0) return null;
$deflang = function_exists('return_i18n_default_language') ? return_i18n_default_language() : null;
$menu = array();
if (isset($pages[$url]['children'])) {
foreach ($pages[$url]['children'] as $childurl) {
$showIt = true;
if (($show & I18N_FILTER_MENU) && $pages[$childurl]['menuStatus'] != 'Y') $showIt = false;
if ($showIt && ($show & I18N_FILTER_LANGUAGE)) {
$fulltitlekey = 'title' . (!@$language || $language == $deflang ? '' : '_' . $language);
if (!isset($pages[$childurl][$fulltitlekey])) $showIt = false;
}
if ($showIt) {
global $filters;
$params = array($childurl, $pages[$childurl]['parent'],
preg_split('/\s*,\s*/', html_entity_decode(stripslashes(trim(@$pages[$childurl]['tags'])), ENT_QUOTES, 'UTF-8')));
foreach ($filters as $filter) {
if ($filter['filter'] == I18N_FILTER_VETO_NAV_ITEM) {
if (call_user_func_array($filter['function'], $params)) {
$showIt = false;
break;
}
}
}
}
if ($showIt) {
$showChildren = !($show & I18N_FILTER_CURRENT) || in_array($childurl,$breadcrumbs);
$children = $showChildren ? self::getMenuImpl($breadcrumbs, $currenturl, $childurl, $levels-1, $show) : null;
$menu[] = array(
'url' => $childurl,
'parent' => $pages[$childurl]['parent'],
'menu' => self::getProperty($childurl,'menu',$deflang),
'title' => self::getProperty($childurl,'title',$deflang),
'link' => self::getProperty($childurl,'link',$deflang),
'currentpath' => in_array($childurl, $breadcrumbs),
'current' => ($childurl == $currenturl),
'children' => $children,
'haschildren' => $showChildren ? count($children) > 0 : self::hasChildren($childurl, $show)
);
}
}
}
return count($menu) > 0 ? $menu : null;
}
private static function hasChildren($url, $show=I18N_SHOW_NORMAL) {
global $language; // only set if I18N base plugin is available
$pages = self::getPages();
if (!@$pages[$url] || !isset($pages[$url]['children'])) return false;
$deflang = function_exists('return_i18n_default_language') ? return_i18n_default_language() : null;
foreach ($pages[$url]['children'] as $childurl) {
if (($show & I18N_FILTER_LANGUAGE)) {
$fulltitlekey = 'title' . (!@$language || $language == $deflang ? '' : '_' . $language);
if (isset($pages[$childurl][$fulltitlekey])) return true;
} else {
return true;
}
}
return false;
}
private static function getProperty($url, $key, $deflang) {
$pages = self::getPages();
if ($deflang !== null) {
$languages = return_i18n_languages();
foreach ($languages as $language) {
$fullkey = $key . ($language == $deflang ? '' : '_' . $language);
if (isset($pages[$url][$fullkey])) return $pages[$url][$fullkey];
}
} else {
if (isset($pages[$url][$key])) return $pages[$url][$key];
}
return null;
}
public static function outputMenu($slug, $minlevel=0, $maxlevel=0, $show=I18N_SHOW_NORMAL, $component=null) {
$slug = '' . $slug;
$menu = self::getMenu($slug, $minlevel, $maxlevel, $show);
if (isset($menu) && count($menu) > 0) {
$html = self::getMenuHTML($menu, ($show & I18N_OUTPUT_TITLE), $component);
echo exec_filter('menuitems',$html);
}
}
private static function getMenuHTML(&$menu, $showTitles=false, $componentname=null) {
$component = null;
if ($componentname && file_exists(GSDATAOTHERPATH.'components.xml')) {
$data = getXML(GSDATAOTHERPATH.'components.xml');
if (count($data->item) != 0) foreach ($data->item as $item) {
if ($componentname == $item->slug) {
$component = stripslashes(htmlspecialchars_decode($item->value, ENT_QUOTES));
break;
}
}
}
return self::getMenuHTMLImpl($menu, $showTitles, $component);
}
public static function getMenuHTMLImpl(&$menu, $showTitles=false, $component=null) {
$html = '';
foreach ($menu as &$item) {
if (!isset($component)) {
$href = @$item['link'] ? $item['link'] : (function_exists('find_i18n_url') ? find_i18n_url($item['url'],$item['parent']) : find_url($item['url'],$item['parent']));
}
$urlclass = (preg_match('/^[a-z]/i',$item['url']) ? '' : 'x') . $item['url'];
$parentclass = !$item['parent'] ? '' : (preg_match('/^[a-z]/i',$item['parent']) ? ' ' : ' x') . $item['parent'];
$classes = $urlclass . $parentclass .
($item['current'] ? ' current' : ($item['currentpath'] ? ' currentpath' : '')) .
(isset($item['children']) && count($item['children']) > 0 ? ' open' : ($item['haschildren'] ? ' closed' : ''));
$text = $item['menu'] ? $item['menu'] : $item['title'];
$title = $item['title'] ? $item['title'] : $item['menu'];
if (isset($component)) {
$navitem = new I18nNavigationItem($item, $classes, $text, $title, $showTitles, $component);
$html .= self::getMenuItem($component, $navitem);
} else {
if ($showTitles) {
$html .= '<li class="' . $classes . '"><a href="' . $href . '" >' . $title . '</a>';
} else {
$html .= '<li class="' . $classes . '"><a href="' . $href . '" title="' . htmlspecialchars(html_entity_decode($title, ENT_QUOTES, 'UTF-8')) . '">' . $text . '</a>';
}
if (isset($item['children']) && count($item['children']) > 0) {
$html .= '<ul>' . self::getMenuHTMLImpl($item['children'], $showTitles, $component) . '</ul>';
}
$html .= '</li>' . "\n";
}
}
return $html;
}
private static function getMenuItem($component, $item) {
ob_start();
eval("?>" . $component . "<?php ");
$content = ob_get_contents();
ob_end_clean();
return $content;
}
public static function getBreadcrumbs($slug) {
$slug = '' . $slug;
$pages = self::getPages();
$breadcrumbs = array();
$deflang = function_exists('return_i18n_default_language') ? return_i18n_default_language() : null;
for ($url = $slug; $url && isset($pages[$url]); $url = $pages[$url]['parent']) {
array_unshift($breadcrumbs, array(
'url' => $url,
'parent' => $pages[$url]['parent'],
'menu' => self::getProperty($url,'menu',$deflang),
'title' => self::getProperty($url,'title',$deflang),
));
}
return $breadcrumbs;
}
public static function outputBreadcrumbs($slug) {
$slug = '' . $slug;
$breadcrumbs = self::getBreadcrumbs($slug);
foreach ($breadcrumbs as &$item) {
$text = $item['menu'] ? $item['menu'] : $item['title'];
$title = $item['title'] ? $item['title'] : $item['menu'];
$url = function_exists('find_i18n_url') ? find_i18n_url($item['url'],$item['parent']) : find_url($item['url'],$item['parent']);
echo ' » <span class="breadcrumb"><a href="' . $url . '" title="' .
strip_quotes($title) . '">' . $text . '</a></span>';
}
}
}
class I18nNavigationItem {
private $item;
private $classes;
private $text;
private $title;
private $showTitles;
private $component;
private $deflang = null;
private $data = array();
public function I18nNavigationItem($item, $classes, $text, $title, $showTitles, $component) {
$this->item = $item;
$this->classes = $classes;
$this->text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');
$this->title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
$this->showTitles = $showTitles;
$this->component = $component;
$this->deflang = function_exists('return_i18n_default_language') ? return_i18n_default_language() : null;
}
public function __get($name) {
switch($name) {
case 'id':
case 'url':
case 'slug': return $this->item['url'];
case 'parent': return $this->item['parent'];
case 'classes': return $this->classes;
case 'text': return $this->text;
case 'title': return $this->title;
case 'current':
case 'iscurrent':
case 'isCurrent': return $this->item['current'];
case 'currentpath':
case 'currentPath':
case 'iscurrentpath':
case 'isCurrentPath': return $this->item['currentpath'];
case 'haschildren':
case 'hasChildren': return $this->item['haschildren'];
case 'open':
case 'isOpen': return isset($this->item['children']) && count($this->item['children']) > 0;
case 'closed':
case 'isClosed': return $this->item['haschildren'] && (!isset($this->item['children']) || count($this->item['children']) <= 0);
case 'titles':
case 'showtitles':
case 'showTitles': return $this->showTitles;
case 'link':
if (@$this->item['link']) {
return $this->item['link'];
} else if (function_exists('find_i18n_url')) {
return find_i18n_url($this->item['url'], $this->item['parent']);
} else {
return find_url($this->item['url'], $this->item['parent']);
}
case 'simplelink':
case 'simpleLink':
if (@$this->item['link']) {
return $this->item['link'];
} else {
return find_url($this->item['url'], $this->item['parent']);
}
case 'content':
return html_entity_decode(stripslashes((string) $this->getProp('content')), ENT_QUOTES, 'UTF-8');
case 'tags':
return preg_split('/\s*,\s*/', trim(html_entity_decode(stripslashes((string) $this->getProp('meta')), ENT_QUOTES, 'UTF-8')));
default:
return (string) $this->getProp($name);
}
}
public function outputChildren() {
if (isset($this->item['children']) && count($this->item['children']) > 0) {
echo I18nNavigationFrontend::getMenuHTMLImpl($this->item['children'], $this->showTitles, $this->component);
}
}
private function getProp($name) {
$value = null;
if ($this->deflang !== null) {
$languages = return_i18n_languages();
foreach ($languages as $language) {
if (!isset($this->data[$language])) {
$this->data[$language] = @getXML(GSDATAPAGESPATH . $this->url.($language == $this->deflang ? '' : '_' . $language).'.xml');
}
if (@$this->data[$language]->$name) return $this->data[$language]->$name;
}
return null;
} else {
if (!isset($this->data[''])) {
$this->data[''] = @getXML(GSDATAPAGESPATH . $this->url.'.xml');
}
return $this->data['']->$name;
}
}
}