1<?php
2/**
3 * @package     Joomla.Site
4 * @subpackage  mod_menu
5 *
6 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
7 * @license     GNU General Public License version 2 or later; see LICENSE.txt
8 */
9
10defined('_JEXEC') or die;
11
12/**
13 * Helper for mod_menu
14 *
15 * @since  1.5
16 */
17class ModMenuHelper
18{
19	/**
20	 * Get a list of the menu items.
21	 *
22	 * @param   \Joomla\Registry\Registry  &$params  The module options.
23	 *
24	 * @return  array
25	 *
26	 * @since   1.5
27	 */
28	public static function getList(&$params)
29	{
30		$app = JFactory::getApplication();
31		$menu = $app->getMenu();
32
33		// Get active menu item
34		$base = self::getBase($params);
35		$user = JFactory::getUser();
36		$levels = $user->getAuthorisedViewLevels();
37		asort($levels);
38		$key = 'menu_items' . $params . implode(',', $levels) . '.' . $base->id;
39		$cache = JFactory::getCache('mod_menu', '');
40
41		if ($cache->contains($key))
42		{
43			$items = $cache->get($key);
44		}
45		else
46		{
47			$path           = $base->tree;
48			$start          = (int) $params->get('startLevel', 1);
49			$end            = (int) $params->get('endLevel', 0);
50			$showAll        = $params->get('showAllChildren', 1);
51			$items          = $menu->getItems('menutype', $params->get('menutype'));
52			$hidden_parents = array();
53			$lastitem       = 0;
54
55			if ($items)
56			{
57				foreach ($items as $i => $item)
58				{
59					$item->parent = false;
60
61					if (isset($items[$lastitem]) && $items[$lastitem]->id == $item->parent_id && $item->params->get('menu_show', 1) == 1)
62					{
63						$items[$lastitem]->parent = true;
64					}
65
66					if (($start && $start > $item->level)
67						|| ($end && $item->level > $end)
68						|| (!$showAll && $item->level > 1 && !in_array($item->parent_id, $path))
69						|| ($start > 1 && !in_array($item->tree[$start - 2], $path)))
70					{
71						unset($items[$i]);
72						continue;
73					}
74
75					// Exclude item with menu item option set to exclude from menu modules
76					if (($item->params->get('menu_show', 1) == 0) || in_array($item->parent_id, $hidden_parents))
77					{
78						$hidden_parents[] = $item->id;
79						unset($items[$i]);
80						continue;
81					}
82
83					$item->deeper     = false;
84					$item->shallower  = false;
85					$item->level_diff = 0;
86
87					if (isset($items[$lastitem]))
88					{
89						$items[$lastitem]->deeper     = ($item->level > $items[$lastitem]->level);
90						$items[$lastitem]->shallower  = ($item->level < $items[$lastitem]->level);
91						$items[$lastitem]->level_diff = ($items[$lastitem]->level - $item->level);
92					}
93
94					$lastitem     = $i;
95					$item->active = false;
96					$item->flink  = $item->link;
97
98					// Reverted back for CMS version 2.5.6
99					switch ($item->type)
100					{
101						case 'separator':
102							break;
103
104						case 'heading':
105							// No further action needed.
106							break;
107
108						case 'url':
109							if ((strpos($item->link, 'index.php?') === 0) && (strpos($item->link, 'Itemid=') === false))
110							{
111								// If this is an internal Joomla link, ensure the Itemid is set.
112								$item->flink = $item->link . '&Itemid=' . $item->id;
113							}
114							break;
115
116						case 'alias':
117							$item->flink = 'index.php?Itemid=' . $item->params->get('aliasoptions');
118
119							// Get the language of the target menu item when site is multilingual
120							if (JLanguageMultilang::isEnabled())
121							{
122								$newItem = JFactory::getApplication()->getMenu()->getItem((int) $item->params->get('aliasoptions'));
123
124								// Use language code if not set to ALL
125								if ($newItem != null && $newItem->language && $newItem->language !== '*')
126								{
127									$item->flink .= '&lang=' . $newItem->language;
128								}
129							}
130							break;
131
132						default:
133							$item->flink = 'index.php?Itemid=' . $item->id;
134							break;
135					}
136
137					if ((strpos($item->flink, 'index.php?') !== false) && strcasecmp(substr($item->flink, 0, 4), 'http'))
138					{
139						$item->flink = JRoute::_($item->flink, true, $item->params->get('secure'));
140					}
141					else
142					{
143						$item->flink = JRoute::_($item->flink);
144					}
145
146					// We prevent the double encoding because for some reason the $item is shared for menu modules and we get double encoding
147					// when the cause of that is found the argument should be removed
148					$item->title          = htmlspecialchars($item->title, ENT_COMPAT, 'UTF-8', false);
149					$item->anchor_css     = htmlspecialchars($item->params->get('menu-anchor_css', ''), ENT_COMPAT, 'UTF-8', false);
150					$item->anchor_title   = htmlspecialchars($item->params->get('menu-anchor_title', ''), ENT_COMPAT, 'UTF-8', false);
151					$item->anchor_rel     = htmlspecialchars($item->params->get('menu-anchor_rel', ''), ENT_COMPAT, 'UTF-8', false);
152					$item->menu_image     = $item->params->get('menu_image', '') ?
153						htmlspecialchars($item->params->get('menu_image', ''), ENT_COMPAT, 'UTF-8', false) : '';
154					$item->menu_image_css = htmlspecialchars($item->params->get('menu_image_css', ''), ENT_COMPAT, 'UTF-8', false);
155				}
156
157				if (isset($items[$lastitem]))
158				{
159					$items[$lastitem]->deeper     = (($start ?: 1) > $items[$lastitem]->level);
160					$items[$lastitem]->shallower  = (($start ?: 1) < $items[$lastitem]->level);
161					$items[$lastitem]->level_diff = ($items[$lastitem]->level - ($start ?: 1));
162				}
163			}
164
165			$cache->store($items, $key);
166		}
167
168		return $items;
169	}
170
171	/**
172	 * Get base menu item.
173	 *
174	 * @param   \Joomla\Registry\Registry  &$params  The module options.
175	 *
176	 * @return  object
177	 *
178	 * @since	3.0.2
179	 */
180	public static function getBase(&$params)
181	{
182		// Get base menu item from parameters
183		if ($params->get('base'))
184		{
185			$base = JFactory::getApplication()->getMenu()->getItem($params->get('base'));
186		}
187		else
188		{
189			$base = false;
190		}
191
192		// Use active menu item if no base found
193		if (!$base)
194		{
195			$base = self::getActive($params);
196		}
197
198		return $base;
199	}
200
201	/**
202	 * Get active menu item.
203	 *
204	 * @param   \Joomla\Registry\Registry  &$params  The module options.
205	 *
206	 * @return  object
207	 *
208	 * @since	3.0.2
209	 */
210	public static function getActive(&$params)
211	{
212		$menu = JFactory::getApplication()->getMenu();
213
214		return $menu->getActive() ?: self::getDefault();
215	}
216
217	/**
218	 * Get default menu item (home page) for current language.
219	 *
220	 * @return  object
221	 */
222	public static function getDefault()
223	{
224		$menu = JFactory::getApplication()->getMenu();
225		$lang = JFactory::getLanguage();
226
227		// Look for the home menu
228		if (JLanguageMultilang::isEnabled())
229		{
230			return $menu->getDefault($lang->getTag());
231		}
232		else
233		{
234			return $menu->getDefault();
235		}
236	}
237}
238