Spade
Mini Shell
| Directory:~$ /home/lmsyaran/public_html/joomla4/ |
| [Home] [System Details] [Kill Me] |
ComponentHelper.php000064400000031767151156363670010412 0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Access\Access;
use Joomla\CMS\Component\Exception\MissingComponentException;
use Joomla\Registry\Registry;
/**
* Component helper class
*
* @since 1.5
*/
class ComponentHelper
{
/**
* The component list cache
*
* @var ComponentRecord[]
* @since 1.6
*/
protected static $components = array();
/**
* Get the component information.
*
* @param string $option The component option.
* @param boolean $strict If set and the component does not exist, the
enabled attribute will be set to false.
*
* @return ComponentRecord An object with the information for the
component.
*
* @since 1.5
*/
public static function getComponent($option, $strict = false)
{
$components = static::getComponents();
if (isset($components[$option]))
{
return $components[$option];
}
$result = new ComponentRecord;
$result->enabled = $strict ? false : true;
$result->setParams(new Registry);
return $result;
}
/**
* Checks if the component is enabled
*
* @param string $option The component option.
*
* @return boolean
*
* @since 1.5
*/
public static function isEnabled($option)
{
$components = static::getComponents();
return isset($components[$option]) &&
$components[$option]->enabled;
}
/**
* Checks if a component is installed
*
* @param string $option The component option.
*
* @return integer
*
* @since 3.4
*/
public static function isInstalled($option)
{
$components = static::getComponents();
return isset($components[$option]) ? 1 : 0;
}
/**
* Gets the parameter object for the component
*
* @param string $option The option for the component.
* @param boolean $strict If set and the component does not exist,
false will be returned
*
* @return Registry A Registry object.
*
* @see Registry
* @since 1.5
*/
public static function getParams($option, $strict = false)
{
return static::getComponent($option, $strict)->getParams();
}
/**
* Applies the global text filters to arbitrary text as per settings for
current user groups
*
* @param string $text The string to filter
*
* @return string The filtered string
*
* @since 2.5
*/
public static function filterText($text)
{
// Punyencoding utf8 email addresses
$text = \JFilterInput::getInstance()->emailToPunycode($text);
// Filter settings
$config = static::getParams('com_config');
$user = \JFactory::getUser();
$userGroups = Access::getGroupsByUser($user->get('id'));
$filters = $config->get('filters');
$blackListTags = array();
$blackListAttributes = array();
$customListTags = array();
$customListAttributes = array();
$whiteListTags = array();
$whiteListAttributes = array();
$whiteList = false;
$blackList = false;
$customList = false;
$unfiltered = false;
// Cycle through each of the user groups the user is in.
// Remember they are included in the Public group as well.
foreach ($userGroups as $groupId)
{
// May have added a group by not saved the filters.
if (!isset($filters->$groupId))
{
continue;
}
// Each group the user is in could have different filtering properties.
$filterData = $filters->$groupId;
$filterType = strtoupper($filterData->filter_type);
if ($filterType === 'NH')
{
// Maximum HTML filtering.
}
elseif ($filterType === 'NONE')
{
// No HTML filtering.
$unfiltered = true;
}
else
{
// Blacklist or whitelist.
// Preprocess the tags and attributes.
$tags = explode(',', $filterData->filter_tags);
$attributes = explode(',',
$filterData->filter_attributes);
$tempTags = array();
$tempAttributes = array();
foreach ($tags as $tag)
{
$tag = trim($tag);
if ($tag)
{
$tempTags[] = $tag;
}
}
foreach ($attributes as $attribute)
{
$attribute = trim($attribute);
if ($attribute)
{
$tempAttributes[] = $attribute;
}
}
// Collect the blacklist or whitelist tags and attributes.
// Each list is cumulative.
if ($filterType === 'BL')
{
$blackList = true;
$blackListTags = array_merge($blackListTags, $tempTags);
$blackListAttributes = array_merge($blackListAttributes,
$tempAttributes);
}
elseif ($filterType === 'CBL')
{
// Only set to true if Tags or Attributes were added
if ($tempTags || $tempAttributes)
{
$customList = true;
$customListTags = array_merge($customListTags, $tempTags);
$customListAttributes = array_merge($customListAttributes,
$tempAttributes);
}
}
elseif ($filterType === 'WL')
{
$whiteList = true;
$whiteListTags = array_merge($whiteListTags, $tempTags);
$whiteListAttributes = array_merge($whiteListAttributes,
$tempAttributes);
}
}
}
// Remove duplicates before processing (because the blacklist uses both
sets of arrays).
$blackListTags = array_unique($blackListTags);
$blackListAttributes = array_unique($blackListAttributes);
$customListTags = array_unique($customListTags);
$customListAttributes = array_unique($customListAttributes);
$whiteListTags = array_unique($whiteListTags);
$whiteListAttributes = array_unique($whiteListAttributes);
if (!$unfiltered)
{
// Custom blacklist precedes Default blacklist
if ($customList)
{
$filter = \JFilterInput::getInstance(array(), array(), 1, 1);
// Override filter's default blacklist tags and attributes
if ($customListTags)
{
$filter->tagBlacklist = $customListTags;
}
if ($customListAttributes)
{
$filter->attrBlacklist = $customListAttributes;
}
}
// Blacklists take second precedence.
elseif ($blackList)
{
// Remove the whitelisted tags and attributes from the black-list.
$blackListTags = array_diff($blackListTags, $whiteListTags);
$blackListAttributes = array_diff($blackListAttributes,
$whiteListAttributes);
$filter = \JFilterInput::getInstance($blackListTags,
$blackListAttributes, 1, 1);
// Remove whitelisted tags from filter's default blacklist
if ($whiteListTags)
{
$filter->tagBlacklist = array_diff($filter->tagBlacklist,
$whiteListTags);
}
// Remove whitelisted attributes from filter's default blacklist
if ($whiteListAttributes)
{
$filter->attrBlacklist = array_diff($filter->attrBlacklist,
$whiteListAttributes);
}
}
// Whitelists take third precedence.
elseif ($whiteList)
{
// Turn off XSS auto clean
$filter = \JFilterInput::getInstance($whiteListTags,
$whiteListAttributes, 0, 0, 0);
}
// No HTML takes last place.
else
{
$filter = \JFilterInput::getInstance();
}
$text = $filter->clean($text, 'html');
}
return $text;
}
/**
* Render the component.
*
* @param string $option The component option.
* @param array $params The component parameters
*
* @return string
*
* @since 1.5
* @throws MissingComponentException
*/
public static function renderComponent($option, $params = array())
{
$app = \JFactory::getApplication();
// Load template language files.
$template = $app->getTemplate(true)->template;
$lang = \JFactory::getLanguage();
$lang->load('tpl_' . $template, JPATH_BASE, null, false,
true)
|| $lang->load('tpl_' . $template, JPATH_THEMES .
"/$template", null, false, true);
if (empty($option))
{
throw new
MissingComponentException(\JText::_('JLIB_APPLICATION_ERROR_COMPONENT_NOT_FOUND'),
404);
}
if (JDEBUG)
{
\JProfiler::getInstance('Application')->mark('beforeRenderComponent
' . $option);
}
// Record the scope
$scope = $app->scope;
// Set scope to component name
$app->scope = $option;
// Build the component path.
$option = preg_replace('/[^A-Z0-9_\.-]/i', '',
$option);
$file = substr($option, 4);
// Define component path.
if (!defined('JPATH_COMPONENT'))
{
/**
* Defines the path to the active component for the request
*
* Note this constant is application aware and is different for each
application (site/admin).
*
* @var string
* @since 1.5
*/
define('JPATH_COMPONENT', JPATH_BASE .
'/components/' . $option);
}
if (!defined('JPATH_COMPONENT_SITE'))
{
/**
* Defines the path to the site element of the active component for the
request
*
* @var string
* @since 1.5
*/
define('JPATH_COMPONENT_SITE', JPATH_SITE .
'/components/' . $option);
}
if (!defined('JPATH_COMPONENT_ADMINISTRATOR'))
{
/**
* Defines the path to the admin element of the active component for the
request
*
* @var string
* @since 1.5
*/
define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR .
'/components/' . $option);
}
$path = JPATH_COMPONENT . '/' . $file . '.php';
// If component is disabled throw error
if (!static::isEnabled($option) || !file_exists($path))
{
throw new
MissingComponentException(\JText::_('JLIB_APPLICATION_ERROR_COMPONENT_NOT_FOUND'),
404);
}
// Load common and local language files.
$lang->load($option, JPATH_BASE, null, false, true) ||
$lang->load($option, JPATH_COMPONENT, null, false, true);
// Handle template preview outlining.
$contents = null;
// Execute the component.
$contents = static::executeComponent($path);
// Revert the scope
$app->scope = $scope;
if (JDEBUG)
{
\JProfiler::getInstance('Application')->mark('afterRenderComponent
' . $option);
}
return $contents;
}
/**
* Execute the component.
*
* @param string $path The component path.
*
* @return string The component output
*
* @since 1.7
*/
protected static function executeComponent($path)
{
ob_start();
require_once $path;
return ob_get_clean();
}
/**
* Load the installed components into the components property.
*
* @param string $option The element value for the extension
*
* @return boolean True on success
*
* @since 1.5
* @deprecated 4.0 Use JComponentHelper::load() instead
*/
protected static function _load($option)
{
return static::load($option);
}
/**
* Load the installed components into the components property.
*
* @param string $option The element value for the extension
*
* @return boolean True on success
*
* @since 3.2
* @note As of 4.0 this method will be restructured to only load the
data into memory
*/
protected static function load($option)
{
$loader = function ()
{
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName(array('extension_id',
'element', 'params', 'enabled'),
array('id', 'option', null, null)))
->from($db->quoteName('#__extensions'))
->where($db->quoteName('type') . ' = ' .
$db->quote('component'))
->where($db->quoteName('state') . ' = 0')
->where($db->quoteName('enabled') . ' = 1');
$db->setQuery($query);
return $db->loadObjectList('option',
'\JComponentRecord');
};
/** @var \JCacheControllerCallback $cache */
$cache = \JFactory::getCache('_system', 'callback');
try
{
static::$components = $cache->get($loader, array(), __METHOD__);
}
catch (\JCacheException $e)
{
static::$components = $loader();
}
// Core CMS will use '*' as a placeholder for required
parameter in this method. In 4.0 this will not be passed at all.
if (isset($option) && $option != '*')
{
// Log deprecated warning and display missing component warning only if
using deprecated format.
try
{
\JLog::add(
sprintf(
'Passing a parameter into %s() is deprecated and will be removed
in 4.0. Read %s::$components directly after loading the data.',
__METHOD__,
__CLASS__
),
\JLog::WARNING,
'deprecated'
);
}
catch (\RuntimeException $e)
{
// Informational log only
}
if (empty(static::$components[$option]))
{
/*
* Fatal error
*
* It is possible for this error to be reached before the global
\JLanguage instance has been loaded so we check for its presence
* before logging the error to ensure a human friendly message is
always given
*/
if (\JFactory::$language)
{
$msg =
\JText::sprintf('JLIB_APPLICATION_ERROR_COMPONENT_NOT_LOADING',
$option,
\JText::_('JLIB_APPLICATION_ERROR_COMPONENT_NOT_FOUND'));
}
else
{
$msg = sprintf('Error loading component: %1$s, %2$s',
$option, 'Component not found.');
}
\JLog::add($msg, \JLog::WARNING, 'jerror');
return false;
}
}
return true;
}
/**
* Get installed components
*
* @return ComponentRecord[] The components property
*
* @since 3.6.3
*/
public static function getComponents()
{
if (empty(static::$components))
{
static::load('*');
}
return static::$components;
}
}
ComponentRecord.php000064400000005307151156363670010400 0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component;
defined('JPATH_PLATFORM') or die;
use Joomla\Registry\Registry;
/**
* Object representing a component extension record
*
* @since 3.7.0
* @note As of 4.0 this class will no longer extend JObject
*/
class ComponentRecord extends \JObject
{
/**
* Primary key
*
* @var integer
* @since 3.7.0
*/
public $id;
/**
* The component name
*
* @var integer
* @since 3.7.0
*/
public $option;
/**
* The component parameters
*
* @var string|Registry
* @since 3.7.0
* @note This field is protected to require reading this field to proxy
through the getter to convert the params to a Registry instance
*/
protected $params;
/**
* Indicates if this component is enabled
*
* @var integer
* @since 3.7.0
*/
public $enabled;
/**
* Class constructor
*
* @param array $data The component record data to load
*
* @since 3.7.0
*/
public function __construct($data = array())
{
foreach ((array) $data as $key => $value)
{
$this->$key = $value;
}
}
/**
* Method to get certain otherwise inaccessible properties from the form
field object.
*
* @param string $name The property name for which to get the value.
*
* @return mixed The property value or null.
*
* @since 3.7.0
* @deprecated 4.0 Access the item parameters through the `getParams()`
method
*/
public function __get($name)
{
if ($name === 'params')
{
return $this->getParams();
}
return $this->get($name);
}
/**
* Method to set certain otherwise inaccessible properties of the form
field object.
*
* @param string $name The property name for which to set the value.
* @param mixed $value The value of the property.
*
* @return void
*
* @since 3.7.0
* @deprecated 4.0 Set the item parameters through the `setParams()`
method
*/
public function __set($name, $value)
{
if ($name === 'params')
{
$this->setParams($value);
return;
}
$this->set($name, $value);
}
/**
* Returns the menu item parameters
*
* @return Registry
*
* @since 3.7.0
*/
public function getParams()
{
if (!($this->params instanceof Registry))
{
$this->params = new Registry($this->params);
}
return $this->params;
}
/**
* Sets the menu item parameters
*
* @param Registry|string $params The data to be stored as the
parameters
*
* @return void
*
* @since 3.7.0
*/
public function setParams($params)
{
$this->params = $params;
}
}
Exception/MissingComponentException.php000064400000001634151156363670014407
0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Exception;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Router\Exception\RouteNotFoundException;
/**
* Exception class defining an error for a missing component
*
* @since 3.7.0
*/
class MissingComponentException extends RouteNotFoundException
{
/**
* Constructor
*
* @param string $message The Exception message to throw.
* @param integer $code The Exception code.
* @param \Exception $previous The previous exception used for the
exception chaining.
*
* @since 3.7.0
*/
public function __construct($message = '', $code = 404,
\Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
Router/RouterBase.php000064400000002572151156363670010633 0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router;
defined('JPATH_PLATFORM') or die;
/**
* Base component routing class
*
* @since 3.3
*/
abstract class RouterBase implements RouterInterface
{
/**
* Application object to use in the router
*
* @var \JApplicationCms
* @since 3.4
*/
public $app;
/**
* Menu object to use in the router
*
* @var \JMenu
* @since 3.4
*/
public $menu;
/**
* Class constructor.
*
* @param \JApplicationCms $app Application-object that the router
should use
* @param \JMenu $menu Menu-object that the router should
use
*
* @since 3.4
*/
public function __construct($app = null, $menu = null)
{
if ($app)
{
$this->app = $app;
}
else
{
$this->app = \JFactory::getApplication('site');
}
if ($menu)
{
$this->menu = $menu;
}
else
{
$this->menu = $this->app->getMenu();
}
}
/**
* Generic method to preprocess a URL
*
* @param array $query An associative array of URL arguments
*
* @return array The URL arguments to use to assemble the subsequent
URL.
*
* @since 3.3
*/
public function preprocess($query)
{
return $query;
}
}
Router/RouterInterface.php000064400000003115151156363670011653
0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router;
defined('JPATH_PLATFORM') or die;
/**
* Component routing interface
*
* @since 3.3
*/
interface RouterInterface
{
/**
* Prepare-method for URLs
* This method is meant to validate and complete the URL parameters.
* For example it can add the Itemid or set a language parameter.
* This method is executed on each URL, regardless of SEF mode switched
* on or not.
*
* @param array $query An associative array of URL arguments
*
* @return array The URL arguments to use to assemble the subsequent
URL.
*
* @since 3.3
*/
public function preprocess($query);
/**
* Build method for URLs
* This method is meant to transform the query parameters into a more
human
* readable form. It is only executed when SEF mode is switched on.
*
* @param array &$query An array of URL arguments
*
* @return array The URL arguments to use to assemble the subsequent
URL.
*
* @since 3.3
*/
public function build(&$query);
/**
* Parse method for URLs
* This method is meant to transform the human readable URL back into
* query parameters. It is only executed when SEF mode is switched on.
*
* @param array &$segments The segments of the URL to parse.
*
* @return array The URL attributes to be used by the application.
*
* @since 3.3
*/
public function parse(&$segments);
}
Router/RouterLegacy.php000064400000004261151156363670011162
0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router;
defined('JPATH_PLATFORM') or die;
/**
* Default routing class for missing or legacy component routers
*
* @since 3.3
*/
class RouterLegacy implements RouterInterface
{
/**
* Name of the component
*
* @var string
* @since 3.3
*/
protected $component;
/**
* Constructor
*
* @param string $component Component name without the com_ prefix
this router should react upon
*
* @since 3.3
*/
public function __construct($component)
{
$this->component = $component;
}
/**
* Generic preprocess function for missing or legacy component router
*
* @param array $query An associative array of URL arguments
*
* @return array The URL arguments to use to assemble the subsequent
URL.
*
* @since 3.3
*/
public function preprocess($query)
{
return $query;
}
/**
* Generic build function for missing or legacy component router
*
* @param array &$query An array of URL arguments
*
* @return array The URL arguments to use to assemble the subsequent
URL.
*
* @since 3.3
*/
public function build(&$query)
{
$function = $this->component . 'BuildRoute';
if (function_exists($function))
{
$segments = $function($query);
$total = count($segments);
for ($i = 0; $i < $total; $i++)
{
$segments[$i] = str_replace(':', '-',
$segments[$i]);
}
return $segments;
}
return array();
}
/**
* Generic parse function for missing or legacy component router
*
* @param array &$segments The segments of the URL to parse.
*
* @return array The URL attributes to be used by the application.
*
* @since 3.3
*/
public function parse(&$segments)
{
$function = $this->component . 'ParseRoute';
if (function_exists($function))
{
$total = count($segments);
for ($i = 0; $i < $total; $i++)
{
$segments[$i] = preg_replace('/-/', ':',
$segments[$i], 1);
}
return $function($segments);
}
return array();
}
}
Router/RouterView.php000064400000012623151156363670010671 0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\Router\Rules\RulesInterface;
/**
* View-based component routing class
*
* @since 3.5
*/
abstract class RouterView extends RouterBase
{
/**
* Name of the router of the component
*
* @var string
* @since 3.5
*/
protected $name;
/**
* Array of rules
*
* @var RulesInterface[]
* @since 3.5
*/
protected $rules = array();
/**
* Views of the component
*
* @var RouterViewConfiguration[]
* @since 3.5
*/
protected $views = array();
/**
* Register the views of a component
*
* @param RouterViewConfiguration $view View configuration object
*
* @return void
*
* @since 3.5
*/
public function registerView(RouterViewConfiguration $view)
{
$this->views[$view->name] = $view;
}
/**
* Return an array of registered view objects
*
* @return RouterViewConfiguration[] Array of registered view objects
*
* @since 3.5
*/
public function getViews()
{
return $this->views;
}
/**
* Get the path of views from target view to root view
* including content items of a nestable view
*
* @param array $query Array of query elements
*
* @return array List of views including IDs of content items
*
* @since 3.5
*/
public function getPath($query)
{
$views = $this->getViews();
$result = array();
// Get the right view object
if (isset($query['view']) &&
isset($views[$query['view']]))
{
$viewobj = $views[$query['view']];
}
// Get the path from the current item to the root view with all IDs
if (isset($viewobj))
{
$path = array_reverse($viewobj->path);
$start = true;
$childkey = false;
foreach ($path as $element)
{
$view = $views[$element];
if ($start)
{
$key = $view->key;
$start = false;
}
else
{
$key = $childkey;
}
$childkey = $view->parent_key;
if (($key || $view->key) && is_callable(array($this,
'get' . ucfirst($view->name) . 'Segment')))
{
if (isset($query[$key]))
{
$result[$view->name] = call_user_func_array(array($this,
'get' . ucfirst($view->name) . 'Segment'),
array($query[$key], $query));
}
elseif (isset($query[$view->key]))
{
$result[$view->name] = call_user_func_array(array($this,
'get' . ucfirst($view->name) . 'Segment'),
array($query[$view->key], $query));
}
else
{
$result[$view->name] = array();
}
}
else
{
$result[$view->name] = true;
}
}
}
return $result;
}
/**
* Get all currently attached rules
*
* @return RulesInterface[] All currently attached rules in an array
*
* @since 3.5
*/
public function getRules()
{
return $this->rules;
}
/**
* Add a number of router rules to the object
*
* @param RulesInterface[] $rules Array of
JComponentRouterRulesInterface objects
*
* @return void
*
* @since 3.5
*/
public function attachRules($rules)
{
foreach ($rules as $rule)
{
$this->attachRule($rule);
}
}
/**
* Attach a build rule
*
* @param RulesInterface $rule The function to be called.
*
* @return void
*
* @since 3.5
*/
public function attachRule(RulesInterface $rule)
{
$this->rules[] = $rule;
}
/**
* Remove a build rule
*
* @param RulesInterface $rule The rule to be removed.
*
* @return boolean Was a rule removed?
*
* @since 3.5
*/
public function detachRule(RulesInterface $rule)
{
foreach ($this->rules as $id => $r)
{
if ($r == $rule)
{
unset($this->rules[$id]);
return true;
}
}
return false;
}
/**
* Generic method to preprocess a URL
*
* @param array $query An associative array of URL arguments
*
* @return array The URL arguments to use to assemble the subsequent
URL.
*
* @since 3.5
*/
public function preprocess($query)
{
// Process the parsed variables based on custom defined rules
foreach ($this->rules as $rule)
{
$rule->preprocess($query);
}
return $query;
}
/**
* Build method for URLs
*
* @param array &$query Array of query elements
*
* @return array Array of URL segments
*
* @since 3.5
*/
public function build(&$query)
{
$segments = array();
// Process the parsed variables based on custom defined rules
foreach ($this->rules as $rule)
{
$rule->build($query, $segments);
}
return $segments;
}
/**
* Parse method for URLs
*
* @param array &$segments Array of URL string-segments
*
* @return array Associative array of query values
*
* @since 3.5
*/
public function parse(&$segments)
{
$vars = array();
// Process the parsed variables based on custom defined rules
foreach ($this->rules as $rule)
{
$rule->parse($segments, $vars);
}
return $vars;
}
/**
* Method to return the name of the router
*
* @return string Name of the router
*
* @since 3.5
*/
public function getName()
{
if (empty($this->name))
{
$r = null;
if (!preg_match('/(.*)Router/i', get_class($this), $r))
{
throw new
\Exception('JLIB_APPLICATION_ERROR_ROUTER_GET_NAME', 500);
}
$this->name = strtolower($r[1]);
}
return $this->name;
}
}
Router/RouterViewConfiguration.php000064400000010170151156363670013414
0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router;
defined('JPATH_PLATFORM') or die;
/**
* View-configuration class for the view-based component router
*
* @since 3.5
*/
class RouterViewConfiguration
{
/**
* Name of the view
*
* @var string
* @since 3.5
*/
public $name;
/**
* Key of the view
*
* @var string
* @since 3.5
*/
public $key = false;
/**
* Parentview of this one
*
* @var RouterViewconfiguration
* @since 3.5
*/
public $parent = false;
/**
* Key of the parent view
*
* @var string
* @since 3.5
*/
public $parent_key = false;
/**
* Is this view nestable?
*
* @var bool
* @since 3.5
*/
public $nestable = false;
/**
* Layouts that are supported by this view
*
* @var array
* @since 3.5
*/
public $layouts = array('default');
/**
* Child-views of this view
*
* @var RouterViewconfiguration[]
* @since 3.5
*/
public $children = array();
/**
* Keys used for this parent view by the child views
*
* @var array
* @since 3.5
*/
public $child_keys = array();
/**
* Path of views from this one to the root view
*
* @var array
* @since 3.5
*/
public $path = array();
/**
* Constructor for the View-configuration class
*
* @param string $name Name of the view
*
* @since 3.5
*/
public function __construct($name)
{
$this->name = $name;
$this->path[] = $name;
}
/**
* Set the name of the view
*
* @param string $name Name of the view
*
* @return RouterViewconfiguration This object for chaining
*
* @since 3.5
*/
public function setName($name)
{
$this->name = $name;
array_pop($this->path);
$this->path[] = $name;
return $this;
}
/**
* Set the key-identifier for the view
*
* @param string $key Key of the view
*
* @return RouterViewconfiguration This object for chaining
*
* @since 3.5
*/
public function setKey($key)
{
$this->key = $key;
return $this;
}
/**
* Set the parent view of this view
*
* @param RouterViewconfiguration $parent Parent view object
* @param string $parentKey Key of the parent view in
this context
*
* @return RouterViewconfiguration This object for chaining
*
* @since 3.5
*/
public function setParent(RouterViewconfiguration $parent, $parentKey =
false)
{
if ($this->parent)
{
$key = array_search($this, $this->parent->children);
if ($key !== false)
{
unset($this->parent->children[$key]);
}
if ($this->parent_key)
{
$child_key = array_search($this->parent_key,
$this->parent->child_keys);
unset($this->parent->child_keys[$child_key]);
}
}
$this->parent = $parent;
$parent->children[] = $this;
$this->path = $parent->path;
$this->path[] = $this->name;
$this->parent_key = $parentKey;
if ($parentKey)
{
$parent->child_keys[] = $parentKey;
}
return $this;
}
/**
* Set if this view is nestable or not
*
* @param bool $isNestable If set to true, the view is nestable
*
* @return RouterViewconfiguration This object for chaining
*
* @since 3.5
*/
public function setNestable($isNestable = true)
{
$this->nestable = (bool) $isNestable;
return $this;
}
/**
* Add a layout to this view
*
* @param string $layout Layouts that this view supports
*
* @return RouterViewconfiguration This object for chaining
*
* @since 3.5
*/
public function addLayout($layout)
{
$this->layouts[] = $layout;
$this->layouts = array_unique($this->layouts);
return $this;
}
/**
* Remove a layout from this view
*
* @param string $layout Layouts that this view supports
*
* @return RouterViewconfiguration This object for chaining
*
* @since 3.5
*/
public function removeLayout($layout)
{
$key = array_search($layout, $this->layouts);
if ($key !== false)
{
unset($this->layouts[$key]);
}
return $this;
}
}
Router/Rules/MenuRules.php000064400000015202151156363670011563
0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router\Rules;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Component\Router\RouterView;
/**
* Rule to identify the right Itemid for a view in a component
*
* @since 3.4
*/
class MenuRules implements RulesInterface
{
/**
* Router this rule belongs to
*
* @var RouterView
* @since 3.4
*/
protected $router;
/**
* Lookup array of the menu items
*
* @var array
* @since 3.4
*/
protected $lookup = array();
/**
* Class constructor.
*
* @param RouterView $router Router this rule belongs to
*
* @since 3.4
*/
public function __construct(RouterView $router)
{
$this->router = $router;
$this->buildLookup();
}
/**
* Finds the right Itemid for this query
*
* @param array &$query The query array to process
*
* @return void
*
* @since 3.4
*/
public function preprocess(&$query)
{
$active = $this->router->menu->getActive();
/**
* If the active item id is not the same as the supplied item id or we
have a supplied item id and no active
* menu item then we just use the supplied menu item and continue
*/
if (isset($query['Itemid']) && ($active === null ||
$query['Itemid'] != $active->id))
{
return;
}
// Get query language
$language = isset($query['lang']) ? $query['lang'] :
'*';
if (!isset($this->lookup[$language]))
{
$this->buildLookup($language);
}
// Check if the active menu item matches the requested query
if ($active !== null && isset($query['Itemid']))
{
// Check if active->query and supplied query are the same
$match = true;
foreach ($active->query as $k => $v)
{
if (isset($query[$k]) && $v !== $query[$k])
{
// Compare again without alias
if (is_string($v) && $v == current(explode(':',
$query[$k], 2)))
{
continue;
}
$match = false;
break;
}
}
if ($match)
{
// Just use the supplied menu item
return;
}
}
$needles = $this->router->getPath($query);
$layout = isset($query['layout']) &&
$query['layout'] !== 'default' ? ':' .
$query['layout'] : '';
if ($needles)
{
foreach ($needles as $view => $ids)
{
$viewLayout = $view . $layout;
if ($layout && isset($this->lookup[$language][$viewLayout]))
{
if (is_bool($ids))
{
$query['Itemid'] =
$this->lookup[$language][$viewLayout];
return;
}
foreach ($ids as $id => $segment)
{
if (isset($this->lookup[$language][$viewLayout][(int) $id]))
{
$query['Itemid'] =
$this->lookup[$language][$viewLayout][(int) $id];
return;
}
}
}
if (isset($this->lookup[$language][$view]))
{
if (is_bool($ids))
{
$query['Itemid'] = $this->lookup[$language][$view];
return;
}
foreach ($ids as $id => $segment)
{
if (isset($this->lookup[$language][$view][(int) $id]))
{
$query['Itemid'] =
$this->lookup[$language][$view][(int) $id];
return;
}
}
}
}
}
// Check if the active menuitem matches the requested language
if ($active && $active->component === 'com_' .
$this->router->getName()
&& ($language === '*' ||
in_array($active->language, array('*', $language)) ||
!\JLanguageMultilang::isEnabled()))
{
$query['Itemid'] = $active->id;
return;
}
// If not found, return language specific home link
$default = $this->router->menu->getDefault($language);
if (!empty($default->id))
{
$query['Itemid'] = $default->id;
}
}
/**
* Method to build the lookup array
*
* @param string $language The language that the lookup should be
built up for
*
* @return void
*
* @since 3.4
*/
protected function buildLookup($language = '*')
{
// Prepare the reverse lookup array.
if (!isset($this->lookup[$language]))
{
$this->lookup[$language] = array();
$component = ComponentHelper::getComponent('com_' .
$this->router->getName());
$views = $this->router->getViews();
$attributes = array('component_id');
$values = array((int) $component->id);
$attributes[] = 'language';
$values[] = array($language, '*');
$items = $this->router->menu->getItems($attributes, $values);
foreach ($items as $item)
{
if (isset($item->query['view'],
$views[$item->query['view']]))
{
$view = $item->query['view'];
$layout = '';
if (isset($item->query['layout']))
{
$layout = ':' . $item->query['layout'];
}
if ($views[$view]->key)
{
if (!isset($this->lookup[$language][$view . $layout]))
{
$this->lookup[$language][$view . $layout] = array();
}
if (!isset($this->lookup[$language][$view]))
{
$this->lookup[$language][$view] = array();
}
// If menuitem has no key set, we assume 0.
if (!isset($item->query[$views[$view]->key]))
{
$item->query[$views[$view]->key] = 0;
}
/**
* Here it will become a bit tricky
* language != * can override existing entries
* language == * cannot override existing entries
*/
if (!isset($this->lookup[$language][$view .
$layout][$item->query[$views[$view]->key]]) || $item->language !==
'*')
{
$this->lookup[$language][$view .
$layout][$item->query[$views[$view]->key]] = $item->id;
$this->lookup[$language][$view][$item->query[$views[$view]->key]]
= $item->id;
}
}
else
{
/**
* Here it will become a bit tricky
* language != * can override existing entries
* language == * cannot override existing entries
*/
if (!isset($this->lookup[$language][$view . $layout]) ||
$item->language !== '*')
{
$this->lookup[$language][$view . $layout] = $item->id;
$this->lookup[$language][$view] = $item->id;
}
}
}
}
}
}
/**
* Dummymethod to fullfill the interface requirements
*
* @param array &$segments The URL segments to parse
* @param array &$vars The vars that result from the segments
*
* @return void
*
* @since 3.4
* @codeCoverageIgnore
*/
public function parse(&$segments, &$vars)
{
}
/**
* Dummymethod to fullfill the interface requirements
*
* @param array &$query The vars that should be converted
* @param array &$segments The URL segments to create
*
* @return void
*
* @since 3.4
* @codeCoverageIgnore
*/
public function build(&$query, &$segments)
{
}
}
Router/Rules/NomenuRules.php000064400000005524151156363670012126
0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router\Rules;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\Router\RouterView;
/**
* Rule to process URLs without a menu item
*
* @since 3.4
*/
class NomenuRules implements RulesInterface
{
/**
* Router this rule belongs to
*
* @var RouterView
* @since 3.4
*/
protected $router;
/**
* Class constructor.
*
* @param RouterView $router Router this rule belongs to
*
* @since 3.4
*/
public function __construct(RouterView $router)
{
$this->router = $router;
}
/**
* Dummymethod to fullfill the interface requirements
*
* @param array &$query The query array to process
*
* @return void
*
* @since 3.4
* @codeCoverageIgnore
*/
public function preprocess(&$query)
{
}
/**
* Parse a menu-less URL
*
* @param array &$segments The URL segments to parse
* @param array &$vars The vars that result from the segments
*
* @return void
*
* @since 3.4
*/
public function parse(&$segments, &$vars)
{
$active = $this->router->menu->getActive();
if (!is_object($active))
{
$views = $this->router->getViews();
if (isset($views[$segments[0]]))
{
$vars['view'] = array_shift($segments);
if (isset($views[$vars['view']]->key) &&
isset($segments[0]))
{
$vars[$views[$vars['view']]->key] =
preg_replace('/-/', ':', array_shift($segments), 1);
}
}
}
}
/**
* Build a menu-less URL
*
* @param array &$query The vars that should be converted
* @param array &$segments The URL segments to create
*
* @return void
*
* @since 3.4
*/
public function build(&$query, &$segments)
{
$menu_found = false;
if (isset($query['Itemid']))
{
$item =
$this->router->menu->getItem($query['Itemid']);
if (!isset($query['option']) || ($item &&
$item->query['option'] === $query['option']))
{
$menu_found = true;
}
}
if (!$menu_found && isset($query['view']))
{
$views = $this->router->getViews();
if (isset($views[$query['view']]))
{
$view = $views[$query['view']];
$segments[] = $query['view'];
if ($view->key && isset($query[$view->key]))
{
if (is_callable(array($this->router, 'get' .
ucfirst($view->name) . 'Segment')))
{
$result = call_user_func_array(array($this->router,
'get' . ucfirst($view->name) . 'Segment'),
array($query[$view->key], $query));
$segments[] = str_replace(':', '-',
array_shift($result));
}
else
{
$segments[] = str_replace(':', '-',
$query[$view->key]);
}
unset($query[$views[$query['view']]->key]);
}
unset($query['view']);
}
}
}
}
Router/Rules/RulesInterface.php000064400000003157151156363670012565
0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router\Rules;
defined('JPATH_PLATFORM') or die;
/**
* RouterRules interface for Joomla
*
* @since 3.4
*/
interface RulesInterface
{
/**
* Prepares a query set to be handed over to the build() method.
* This should complete a partial query set to work as a complete
non-SEFed
* URL and in general make sure that all information is present and
properly
* formatted. For example, the Itemid should be retrieved and set here.
*
* @param array &$query The query array to process
*
* @return void
*
* @since 3.4
*/
public function preprocess(&$query);
/**
* Parses a URI to retrieve informations for the right route through
* the component.
* This method should retrieve all its input from its method arguments.
*
* @param array &$segments The URL segments to parse
* @param array &$vars The vars that result from the segments
*
* @return void
*
* @since 3.4
*/
public function parse(&$segments, &$vars);
/**
* Builds URI segments from a query to encode the necessary informations
* for a route in a human-readable URL.
* This method should retrieve all its input from its method arguments.
*
* @param array &$query The vars that should be converted
* @param array &$segments The URL segments to create
*
* @return void
*
* @since 3.4
*/
public function build(&$query, &$segments);
}
Router/Rules/StandardRules.php000064400000015231151156363670012421
0ustar00<?php
/**
* Joomla! Content Management System
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Component\Router\Rules;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\Router\RouterView;
/**
* Rule for the standard handling of component routing
*
* @since 3.4
*/
class StandardRules implements RulesInterface
{
/**
* Router this rule belongs to
*
* @var RouterView
* @since 3.4
*/
protected $router;
/**
* Class constructor.
*
* @param RouterView $router Router this rule belongs to
*
* @since 3.4
*/
public function __construct(RouterView $router)
{
$this->router = $router;
}
/**
* Dummymethod to fullfill the interface requirements
*
* @param array &$query The query array to process
*
* @return void
*
* @since 3.4
*/
public function preprocess(&$query)
{
}
/**
* Parse the URL
*
* @param array &$segments The URL segments to parse
* @param array &$vars The vars that result from the segments
*
* @return void
*
* @since 3.4
*/
public function parse(&$segments, &$vars)
{
// Get the views and the currently active query vars
$views = $this->router->getViews();
$active = $this->router->menu->getActive();
if ($active)
{
$vars = array_merge($active->query, $vars);
}
// We don't have a view or its not a view of this component! We stop
here
if (!isset($vars['view']) ||
!isset($views[$vars['view']]))
{
return;
}
// Copy the segments, so that we can iterate over all of them and at the
same time modify the original segments
$tempSegments = $segments;
// Iterate over the segments as long as a segment fits
foreach ($tempSegments as $segment)
{
// Our current view is nestable. We need to check first if the segment
fits to that
if ($views[$vars['view']]->nestable)
{
if (is_callable(array($this->router, 'get' .
ucfirst($views[$vars['view']]->name) . 'Id')))
{
$key = call_user_func_array(array($this->router, 'get' .
ucfirst($views[$vars['view']]->name) . 'Id'),
array($segment, $vars));
// Did we get a proper key? If not, we need to look in the child-views
if ($key)
{
$vars[$views[$vars['view']]->key] = $key;
array_shift($segments);
continue;
}
}
else
{
// The router is not complete. The get<View>Id() method is
missing.
return;
}
}
// Lets find the right view that belongs to this segment
$found = false;
foreach ($views[$vars['view']]->children as $view)
{
if (!$view->key)
{
if ($view->name === $segment)
{
// The segment is a view name
$parent = $views[$vars['view']];
$vars['view'] = $view->name;
$found = true;
if ($view->parent_key && isset($vars[$parent->key]))
{
$parent_key = $vars[$parent->key];
$vars[$view->parent_key] = $parent_key;
unset($vars[$parent->key]);
}
break;
}
}
elseif (is_callable(array($this->router, 'get' .
ucfirst($view->name) . 'Id')))
{
// Hand the data over to the router specific method and see if there
is a content item that fits
$key = call_user_func_array(array($this->router, 'get' .
ucfirst($view->name) . 'Id'), array($segment, $vars));
if ($key)
{
// Found the right view and the right item
$parent = $views[$vars['view']];
$vars['view'] = $view->name;
$found = true;
if ($view->parent_key && isset($vars[$parent->key]))
{
$parent_key = $vars[$parent->key];
$vars[$view->parent_key] = $parent_key;
unset($vars[$parent->key]);
}
$vars[$view->key] = $key;
break;
}
}
}
if (!$found)
{
return;
}
array_shift($segments);
}
}
/**
* Build a standard URL
*
* @param array &$query The vars that should be converted
* @param array &$segments The URL segments to create
*
* @return void
*
* @since 3.4
*/
public function build(&$query, &$segments)
{
if (!isset($query['Itemid'], $query['view']))
{
return;
}
// Get the menu item belonging to the Itemid that has been found
$item =
$this->router->menu->getItem($query['Itemid']);
if ($item === null
|| $item->component !== 'com_' .
$this->router->getName()
|| !isset($item->query['view']))
{
return;
}
// Get menu item layout
$mLayout = isset($item->query['layout']) ?
$item->query['layout'] : null;
// Get all views for this component
$views = $this->router->getViews();
// Return directly when the URL of the Itemid is identical with the URL
to build
if ($item->query['view'] === $query['view'])
{
$view = $views[$query['view']];
if (!$view->key)
{
unset($query['view']);
if (isset($query['layout']) && $mLayout ===
$query['layout'])
{
unset($query['layout']);
}
return;
}
if (isset($query[$view->key]) &&
$item->query[$view->key] == (int) $query[$view->key])
{
unset($query[$view->key]);
while ($view)
{
unset($query[$view->parent_key]);
$view = $view->parent;
}
unset($query['view']);
if (isset($query['layout']) && $mLayout ===
$query['layout'])
{
unset($query['layout']);
}
return;
}
}
// Get the path from the view of the current URL and parse it to the menu
item
$path = array_reverse($this->router->getPath($query), true);
$found = false;
foreach ($path as $element => $ids)
{
$view = $views[$element];
if ($found === false && $item->query['view'] ===
$element)
{
if ($view->nestable)
{
$found = true;
}
elseif ($view->children)
{
$found = true;
continue;
}
}
if ($found === false)
{
// Jump to the next view
continue;
}
if ($ids)
{
if ($view->nestable)
{
$found2 = false;
foreach (array_reverse($ids, true) as $id => $segment)
{
if ($found2)
{
$segments[] = str_replace(':', '-', $segment);
}
elseif ((int) $item->query[$view->key] === (int) $id)
{
$found2 = true;
}
}
}
elseif ($ids === true)
{
$segments[] = $element;
}
else
{
$segments[] = str_replace(':', '-',
current($ids));
}
}
if ($view->parent_key)
{
// Remove parent key from query
unset($query[$view->parent_key]);
}
}
if ($found)
{
unset($query[$views[$query['view']]->key],
$query['view']);
if (isset($query['layout']) && $mLayout ===
$query['layout'])
{
unset($query['layout']);
}
}
}
}