File manager - Edit - /home/verseaumee/ptitsanes/libraries/gantry5/src/classes/Gantry/Framework/Menu.php
Back
<?php /** * @package Gantry5 * @author RocketTheme http://www.rockettheme.com * @copyright Copyright (C) 2007 - 2022 RocketTheme, LLC * @license GNU/GPLv2 and later * * http://www.gnu.org/licenses/gpl-2.0.html */ namespace Gantry\Framework; use Gantry\Component\Gantry\GantryTrait; use Gantry\Component\Menu\AbstractMenu; use Gantry\Component\Menu\Item; use Gantry\Joomla\MenuHelper; use Joomla\CMS\Application\CMSApplication; use Joomla\CMS\Factory; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Menu\MenuItem; use Joomla\CMS\Router\Route; use Joomla\CMS\Version; use Joomla\Registry\Registry; /** * Class Menu * @package Gantry\Framework */ class Menu extends AbstractMenu { use GantryTrait; /** @var bool */ protected $isAdmin; /** @var CMSApplication */ protected $application; /** @var \Joomla\CMS\Menu\AbstractMenu */ protected $menu; public function __construct() { /** @var CMSApplication $app */ $app = Factory::getApplication(); if ($app->isClient('administrator')) { $this->isAdmin = true; $this->application = CMSApplication::getInstance('site'); } else { $this->isAdmin = false; $this->application = $app; } if (Multilanguage::isEnabled()) { $language = $app->getLanguage(); $tag = $language->getTag(); } else { $tag = '*'; } $this->menu = $this->application->getMenu(); $this->default = $this->menu->getDefault($tag); $this->active = $this->menu->getActive(); } /** * @param string|int $offset * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($offset) { return $this->offsetGet($offset) !== null; } /** * @param string|int $offset * @return Item|null */ #[\ReturnTypeWillChange] public function offsetGet($offset) { $item = isset($this->items[$offset]) ? $this->items[$offset] : null; if (!$this->isAdmin) { return $item && $item->enabled ? $item : null; } return $item; } /** * @param array $params */ public function init(&$params) { parent::init($params); if (!empty($params['admin'])) { $menuType = MenuHelper::getMenuType($params['menu']); $config = $this->config(); $this->id = $menuType->id; $config->set('settings.title', $menuType->title); $config->set('settings.description', $menuType->description); } } /** * Return list of menus. * * @return array * @throws \RuntimeException */ public function getMenus() { return array_keys($this->getMenuOptions()); } /** * Return list of menus. * * @return array * @throws \RuntimeException */ public function getMenuOptions() { static $items; if ($items === null) { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('a.menutype')) ->select($db->quoteName('a.title')) ->from($db->quoteName('#__menu_types', 'a')) ->where($db->quoteName('a.client_id') . ' = 0'); $db->setQuery($query); $items = $db->loadAssocList('menutype'); $items = array_map(static function($val) { return $val['title']; }, $items); natsort($items); } return $items; } /** * Get menu ids. * * @return int[] */ public function getMenuIds() { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select('a.id') ->from('#__menu_types AS a'); $query->where('a.client_id = 0'); $db->setQuery($query); return $db->loadColumn(); } /** * @return array */ public function getGroupedItems() { $groups = []; // Works also in Joomla 4 require_once JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php'; // Get the menu items. $items = \MenusHelper::getMenuLinks(); // Build the groups arrays. foreach ($items as $item) { // Initialize the group. $groups[$item->menutype] = []; // Build the options array. foreach ($item->links as $link) { $groups[$item->menutype][$link->value] = [ 'spacing' => str_repeat(' ', max(0, $link->level-1)), 'label' => $link->text ]; } } return $groups; } /** * Return default menu. * * @return string|null */ public function getDefaultMenuName() { return $this->default ? $this->default->menutype : null; } /** * Returns true if the platform implements a Default menu. * * @return bool */ public function hasDefaultMenu() { return true; } /** * Return active menu. * * @return string|null */ public function getActiveMenuName() { return $this->active ? $this->active->menutype : null; } /** * Returns true if the platform implements an Active menu. * * @return boolean */ public function hasActiveMenu() { return true; } /** * @return string|null */ public function getCacheId() { /** @var CMSApplication $application */ $application = Factory::getApplication(); $user = $application->getIdentity(); if ($user && !$user->guest) { return null; } return $this->active ? $this->active->id : 0; } /** * @param MenuItem $item * @return bool */ public function isActive($item) { $tree = $this->base->tree; if (\in_array($item->id, $tree, false)) { return true; } if ($item->type === 'alias') { $aliasToId = $item->link_id; if (\count($tree) > 0 && $aliasToId === $tree[\count($tree) - 1]) { return (bool) $this->params['highlightAlias']; } if (\in_array($aliasToId, $tree, false)) { return (bool) $this->params['highlightParentAlias']; } } return false; } /** * @param MenuItem $item * @return bool */ public function isCurrent($item) { return $item->id == $this->active->id || ($item->type === 'alias' && $item->getParams()->get('aliasoptions') == $this->active->id); } /** * Get menu items from the platform. * * @param array $params * @return array<string,object|MenuItem> List of routes to the pages. */ protected function getItemsFromPlatform($params) { /** @var CMSApplication $app */ $app = Factory::getApplication(); // Items are already filtered by access and language, in admin we need to work around that. if ($app->isClient('administrator')) { $items = $this->getMenuItemsInAdmin($params['menu']); } else { $attributes = ['menutype']; $values = [$params['menu']]; $items = []; foreach ($this->menu->getItems($attributes, $values) as $item) { $items[$item->id] = $item; } $items = array_replace($this->getMenuItemIds($params['menu']), $items); } return $items; } /** * @param array<string,object|MenuItem> $menuItems * @param array[] $items * @return Item[] */ public function createMenuItems($menuItems, $items) { // Generate lookup indexes using menu item ids and paths. $idLookup = []; $pathLookup = []; foreach ($items as $path => &$item) { if (isset($item['yaml_path'])) { $path = $item['yaml_path']; } $path = strtolower(str_replace('/__', '/', trim($path, '_'))); $item['yaml_path'] = $path; $pathLookup[$path] = &$item; if (isset($item['id']) && is_numeric($item['id'])) { $idLookup[$item['id']] = &$item; } } unset($item); $map = []; $list = []; // Create menu items for the pages. foreach ($menuItems as $menuItem) { $id = $menuItem->id; $path = $menuItem->route; // Try to locate Gantry menu item. if (isset($idLookup[$id])) { // Id found, use it. $data = $idLookup[$id]; } elseif (isset($pathLookup[$path])) { // ID not found, use route instead. $data = $pathLookup[$path]; } else { // Menu item is not in YAML file. $data = ['yaml_path' => $path]; } $map[$data['yaml_path']] = $id; $item = $this->createMenuItem($data, $menuItem); $list[$item->id] = $item; } // Create particles which are only inside the menu YAML. foreach ($pathLookup as $path => $data) { // Ignore everything which is not a module or particle type. if (isset($map[$path]) || !isset($data['type']) || !\in_array($data['type'], ['module', 'particle'], true)) { continue; } $level = substr_count($path, '/'); if ($level) { $parentRoute = $level ? dirname($path) : ''; // If we cannot locate parent, we need to skip the menu item. if (!isset($map[$parentRoute])) { continue; } $parent_id = $map[$parentRoute]; } else { $parent_id = ''; } $data['id'] = $path; $data['parent_id'] = $parent_id; $data['path'] = $path; $tree = isset($list[$parent_id]) ? $list[$parent_id]->tree : []; $tree[] = $item->id; $data['tree'] = $tree; $item = $this->createMenuItem($data); $list[$item->id] = $item; } return $list; } /** * @param Registry $params * @param array $item * @return bool */ public static function updateJParams($params, $item) { $modified = false; // Convert Gantry params to Registry format. $all = Menu::encodeJParams($item); // Registry thinks that empty strings do not exist, so work around that. $list = $params->toArray(); foreach ($all as $var => $value) { $old = isset($list[$var]) ? $list[$var] : null; if ($value !== $old) { if (null === $value) { // Remove default value. $params->remove($var); } else { // Change value. $params->set($var, $value); } $modified = true; } } return $modified; } /** * @param array $item * @param bool $defaultsAsNull * @return int[] */ public static function encodeJParams($item = [], $defaultsAsNull = true) { // These are stored in Joomla menu item. static $ignoreList = ['type', 'link', 'title', 'anchor_class', 'image', 'icon_only', 'target', 'enabled']; $version = Version::MAJOR_VERSION; // Flag menu item to contain gantry data. $params = [ 'gantry' => 1 ]; $defaults = Item::$defaults; $item = static::normalizeMenuItem($item + $defaults, $ignoreList, true); foreach ($item as $var => $value) { if (is_array($value)) { // Joomla has different format for lists than Gantry, convert to Joomla supported version. if (in_array($var, ['attributes', 'link_attributes'], true)) { $i = $version < 4 ? 0 : 10; $list = []; foreach ($value as $k => $v) { if (is_array($v)) { if ($version < 4) { // Joomla 3: Save lists as {"fieldname0":{"key":"key","value":"value"}, ...} $list["{$var}{$i}"] = ['key' => key($v), 'value' => current($v)]; } else { // Joomla 4: Save lists as {"__field10":{"key":"key","value":"value"}, ...} $list["__field{$i}"] = ['key' => key($v), 'value' => current($v)]; } } else { $list[$k] = $v; } $i++; } $value = $list; } elseif (in_array($var, ['options', 'columns', 'columns_count'])) { $value = json_encode($value); } } // Prefix gantry parameters and save them. $var = 'gantry-' . $var; if ($defaultsAsNull && $value == (isset($defaults[$var]) ? $defaults[$var] : null)) { $params[$var] = null; } else { $params[$var] = $value; } } return $params; } /** * @param iterable $params * @return array|null */ public static function decodeJParams($params) { $properties = []; // Add Gantry menu item properties from the menu item. $paramsEmbedded = !empty($params['gantry']); foreach ($params as $param => $value) { if (strpos($param, 'gantry-') === 0) { $param = substr($param, 7); // Convert input from Joomla list format. if (is_object($value)) { $value = get_object_vars($value); } if (is_array($value) && in_array($param, ['attributes', 'link_attributes'], true)) { $list = []; foreach ($value as $v) { if (is_object($v) && isset($v->key, $v->value)) { $list[] = [$v->key => $v->value]; } elseif (is_array($v) && isset($v['key'], $v['value'])) { $list[] = [$v['key'] => $v['value']]; } } $value = $list; } elseif ($param === 'options') { $value = $value ? json_decode($value, true) : []; } elseif (!is_array($value) && in_array($param, ['columns', 'columns_count'], true)) { $value = $value ? json_decode($value, true) : []; } $properties[$param] = $value; } } return $paramsEmbedded || $properties ? $properties : null; } /** * @param array $data * @param MenuItem|object|null $menuItem * @return Item */ protected function createMenuItem($data, $menuItem = null) { if ($menuItem) { // This logic was originally copied from Joomla 3.10 mod_menu/helper.php (joomla-cms/staging, 2021-11-09). // We should keep the contents of the function similar to Joomla in order to review it against any changes. $id = (int)$menuItem->id; $type = $menuItem->type; $link = $menuItem->link; $params = method_exists($menuItem, 'getParams') ? $menuItem->getParams() : null; $enabled = $params && $params->get('menu_show', 1); // Figure out menu link. switch ($type) { case 'heading': case 'separator': // Check if menu item contains a particle. if ($params && !empty($params->get('gantry-particle'))) { $type = 'particle'; $options = $params->get('gantry-options'); $enabled = isset($options['particle']['enabled']) ? $options['particle']['enabled'] : true; } // These types have no link. $link = null; break; case 'url': if ((strpos($link, 'index.php?') === 0) && (strpos($link, 'Itemid=') === false)) { // If this is an internal Joomla link, ensure the Itemid is set. $link .= '&Itemid=' . $id; } break; case 'alias': // If this is an alias use the item id stored in the parameters to make the link. $link = 'index.php?Itemid=' . $params->get('aliasoptions', 0); // Get the language of the target menu item when site is multilingual if (Multilanguage::isEnabled()) { $menu = $this->application->getMenu(); $newItem = $menu && $params ? $menu->getItem((int) $params->get('aliasoptions')) : null; // Use language code if not set to ALL if ($newItem && $newItem->language && $newItem->language !== '*') { $link .= '&lang=' . $newItem->language; } } break; case 'component': default: $link = 'index.php?Itemid=' . $menuItem->id; if (isset($menuItem->query['format']) && $this->application->get('sef_suffix')) { $link .= '&format=' . $menuItem->query['format']; } break; } // Get default target from Joomla. switch ($menuItem->browserNav) { default: case 0: // Target window: Parent. $target = '_self'; break; case 1: // Target window: New with navigation. $target = '_blank'; break; case 2: // Target window: New without navigation. $target = '_nonav'; break; } $level = (int)$menuItem->level; $properties = [ 'id' => $id, 'parent_id' => $level !== 1 ? (int)$menuItem->parent_id : '', 'path' => $menuItem->route, 'tree' => $menuItem->tree, 'alias' => $menuItem->alias, 'type' => $type, 'link' => $link, 'enabled' => $enabled, 'level' => $level, 'link_title' => $params ? $params->get('menu-anchor_title', '') : '', 'rel' => $params ? $params->get('menu-anchor_rel', '') : '', ]; $props = $params ? static::decodeJParams($params) : null; if (null !== $props) { $paramsEmbedded = true; foreach ($props as $param => $value) { $properties[$param] = $value; } } else { $paramsEmbedded = false; } // Add menu item properties from menu configuration. if ($paramsEmbedded === false) { $properties = array_replace($properties, $data); } // And if not available in configuration, default to Joomla. $properties += [ 'title' => $menuItem->title, 'anchor_class' => $params ? $params->get('menu-anchor_css', '') : '', 'image' => $params ? $params->get('menu_image', '') : '', 'icon_only' => $params ? !$params->get('menu_text', 1) : false, 'target' => $target ]; } else { // There is no Joomla menu item. $properties = $data; $route = $data['id']; $level = substr_count($route, '/') + 1; $properties['enabled'] = !isset($properties['options']['particle']['enabled']) || !empty($properties['options']['particle']['enabled']); $properties['alias'] = Gantry::basename($route); $properties['level'] = $level; // Deal with special types which do not have link. if (in_array($properties['type'], ['module', 'particle', 'separator', 'heading'], true)) { $properties['link'] = null; } } $item = new Item($this, $properties); $link = $item->link; if ($item->type === 'url') { // Moved from modules/mod_menu/tmpl/default_url.php, not sure why Joomla had application logic in there. // Keep compatibility to Joomla menu module, but we need non-encoded version of the url. $link = htmlspecialchars_decode(\JFilterOutput::ampReplace(htmlspecialchars($link, ENT_COMPAT|ENT_SUBSTITUTE, 'UTF-8'))); } if (!$link) { $url = false; } elseif ((strpos($link, 'index.php?') !== false) && strcasecmp(substr($link, 0, 4), 'http')) { $url = Route::_($link, false, $params->get('secure')); } else { $url = Route::_($link, false); } $item->url($url); return $item; } /** * @param array $item * @param array $ignore * @param bool $keepDefaults * @return array */ protected static function normalizeMenuItem(array $item, array $ignore = [], $keepDefaults = false) { static $ignoreList = [ // Never save derived values. 'id', 'path', 'route', 'alias', 'parent_id', 'level', 'group', 'current', 'yaml_path', 'yaml_alias' ]; return Item::normalize($item, array_merge($ignore, $ignoreList), $keepDefaults); } /** * Get base menu item. * * If itemid is not specified or does not exist, return active menu item. * If there is no active menu item, fall back to home page for the current language. * If there is no home page, return null. * * @param int $itemid * * @return object|null */ protected function calcBase($itemid = null) { $menu = $this->application->getMenu(); // Get base menu item. $base = $itemid && $itemid !== '/' ? $menu->getItem($itemid) : null; // Use active menu item or fall back to default menu item. return $base ?: $this->active ?: $this->default; } /** * Get a list of the menu items. * * @param array $params * @param array $items */ public function getList(array $params, array $items) { // Get base menu item for this menu (defaults to active menu item). $this->base = $this->calcBase($params['base']); // Make sure that the menu item exists. if (!$this->base && !$this->application->isClient('administrator')) { return; } $tree = isset($this->base->tree) ? $this->base->tree : []; $start = (int)$params['startLevel']; $max = (int)$params['maxLevels']; $end = $max ? $start + $max - 1 : 0; $this->root = $start > 1 && isset($tree[$start - 2]) ? (int)$tree[$start - 2] : ''; $menuItems = $this->createMenuItems($this->getItemsFromPlatform($params), $items); foreach ($menuItems as $item) { $level = $item->level; if ($item->id === $this->root) { $this->add($item); continue; } if (($start && $start > $level) || ($end && $level > $end) || ($start > 1 && !in_array($this->root, $item->tree, false))) { continue; } $this->add($item); } } /** * @param string $menutype * @return array */ private function getMenuItemIds($menutype) { $db = \JFactory::getDbo(); $query = $db->getQuery(true) ->select('m.id, m.alias, m.path AS route, m.level, m.parent_id') ->from('#__menu AS m') ->where('m.menutype = ' . $db->quote($menutype)) ->where('m.parent_id > 0') ->where('m.client_id = 0') ->where('m.published >= 0') ->order('m.lft'); // Set the query $db->setQuery($query); $items = []; foreach ($db->loadAssocList('id') as $id => $data) { $data += ['type' => 'separator', 'tree' => [], 'title' => '', 'link' => null, 'browserNav' => null]; $items[$id] = (object)$data; } foreach ($items as &$item) { // Get parent information. $parent_tree = []; if (isset($items[$item->parent_id])) { $parent_tree = $items[$item->parent_id]->tree; } // Create tree. $parent_tree[] = $item->id; $item->tree = $parent_tree; } return $items; } /** * This code is taken from Joomla\CMS\Menu\SiteMenu::load() * * @param string $menutype * @return array */ private function getMenuItemsInAdmin($menutype) { $loader = static function () use ($menutype) { $db = \JFactory::getDbo(); $query = $db->getQuery(true) ->select('m.id, m.menutype, m.title, m.alias, m.note, m.path AS route, m.link, m.type, m.level, m.language') ->select($db->quoteName('m.browserNav') . ', m.access, m.params, m.home, m.img, m.template_style_id, m.component_id, m.parent_id') ->select('e.element as component') ->from('#__menu AS m') ->join('LEFT', '#__extensions AS e ON m.component_id = e.extension_id') ->where('m.menutype = ' . $db->quote($menutype)) ->where('m.parent_id > 0') ->where('m.client_id = 0') ->where('m.published >= 0') ->order('m.lft'); // Set the query $db->setQuery($query); $list = []; foreach ($db->loadAssocList('id') as $id => $data) { $list[$id] = new MenuItem($data); } return $list; }; try { /** @var \JCacheControllerCallback $cache */ $cache = \JFactory::getCache('com_menus', 'callback'); $items = $cache->get($loader, [], md5(get_class($this) . $menutype), false); } catch (\JCacheException $e) { try { $items = $loader(); } catch (\JDatabaseExceptionExecuting $databaseException) { throw new \RuntimeException(\JText::sprintf('JERROR_LOADING_MENUS', $databaseException->getMessage())); } } catch (\JDatabaseExceptionExecuting $e) { throw new \RuntimeException(\JText::sprintf('JERROR_LOADING_MENUS', $e->getMessage())); } foreach ($items as &$item) { // Get parent information. $parent_tree = []; if (isset($items[$item->parent_id])) { $parent_tree = $items[$item->parent_id]->tree; } // Create tree. $parent_tree[] = $item->id; $item->tree = $parent_tree; // Create the query array. $url = str_replace('index.php?', '', $item->link); $url = str_replace('&', '&', $url); parse_str($url, $item->query); } return array_values($items); } }
| ver. 1.4 |
Github
|
.
| PHP 8.5.7 | Generation time: 0 |
proxy
|
phpinfo
|
Settings