2017-05-19 12:33:30 +00:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* @package Joomla.Administrator
|
|
|
|
* @subpackage com_menus
|
|
|
|
*
|
2020-11-28 01:33:45 +00:00
|
|
|
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
2017-05-19 12:33:30 +00:00
|
|
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
|
|
|
*/
|
2018-06-20 16:26:51 +00:00
|
|
|
|
2017-05-19 12:33:30 +00:00
|
|
|
namespace Joomla\Component\Menus\Administrator\Helper;
|
|
|
|
|
2020-03-24 22:21:49 +00:00
|
|
|
\defined('_JEXEC') or die;
|
2018-06-20 16:26:51 +00:00
|
|
|
|
2020-02-04 20:59:27 +00:00
|
|
|
use Joomla\CMS\Application\ApplicationHelper;
|
2020-02-11 07:12:52 +00:00
|
|
|
use Joomla\CMS\Component\ComponentHelper;
|
2017-08-17 21:31:26 +00:00
|
|
|
use Joomla\CMS\Factory;
|
2020-02-11 07:12:52 +00:00
|
|
|
use Joomla\CMS\Filesystem\File;
|
2019-02-03 20:17:58 +00:00
|
|
|
use Joomla\CMS\Filesystem\Folder;
|
2018-09-23 10:14:29 +00:00
|
|
|
use Joomla\CMS\Helper\ContentHelper;
|
2017-05-19 12:33:30 +00:00
|
|
|
use Joomla\CMS\Language\Associations;
|
|
|
|
use Joomla\CMS\Language\Multilanguage;
|
2018-10-19 04:47:18 +00:00
|
|
|
use Joomla\CMS\Language\Text;
|
2019-11-30 21:38:08 +00:00
|
|
|
use Joomla\CMS\Menu\AdministratorMenuItem;
|
2017-08-17 21:31:26 +00:00
|
|
|
use Joomla\CMS\Table\Table;
|
2018-11-01 10:24:58 +00:00
|
|
|
use Joomla\Database\DatabaseInterface;
|
2019-10-19 13:23:10 +00:00
|
|
|
use Joomla\Database\ParameterType;
|
2017-08-17 21:31:26 +00:00
|
|
|
use Joomla\Registry\Registry;
|
2017-05-19 12:33:30 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Menus component helper.
|
|
|
|
*
|
|
|
|
* @since 1.6
|
|
|
|
*/
|
2018-09-23 10:14:29 +00:00
|
|
|
class MenusHelper extends ContentHelper
|
2017-05-19 12:33:30 +00:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Defines the valid request variables for the reverse lookup.
|
2019-07-11 20:37:27 +00:00
|
|
|
*
|
|
|
|
* @var array
|
2017-05-19 12:33:30 +00:00
|
|
|
*/
|
|
|
|
protected static $_filter = array('option', 'view', 'layout');
|
|
|
|
|
2019-02-03 20:17:58 +00:00
|
|
|
/**
|
|
|
|
* List of preset include paths
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2019-02-03 20:17:58 +00:00
|
|
|
*/
|
|
|
|
protected static $presets = null;
|
|
|
|
|
2017-05-19 12:33:30 +00:00
|
|
|
/**
|
|
|
|
* Gets a standard form of a link for lookups.
|
|
|
|
*
|
|
|
|
* @param mixed $request A link string or array of request variables.
|
|
|
|
*
|
|
|
|
* @return mixed A link in standard option-view-layout form, or false if the supplied response is invalid.
|
|
|
|
*
|
|
|
|
* @since 1.6
|
|
|
|
*/
|
|
|
|
public static function getLinkKey($request)
|
|
|
|
{
|
|
|
|
if (empty($request))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the link is in the form of index.php?...
|
|
|
|
if (is_string($request))
|
|
|
|
{
|
|
|
|
$args = array();
|
|
|
|
|
|
|
|
if (strpos($request, 'index.php') === 0)
|
|
|
|
{
|
|
|
|
parse_str(parse_url(htmlspecialchars_decode($request), PHP_URL_QUERY), $args);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parse_str($request, $args);
|
|
|
|
}
|
|
|
|
|
|
|
|
$request = $args;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only take the option, view and layout parts.
|
|
|
|
foreach ($request as $name => $value)
|
|
|
|
{
|
|
|
|
if ((!in_array($name, self::$_filter)) && (!($name == 'task' && !array_key_exists('view', $request))))
|
|
|
|
{
|
|
|
|
// Remove the variables we want to ignore.
|
|
|
|
unset($request[$name]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ksort($request);
|
|
|
|
|
|
|
|
return 'index.php?' . http_build_query($request, '', '&');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the menu list for create a menu module
|
|
|
|
*
|
|
|
|
* @param int $clientId Optional client id - viz 0 = site, 1 = administrator, can be NULL for all
|
|
|
|
*
|
|
|
|
* @return array The menu array list
|
|
|
|
*
|
|
|
|
* @since 1.6
|
|
|
|
*/
|
|
|
|
public static function getMenuTypes($clientId = 0)
|
|
|
|
{
|
2018-07-13 13:21:22 +00:00
|
|
|
$db = Factory::getDbo();
|
2017-05-19 12:33:30 +00:00
|
|
|
$query = $db->getQuery(true)
|
2019-10-19 13:23:10 +00:00
|
|
|
->select($db->quoteName('a.menutype'))
|
|
|
|
->from($db->quoteName('#__menu_types', 'a'));
|
2017-05-19 12:33:30 +00:00
|
|
|
|
|
|
|
if (isset($clientId))
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$clientId = (int) $clientId;
|
|
|
|
$query->where($db->quoteName('a.client_id') . ' = :clientId')
|
|
|
|
->bind(':clientId', $clientId, ParameterType::INTEGER);
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$db->setQuery($query);
|
|
|
|
|
|
|
|
return $db->loadColumn();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a list of menu links for one or all menus.
|
|
|
|
*
|
|
|
|
* @param string $menuType An option menu to filter the list on, otherwise all menu with given client id links
|
|
|
|
* are returned as a grouped array.
|
|
|
|
* @param integer $parentId An optional parent ID to pivot results around.
|
|
|
|
* @param integer $mode An optional mode. If parent ID is set and mode=2, the parent and children are excluded from the list.
|
|
|
|
* @param array $published An optional array of states
|
|
|
|
* @param array $languages Optional array of specify which languages we want to filter
|
2020-06-28 18:54:18 +00:00
|
|
|
* @param int $clientId Optional client id - viz 0 = site, 1 = administrator, can be NULL for all (used only if menutype not given)
|
2017-05-19 12:33:30 +00:00
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*
|
|
|
|
* @since 1.6
|
|
|
|
*/
|
|
|
|
public static function getMenuLinks($menuType = null, $parentId = 0, $mode = 0, $published = array(), $languages = array(), $clientId = 0)
|
|
|
|
{
|
2020-01-11 13:35:01 +00:00
|
|
|
$hasClientId = $clientId !== null;
|
2019-10-19 13:23:10 +00:00
|
|
|
$clientId = (int) $clientId;
|
|
|
|
|
2018-07-13 13:21:22 +00:00
|
|
|
$db = Factory::getDbo();
|
2017-05-19 12:33:30 +00:00
|
|
|
$query = $db->getQuery(true)
|
2019-10-19 13:23:10 +00:00
|
|
|
->select(
|
|
|
|
[
|
|
|
|
'DISTINCT ' . $db->quoteName('a.id', 'value'),
|
|
|
|
$db->quoteName('a.title', 'text'),
|
|
|
|
$db->quoteName('a.alias'),
|
|
|
|
$db->quoteName('a.level'),
|
|
|
|
$db->quoteName('a.menutype'),
|
|
|
|
$db->quoteName('a.client_id'),
|
|
|
|
$db->quoteName('a.type'),
|
|
|
|
$db->quoteName('a.published'),
|
|
|
|
$db->quoteName('a.template_style_id'),
|
|
|
|
$db->quoteName('a.checked_out'),
|
|
|
|
$db->quoteName('a.language'),
|
|
|
|
$db->quoteName('a.lft'),
|
|
|
|
$db->quoteName('e.name', 'componentname'),
|
|
|
|
$db->quoteName('e.element'),
|
|
|
|
]
|
2018-02-10 23:16:43 +00:00
|
|
|
)
|
2019-10-19 13:23:10 +00:00
|
|
|
->from($db->quoteName('#__menu', 'a'))
|
|
|
|
->join('LEFT', $db->quoteName('#__extensions', 'e'), $db->quoteName('e.extension_id') . ' = ' . $db->quoteName('a.component_id'));
|
2017-05-19 12:33:30 +00:00
|
|
|
|
|
|
|
if (Multilanguage::isEnabled())
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->select(
|
|
|
|
[
|
|
|
|
$db->quoteName('l.title', 'language_title'),
|
|
|
|
$db->quoteName('l.image', 'language_image'),
|
|
|
|
$db->quoteName('l.sef', 'language_sef'),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
->join('LEFT', $db->quoteName('#__languages', 'l'), $db->quoteName('l.lang_code') . ' = ' . $db->quoteName('a.language'));
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Filter by the type if given, this is more specific than client id
|
|
|
|
if ($menuType)
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->where('(' . $db->quoteName('a.menutype') . ' = :menuType OR ' . $db->quoteName('a.parent_id') . ' = 0)')
|
|
|
|
->bind(':menuType', $menuType);
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|
2019-10-19 13:23:10 +00:00
|
|
|
elseif ($hasClientId)
|
2017-05-19 12:33:30 +00:00
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->where($db->quoteName('a.client_id') . ' = :clientId')
|
|
|
|
->bind(':clientId', $clientId, ParameterType::INTEGER);
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Prevent the parent and children from showing if requested.
|
|
|
|
if ($parentId && $mode == 2)
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->join('LEFT', $db->quoteName('#__menu', 'p'), $db->quoteName('p.id') . ' = :parentId')
|
|
|
|
->where(
|
|
|
|
'(' . $db->quoteName('a.lft') . ' <= ' . $db->quoteName('p.lft')
|
|
|
|
. ' OR ' . $db->quoteName('a.rgt') . ' >= ' . $db->quoteName('p.rgt') . ')'
|
|
|
|
)
|
|
|
|
->bind(':parentId', $parentId, ParameterType::INTEGER);
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!empty($languages))
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->whereIn($db->quoteName('a.language'), (array) $languages, ParameterType::STRING);
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!empty($published))
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->whereIn($db->quoteName('a.published'), (array) $published);
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|
|
|
|
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->where($db->quoteName('a.published') . ' != -2');
|
|
|
|
$query->order($db->quoteName('a.lft') . ' ASC');
|
2017-05-19 12:33:30 +00:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
// Get the options.
|
|
|
|
$db->setQuery($query);
|
2017-05-19 12:33:30 +00:00
|
|
|
$links = $db->loadObjectList();
|
|
|
|
}
|
|
|
|
catch (\RuntimeException $e)
|
|
|
|
{
|
2018-07-13 13:21:22 +00:00
|
|
|
Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
|
2017-05-19 12:33:30 +00:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($menuType))
|
|
|
|
{
|
|
|
|
// If the menutype is empty, group the items by menutype.
|
2019-10-19 13:23:10 +00:00
|
|
|
$query = $db->getQuery(true)
|
2017-05-19 12:33:30 +00:00
|
|
|
->select('*')
|
2019-10-19 13:23:10 +00:00
|
|
|
->from($db->quoteName('#__menu_types'))
|
|
|
|
->where($db->quoteName('menutype') . ' <> ' . $db->quote(''))
|
|
|
|
->order(
|
|
|
|
[
|
|
|
|
$db->quoteName('title'),
|
|
|
|
$db->quoteName('menutype'),
|
|
|
|
]
|
|
|
|
);
|
2017-05-19 12:33:30 +00:00
|
|
|
|
2019-10-19 13:23:10 +00:00
|
|
|
if ($hasClientId)
|
2017-05-19 12:33:30 +00:00
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->where($db->quoteName('client_id') . ' = :clientId')
|
|
|
|
->bind(':clientId', $clientId, ParameterType::INTEGER);
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$db->setQuery($query);
|
2017-05-19 12:33:30 +00:00
|
|
|
$menuTypes = $db->loadObjectList();
|
|
|
|
}
|
|
|
|
catch (\RuntimeException $e)
|
|
|
|
{
|
2018-07-13 13:21:22 +00:00
|
|
|
Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
|
2017-05-19 12:33:30 +00:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a reverse lookup and aggregate the links.
|
|
|
|
$rlu = array();
|
|
|
|
|
|
|
|
foreach ($menuTypes as &$type)
|
|
|
|
{
|
|
|
|
$rlu[$type->menutype] = & $type;
|
|
|
|
$type->links = array();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Loop through the list of menu links.
|
|
|
|
foreach ($links as &$link)
|
|
|
|
{
|
|
|
|
if (isset($rlu[$link->menutype]))
|
|
|
|
{
|
|
|
|
$rlu[$link->menutype]->links[] = & $link;
|
|
|
|
|
|
|
|
// Cleanup garbage.
|
|
|
|
unset($link->menutype);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $menuTypes;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return $links;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-06-02 19:47:42 +00:00
|
|
|
* Get the associations
|
2017-05-19 12:33:30 +00:00
|
|
|
*
|
|
|
|
* @param integer $pk Menu item id
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*
|
|
|
|
* @since 3.0
|
|
|
|
*/
|
|
|
|
public static function getAssociations($pk)
|
|
|
|
{
|
|
|
|
$langAssociations = Associations::getAssociations('com_menus', '#__menu', 'com_menus.item', $pk, 'id', '', '');
|
|
|
|
$associations = array();
|
|
|
|
|
|
|
|
foreach ($langAssociations as $langAssociation)
|
|
|
|
{
|
|
|
|
$associations[$langAssociation->language] = $langAssociation->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $associations;
|
|
|
|
}
|
2017-08-17 21:31:26 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Load the menu items from database for the given menutype
|
|
|
|
*
|
|
|
|
* @param string $menutype The selected menu type
|
|
|
|
* @param boolean $enabledOnly Whether to load only enabled/published menu items.
|
|
|
|
* @param int[] $exclude The menu items to exclude from the list
|
|
|
|
*
|
2019-11-30 21:38:08 +00:00
|
|
|
* @return AdministratorMenuItem A root node with the menu items as children
|
2017-08-17 21:31:26 +00:00
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2017-08-17 21:31:26 +00:00
|
|
|
*/
|
|
|
|
public static function getMenuItems($menutype, $enabledOnly = false, $exclude = array())
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$root = new AdministratorMenuItem;
|
2018-11-01 10:24:58 +00:00
|
|
|
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
2017-08-17 21:31:26 +00:00
|
|
|
$query = $db->getQuery(true);
|
|
|
|
|
|
|
|
// Prepare the query.
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->select($db->quoteName('m') . '.*')
|
|
|
|
->from($db->quoteName('#__menu', 'm'))
|
|
|
|
->where(
|
|
|
|
[
|
|
|
|
$db->quoteName('m.menutype') . ' = :menutype',
|
|
|
|
$db->quoteName('m.client_id') . ' = 1',
|
|
|
|
$db->quoteName('m.id') . ' > 1',
|
|
|
|
]
|
|
|
|
)
|
|
|
|
->bind(':menutype', $menutype);
|
2017-08-17 21:31:26 +00:00
|
|
|
|
|
|
|
if ($enabledOnly)
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->where($db->quoteName('m.published') . ' = 1');
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Filter on the enabled states.
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->select($db->quoteName('e.element'))
|
|
|
|
->join('LEFT', $db->quoteName('#__extensions', 'e'), $db->quoteName('m.component_id') . ' = ' . $db->quoteName('e.extension_id'))
|
|
|
|
->extendWhere(
|
|
|
|
'AND',
|
|
|
|
[
|
|
|
|
$db->quoteName('e.enabled') . ' = 1',
|
|
|
|
$db->quoteName('e.enabled') . ' IS NULL',
|
|
|
|
],
|
|
|
|
'OR'
|
|
|
|
);
|
2017-08-17 21:31:26 +00:00
|
|
|
|
|
|
|
if (count($exclude))
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$exId = array_map('intval', array_filter($exclude, 'is_numeric'));
|
2017-08-17 21:31:26 +00:00
|
|
|
$exEl = array_filter($exclude, 'is_string');
|
|
|
|
|
|
|
|
if ($exId)
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->whereNotIn($db->quoteName('m.id'), $exId)
|
|
|
|
->whereNotIn($db->quoteName('m.parent_id'), $exId);
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($exEl)
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->whereNotIn($db->quoteName('e.element'), $exEl, ParameterType::STRING);
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Order by lft.
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->order($db->quoteName('m.lft'));
|
2017-08-17 21:31:26 +00:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2019-11-11 11:16:16 +00:00
|
|
|
$menuItems = [];
|
|
|
|
$iterator = $db->setQuery($query)->getIterator();
|
|
|
|
|
|
|
|
foreach ($iterator as $item)
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$menuItems[$item->id] = new AdministratorMenuItem((array) $item);
|
2019-11-11 11:16:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unset($iterator);
|
2017-08-17 21:31:26 +00:00
|
|
|
|
2019-02-03 20:17:58 +00:00
|
|
|
foreach ($menuItems as $menuitem)
|
2017-08-17 21:31:26 +00:00
|
|
|
{
|
2019-02-03 20:17:58 +00:00
|
|
|
// Resolve the alias item to get the original item
|
|
|
|
if ($menuitem->type == 'alias')
|
|
|
|
{
|
|
|
|
static::resolveAlias($menuitem);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($menuitem->link = in_array($menuitem->type, array('separator', 'heading', 'container')) ? '#' : trim($menuitem->link))
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$menuitem->submenu = array();
|
|
|
|
$menuitem->class = $menuitem->img ?? '';
|
|
|
|
$menuitem->scope = $menuitem->scope ?? null;
|
|
|
|
$menuitem->target = $menuitem->browserNav ? '_blank' : '';
|
2019-02-03 20:17:58 +00:00
|
|
|
}
|
|
|
|
|
2019-03-18 21:11:12 +00:00
|
|
|
$menuitem->ajaxbadge = $menuitem->getParams()->get('ajax-badge');
|
|
|
|
$menuitem->dashboard = $menuitem->getParams()->get('dashboard');
|
|
|
|
|
2019-02-03 20:17:58 +00:00
|
|
|
if ($menuitem->parent_id > 1)
|
|
|
|
{
|
|
|
|
if (isset($menuItems[$menuitem->parent_id]))
|
|
|
|
{
|
|
|
|
$menuItems[$menuitem->parent_id]->addChild($menuitem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$root->addChild($menuitem);
|
|
|
|
}
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (\RuntimeException $e)
|
|
|
|
{
|
2018-07-13 13:21:22 +00:00
|
|
|
Factory::getApplication()->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 'error');
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
2019-02-03 20:17:58 +00:00
|
|
|
return $root;
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Method to install a preset menu into database and link them to the given menutype
|
|
|
|
*
|
|
|
|
* @param string $preset The preset name
|
|
|
|
* @param string $menutype The target menutype
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*
|
|
|
|
* @throws \Exception
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2017-08-17 21:31:26 +00:00
|
|
|
*/
|
|
|
|
public static function installPreset($preset, $menutype)
|
|
|
|
{
|
2019-02-09 22:57:30 +00:00
|
|
|
$root = static::loadPreset($preset, false);
|
2017-08-17 21:31:26 +00:00
|
|
|
|
2019-02-09 22:57:30 +00:00
|
|
|
if (count($root->getChildren()) == 0)
|
2017-08-17 21:31:26 +00:00
|
|
|
{
|
2018-07-13 13:21:22 +00:00
|
|
|
throw new \Exception(Text::_('COM_MENUS_PRESET_LOAD_FAILED'));
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
2021-05-19 20:08:12 +00:00
|
|
|
static::installPresetItems($root, $menutype);
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Method to install a preset menu item into database and link it to the given menutype
|
|
|
|
*
|
2019-11-30 21:38:08 +00:00
|
|
|
* @param AdministratorMenuItem $node The parent node of the items to process
|
|
|
|
* @param string $menutype The target menutype
|
2017-08-17 21:31:26 +00:00
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*
|
|
|
|
* @throws \Exception
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2017-08-17 21:31:26 +00:00
|
|
|
*/
|
2019-02-09 22:57:30 +00:00
|
|
|
protected static function installPresetItems($node, $menutype)
|
2017-08-17 21:31:26 +00:00
|
|
|
{
|
|
|
|
$db = Factory::getDbo();
|
|
|
|
$query = $db->getQuery(true);
|
2019-02-09 22:57:30 +00:00
|
|
|
$items = $node->getChildren();
|
2017-08-17 21:31:26 +00:00
|
|
|
|
|
|
|
static $components = array();
|
|
|
|
|
|
|
|
if (!$components)
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->select(
|
|
|
|
[
|
|
|
|
$db->quoteName('extension_id'),
|
|
|
|
$db->quoteName('element'),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
->from($db->quoteName('#__extensions'))
|
|
|
|
->where($db->quoteName('type') . ' = ' . $db->quote('component'));
|
2017-08-17 21:31:26 +00:00
|
|
|
$components = $db->setQuery($query)->loadObjectList();
|
2019-09-17 08:48:58 +00:00
|
|
|
$components = array_column((array) $components, 'element', 'extension_id');
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
2017-11-08 00:39:15 +00:00
|
|
|
Factory::getApplication()->triggerEvent('onPreprocessMenuItems', array('com_menus.administrator.import', &$items, null, true));
|
|
|
|
|
2019-02-09 22:57:30 +00:00
|
|
|
foreach ($items as $item)
|
2017-08-17 21:31:26 +00:00
|
|
|
{
|
|
|
|
/** @var \JTableMenu $table */
|
|
|
|
$table = Table::getInstance('Menu');
|
|
|
|
|
|
|
|
$item->alias = $menutype . '-' . $item->title;
|
|
|
|
|
2020-02-04 20:59:27 +00:00
|
|
|
// Temporarily set unicodeslugs if a menu item has an unicode alias
|
2020-07-25 18:35:07 +00:00
|
|
|
$unicode = Factory::getApplication()->set('unicodeslugs', 1);
|
2020-02-04 20:59:27 +00:00
|
|
|
$item->alias = ApplicationHelper::stringURLSafe($item->alias);
|
2020-07-25 18:35:07 +00:00
|
|
|
Factory::getApplication()->set('unicodeslugs', $unicode);
|
2020-02-04 20:59:27 +00:00
|
|
|
|
2017-08-17 21:31:26 +00:00
|
|
|
if ($item->type == 'separator')
|
|
|
|
{
|
|
|
|
// Do not reuse a separator
|
|
|
|
$item->title = $item->title ?: '-';
|
|
|
|
$item->alias = microtime(true);
|
|
|
|
}
|
|
|
|
elseif ($item->type == 'heading' || $item->type == 'container')
|
|
|
|
{
|
|
|
|
// Try to match an existing record to have minimum collision for a heading
|
|
|
|
$keys = array(
|
|
|
|
'menutype' => $menutype,
|
|
|
|
'type' => $item->type,
|
|
|
|
'title' => $item->title,
|
2019-02-09 22:57:30 +00:00
|
|
|
'parent_id' => $item->getParent()->id,
|
2017-08-17 21:31:26 +00:00
|
|
|
'client_id' => 1,
|
|
|
|
);
|
|
|
|
$table->load($keys);
|
|
|
|
}
|
|
|
|
elseif ($item->type == 'url' || $item->type == 'component')
|
|
|
|
{
|
2017-11-08 00:39:15 +00:00
|
|
|
if (substr($item->link, 0, 8) === 'special:')
|
|
|
|
{
|
|
|
|
$special = substr($item->link, 8);
|
|
|
|
|
|
|
|
if ($special === 'language-forum')
|
|
|
|
{
|
|
|
|
$item->link = 'index.php?option=com_admin&view=help&layout=langforum';
|
|
|
|
}
|
|
|
|
elseif ($special === 'custom-forum')
|
|
|
|
{
|
|
|
|
$item->link = '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-17 21:31:26 +00:00
|
|
|
// Try to match an existing record to have minimum collision for a link
|
|
|
|
$keys = array(
|
|
|
|
'menutype' => $menutype,
|
|
|
|
'type' => $item->type,
|
|
|
|
'link' => $item->link,
|
2019-02-09 22:57:30 +00:00
|
|
|
'parent_id' => $item->getParent()->id,
|
2017-08-17 21:31:26 +00:00
|
|
|
'client_id' => 1,
|
|
|
|
);
|
|
|
|
$table->load($keys);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Translate "hideitems" param value from "element" into "menu-item-id"
|
2019-11-30 21:38:08 +00:00
|
|
|
if ($item->type == 'container' && count($hideitems = (array) $item->getParams()->get('hideitems')))
|
2017-08-17 21:31:26 +00:00
|
|
|
{
|
|
|
|
foreach ($hideitems as &$hel)
|
|
|
|
{
|
|
|
|
if (!is_numeric($hel))
|
|
|
|
{
|
|
|
|
$hel = array_search($hel, $components);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-19 13:23:10 +00:00
|
|
|
$query = $db->getQuery(true)
|
|
|
|
->select($db->quoteName('id'))
|
|
|
|
->from($db->quoteName('#__menu'))
|
|
|
|
->whereIn($db->quoteName('component_id'), $hideitems);
|
2017-08-17 21:31:26 +00:00
|
|
|
$hideitems = $db->setQuery($query)->loadColumn();
|
|
|
|
|
2019-11-30 21:38:08 +00:00
|
|
|
$item->getParams()->set('hideitems', $hideitems);
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$record = array(
|
|
|
|
'menutype' => $menutype,
|
|
|
|
'title' => $item->title,
|
|
|
|
'alias' => $item->alias,
|
|
|
|
'type' => $item->type,
|
|
|
|
'link' => $item->link,
|
2019-11-30 21:38:08 +00:00
|
|
|
'browserNav' => $item->browserNav,
|
2017-08-17 21:31:26 +00:00
|
|
|
'img' => $item->class,
|
|
|
|
'access' => $item->access,
|
2018-11-02 08:18:34 +00:00
|
|
|
'component_id' => array_search($item->element, $components) ?: 0,
|
2019-02-09 22:57:30 +00:00
|
|
|
'parent_id' => $item->getParent()->id,
|
2017-08-17 21:31:26 +00:00
|
|
|
'client_id' => 1,
|
|
|
|
'published' => 1,
|
|
|
|
'language' => '*',
|
|
|
|
'home' => 0,
|
2019-11-30 21:38:08 +00:00
|
|
|
'params' => (string) $item->getParams(),
|
2017-08-17 21:31:26 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
if (!$table->bind($record))
|
|
|
|
{
|
2021-02-03 14:09:56 +00:00
|
|
|
throw new \Exception($table->getError());
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
2019-02-09 22:57:30 +00:00
|
|
|
$table->setLocation($item->getParent()->id, 'last-child');
|
2017-08-17 21:31:26 +00:00
|
|
|
|
|
|
|
if (!$table->check())
|
|
|
|
{
|
2021-02-03 14:09:56 +00:00
|
|
|
throw new \Exception($table->getError());
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!$table->store())
|
|
|
|
{
|
2021-02-03 14:09:56 +00:00
|
|
|
throw new \Exception($table->getError());
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$item->id = $table->get('id');
|
|
|
|
|
2019-02-09 22:57:30 +00:00
|
|
|
if ($item->hasChildren())
|
2017-08-17 21:31:26 +00:00
|
|
|
{
|
2019-02-09 22:57:30 +00:00
|
|
|
static::installPresetItems($item, $menutype);
|
2017-08-17 21:31:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-03 20:17:58 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a custom preset externally via plugin or any other means.
|
|
|
|
* WARNING: Presets with same name will replace previously added preset *except* Joomla's default preset (joomla)
|
|
|
|
*
|
|
|
|
* @param string $name The unique identifier for the preset.
|
|
|
|
* @param string $title The display label for the preset.
|
|
|
|
* @param string $path The path to the preset file.
|
|
|
|
* @param bool $replace Whether to replace the preset with the same name if any (except 'joomla').
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2019-02-03 20:17:58 +00:00
|
|
|
*/
|
|
|
|
public static function addPreset($name, $title, $path, $replace = true)
|
|
|
|
{
|
|
|
|
if (static::$presets === null)
|
|
|
|
{
|
|
|
|
static::getPresets();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($name == 'joomla')
|
|
|
|
{
|
|
|
|
$replace = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (($replace || !array_key_exists($name, static::$presets)) && is_file($path))
|
|
|
|
{
|
|
|
|
$preset = new \stdClass;
|
|
|
|
|
|
|
|
$preset->name = $name;
|
|
|
|
$preset->title = $title;
|
|
|
|
$preset->path = $path;
|
|
|
|
|
|
|
|
static::$presets[$name] = $preset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a list of available presets.
|
|
|
|
*
|
|
|
|
* @return \stdClass[]
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2019-02-03 20:17:58 +00:00
|
|
|
*/
|
|
|
|
public static function getPresets()
|
|
|
|
{
|
|
|
|
if (static::$presets === null)
|
|
|
|
{
|
|
|
|
// Important: 'null' will cause infinite recursion.
|
|
|
|
static::$presets = array();
|
|
|
|
|
2020-02-11 07:12:52 +00:00
|
|
|
$components = ComponentHelper::getComponents();
|
|
|
|
$lang = Factory::getApplication()->getLanguage();
|
|
|
|
|
|
|
|
foreach ($components as $component)
|
|
|
|
{
|
|
|
|
if (!$component->enabled)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$folder = JPATH_ADMINISTRATOR . '/components/' . $component->option . '/presets/';
|
|
|
|
|
|
|
|
if (!Folder::exists($folder))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$lang->load($component->option . '.sys', JPATH_ADMINISTRATOR)
|
|
|
|
|| $lang->load($component->option . '.sys', JPATH_ADMINISTRATOR . '/components/' . $component->option);
|
|
|
|
|
|
|
|
$presets = Folder::files($folder, '.xml');
|
|
|
|
|
|
|
|
foreach ($presets as $preset)
|
|
|
|
{
|
|
|
|
$name = File::stripExt($preset);
|
|
|
|
$title = strtoupper($component->option . '_MENUS_PRESET_' . $name);
|
|
|
|
static::addPreset($name, $title, $folder . $preset);
|
|
|
|
}
|
|
|
|
}
|
2019-02-03 20:17:58 +00:00
|
|
|
|
|
|
|
// Load from template folder automatically
|
|
|
|
$app = Factory::getApplication();
|
|
|
|
$tpl = JPATH_THEMES . '/' . $app->getTemplate() . '/html/com_menus/presets';
|
|
|
|
|
|
|
|
if (is_dir($tpl))
|
|
|
|
{
|
|
|
|
$files = Folder::files($tpl, '\.xml$');
|
|
|
|
|
|
|
|
foreach ($files as $file)
|
|
|
|
{
|
|
|
|
$name = substr($file, 0, -4);
|
|
|
|
$title = str_replace('-', ' ', $name);
|
|
|
|
|
|
|
|
static::addPreset(strtolower($name), ucwords($title), $tpl . '/' . $file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return static::$presets;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load the menu items from a preset file into a hierarchical list of objects
|
|
|
|
*
|
2019-11-30 21:38:08 +00:00
|
|
|
* @param string $name The preset name
|
|
|
|
* @param bool $fallback Fallback to default (joomla) preset if the specified one could not be loaded?
|
|
|
|
* @param AdministratorMenuItem $parent Root node of the menu
|
2019-02-03 20:17:58 +00:00
|
|
|
*
|
2019-11-30 21:38:08 +00:00
|
|
|
* @return AdministratorMenuItem
|
2019-02-03 20:17:58 +00:00
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2019-02-03 20:17:58 +00:00
|
|
|
*/
|
|
|
|
public static function loadPreset($name, $fallback = true, $parent = null)
|
|
|
|
{
|
|
|
|
$presets = static::getPresets();
|
|
|
|
|
|
|
|
if (!$parent)
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$parent = new AdministratorMenuItem;
|
2019-02-03 20:17:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($presets[$name]) && ($xml = simplexml_load_file($presets[$name]->path, null, LIBXML_NOCDATA)) && $xml instanceof \SimpleXMLElement)
|
|
|
|
{
|
|
|
|
static::loadXml($xml, $parent);
|
|
|
|
}
|
2019-09-01 06:36:39 +00:00
|
|
|
elseif ($fallback && isset($presets['default']))
|
2019-02-03 20:17:58 +00:00
|
|
|
{
|
2019-09-01 06:36:39 +00:00
|
|
|
if (($xml = simplexml_load_file($presets['default']->path, null, LIBXML_NOCDATA)) && $xml instanceof \SimpleXMLElement)
|
2019-02-03 20:17:58 +00:00
|
|
|
{
|
|
|
|
static::loadXml($xml, $parent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Method to resolve the menu item alias type menu item
|
|
|
|
*
|
2019-11-30 21:38:08 +00:00
|
|
|
* @param AdministratorMenuItem &$item The alias object
|
2019-02-03 20:17:58 +00:00
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2019-02-03 20:17:58 +00:00
|
|
|
*/
|
|
|
|
public static function resolveAlias(&$item)
|
|
|
|
{
|
|
|
|
$obj = $item;
|
|
|
|
|
|
|
|
while ($obj->type == 'alias')
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$aliasTo = (int) $obj->getParams()->get('aliasoptions');
|
2019-02-03 20:17:58 +00:00
|
|
|
|
|
|
|
$db = Factory::getDbo();
|
|
|
|
$query = $db->getQuery(true);
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->select(
|
|
|
|
[
|
|
|
|
$db->quoteName('a.id'),
|
|
|
|
$db->quoteName('a.link'),
|
|
|
|
$db->quoteName('a.type'),
|
|
|
|
$db->quoteName('e.element'),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
->from($db->quoteName('#__menu', 'a'))
|
|
|
|
->join('LEFT', $db->quoteName('#__extensions', 'e'), $db->quoteName('e.extension_id') . ' = ' . $db->quoteName('a.component_id'))
|
|
|
|
->where($db->quoteName('a.id') . ' = :aliasTo')
|
|
|
|
->bind(':aliasTo', $aliasTo, ParameterType::INTEGER);
|
2019-02-03 20:17:58 +00:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$obj = new AdministratorMenuItem($db->setQuery($query)->loadAssoc());
|
2019-02-03 20:17:58 +00:00
|
|
|
|
|
|
|
if (!$obj)
|
|
|
|
{
|
|
|
|
$item->link = '';
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (\Exception $e)
|
|
|
|
{
|
|
|
|
$item->link = '';
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$item->id = $obj->id;
|
|
|
|
$item->link = $obj->link;
|
|
|
|
$item->type = $obj->type;
|
|
|
|
$item->element = $obj->element;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse the flat list of menu items and prepare the hierarchy of them using parent-child relationship.
|
|
|
|
*
|
2019-11-30 21:38:08 +00:00
|
|
|
* @param AdministratorMenuItem $item Menu item to preprocess
|
2019-02-03 20:17:58 +00:00
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2019-02-03 20:17:58 +00:00
|
|
|
*/
|
|
|
|
public static function preprocess($item)
|
|
|
|
{
|
|
|
|
// Resolve the alias item to get the original item
|
|
|
|
if ($item->type == 'alias')
|
|
|
|
{
|
|
|
|
static::resolveAlias($item);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($item->link = in_array($item->type, array('separator', 'heading', 'container')) ? '#' : trim($item->link))
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$item->class = $item->img ?? '';
|
|
|
|
$item->scope = $item->scope ?? null;
|
|
|
|
$item->target = $item->browserNav ? '_blank' : '';
|
2019-02-03 20:17:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load a menu tree from an XML file
|
|
|
|
*
|
2019-11-30 21:38:08 +00:00
|
|
|
* @param \SimpleXMLElement[] $elements The xml menuitem nodes
|
|
|
|
* @param AdministratorMenuItem $parent The menu hierarchy list to be populated
|
|
|
|
* @param string[] $replace The substring replacements for iterator type items
|
2019-02-03 20:17:58 +00:00
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2019-02-03 20:17:58 +00:00
|
|
|
*/
|
|
|
|
protected static function loadXml($elements, $parent, $replace = array())
|
|
|
|
{
|
|
|
|
foreach ($elements as $element)
|
|
|
|
{
|
|
|
|
if ($element->getName() != 'menuitem')
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$select = (string) $element['sql_select'];
|
|
|
|
$from = (string) $element['sql_from'];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Following is a repeatable group based on simple database query. This requires sql_* attributes (sql_select and sql_from are required)
|
|
|
|
* The values can be used like - "{sql:columnName}" in any attribute of repeated elements.
|
|
|
|
* The repeated elements are place inside this xml node but they will be populated in the same level in the rendered menu
|
|
|
|
*/
|
|
|
|
if ($select && $from)
|
|
|
|
{
|
|
|
|
$hidden = $element['hidden'] == 'true';
|
|
|
|
$where = (string) $element['sql_where'];
|
|
|
|
$order = (string) $element['sql_order'];
|
|
|
|
$group = (string) $element['sql_group'];
|
|
|
|
$lJoin = (string) $element['sql_leftjoin'];
|
|
|
|
$iJoin = (string) $element['sql_innerjoin'];
|
|
|
|
|
|
|
|
$db = Factory::getDbo();
|
|
|
|
$query = $db->getQuery(true);
|
|
|
|
$query->select($select)->from($from);
|
|
|
|
|
|
|
|
if ($where)
|
|
|
|
{
|
|
|
|
$query->where($where);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($order)
|
|
|
|
{
|
|
|
|
$query->order($order);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($group)
|
|
|
|
{
|
|
|
|
$query->group($group);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($lJoin)
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->join('LEFT', $lJoin);
|
2019-02-03 20:17:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($iJoin)
|
|
|
|
{
|
2019-10-19 13:23:10 +00:00
|
|
|
$query->join('INNER', $iJoin);
|
2019-02-03 20:17:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$results = $db->setQuery($query)->loadObjectList();
|
|
|
|
|
|
|
|
// Skip the entire group if no items to iterate over.
|
|
|
|
if ($results)
|
|
|
|
{
|
|
|
|
// Show the repeatable group heading node only if not set as hidden.
|
|
|
|
if (!$hidden)
|
|
|
|
{
|
|
|
|
$child = static::parseXmlNode($element, $replace);
|
|
|
|
$parent->addChild($child);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterate over the matching records, items goes in the same level (not $item->submenu) as this node.
|
2019-02-20 20:23:42 +00:00
|
|
|
if ('self' == (string) $element['sql_target'])
|
2019-02-03 20:17:58 +00:00
|
|
|
{
|
2019-02-20 20:23:42 +00:00
|
|
|
foreach ($results as $result)
|
|
|
|
{
|
|
|
|
static::loadXml($element->menuitem, $child, $result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
foreach ($results as $result)
|
|
|
|
{
|
|
|
|
static::loadXml($element->menuitem, $parent, $result);
|
|
|
|
}
|
2019-02-03 20:17:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$item = static::parseXmlNode($element, $replace);
|
|
|
|
|
|
|
|
// Process the child nodes
|
|
|
|
static::loadXml($element->menuitem, $item, $replace);
|
|
|
|
|
|
|
|
$parent->addChild($item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a menu item node from an xml element
|
|
|
|
*
|
|
|
|
* @param \SimpleXMLElement $node A menuitem element from preset xml
|
|
|
|
* @param string[] $replace The values to substitute in the title, link and element texts
|
|
|
|
*
|
|
|
|
* @return \stdClass
|
|
|
|
*
|
2019-03-09 10:20:38 +00:00
|
|
|
* @since 4.0.0
|
2019-02-03 20:17:58 +00:00
|
|
|
*/
|
|
|
|
protected static function parseXmlNode($node, $replace = array())
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$item = new AdministratorMenuItem;
|
2019-02-03 20:17:58 +00:00
|
|
|
|
|
|
|
$item->id = null;
|
|
|
|
$item->type = (string) $node['type'];
|
|
|
|
$item->title = (string) $node['title'];
|
2019-02-10 21:17:18 +00:00
|
|
|
$item->alias = (string) $node['alias'];
|
2019-02-03 20:17:58 +00:00
|
|
|
$item->link = (string) $node['link'];
|
2019-05-26 11:24:32 +00:00
|
|
|
$item->target = (string) $node['target'];
|
2019-02-03 20:17:58 +00:00
|
|
|
$item->element = (string) $node['element'];
|
|
|
|
$item->class = (string) $node['class'];
|
|
|
|
$item->icon = (string) $node['icon'];
|
|
|
|
$item->access = (int) $node['access'];
|
|
|
|
$item->scope = (string) $node['scope'] ?: 'default';
|
2019-02-17 23:10:10 +00:00
|
|
|
$item->ajaxbadge = (string) $node['ajax-badge'];
|
2019-02-20 20:23:42 +00:00
|
|
|
$item->dashboard = (string) $node['dashboard'];
|
2019-11-30 21:38:08 +00:00
|
|
|
|
|
|
|
$params = new Registry(trim($node->params));
|
|
|
|
$params->set('menu-permission', (string) $node['permission']);
|
2019-02-03 20:17:58 +00:00
|
|
|
|
|
|
|
if ($item->type == 'separator' && trim($item->title, '- '))
|
|
|
|
{
|
2019-11-30 21:38:08 +00:00
|
|
|
$params->set('text_separator', 1);
|
2019-02-03 20:17:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($item->type == 'heading' || $item->type == 'container')
|
|
|
|
{
|
|
|
|
$item->link = '#';
|
|
|
|
}
|
|
|
|
|
2019-02-09 22:57:30 +00:00
|
|
|
if ((string) $node['quicktask'])
|
|
|
|
{
|
2020-02-12 08:20:52 +00:00
|
|
|
$params->set('menu-quicktask', (string) $node['quicktask']);
|
2019-11-30 21:38:08 +00:00
|
|
|
$params->set('menu-quicktask-title', (string) $node['quicktask-title']);
|
|
|
|
$params->set('menu-quicktask-icon', (string) $node['quicktask-icon']);
|
|
|
|
$params->set('menu-quicktask-permission', (string) $node['quicktask-permission']);
|
2019-02-09 22:57:30 +00:00
|
|
|
}
|
|
|
|
|
2019-02-03 20:17:58 +00:00
|
|
|
// Translate attributes for iterator values
|
|
|
|
foreach ($replace as $var => $val)
|
|
|
|
{
|
|
|
|
$item->title = str_replace("{sql:$var}", $val, $item->title);
|
|
|
|
$item->element = str_replace("{sql:$var}", $val, $item->element);
|
|
|
|
$item->link = str_replace("{sql:$var}", $val, $item->link);
|
|
|
|
$item->class = str_replace("{sql:$var}", $val, $item->class);
|
|
|
|
$item->icon = str_replace("{sql:$var}", $val, $item->icon);
|
2020-02-12 08:20:52 +00:00
|
|
|
$params->set('menu-quicktask', str_replace("{sql:$var}", $val, $params->get('menu-quicktask')));
|
2019-02-03 20:17:58 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 21:38:08 +00:00
|
|
|
$item->setParams($params);
|
|
|
|
|
2019-02-03 20:17:58 +00:00
|
|
|
return $item;
|
|
|
|
}
|
2017-05-19 12:33:30 +00:00
|
|
|
}
|