Spade
Mini Shell
| Directory:~$ /proc/self/root/home/lmsyaran/www/joomla5/libraries/src/Helper/ |
| [Home] [System Details] [Kill Me] |
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2005 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\CMS\Helper;
use Joomla\CMS\Cache\CacheControllerFactoryInterface;
use Joomla\CMS\Cache\Controller\CallbackController;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Event\Module;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Profiler\Profiler;
use Joomla\Database\ParameterType;
use Joomla\Filesystem\Path;
use Joomla\Registry\Registry;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Module helper class
*
* @since 1.5
*/
abstract class ModuleHelper
{
/**
* Get module by name (real, eg 'Breadcrumbs' or folder, eg
'mod_breadcrumbs')
*
* @param string $name The name of the module
* @param string $title The title of the module, optional
*
* @return \stdClass The Module object
*
* @since 1.5
*/
public static function &getModule($name, $title = null)
{
$result = null;
$modules =& static::load();
$total = \count($modules);
for ($i = 0; $i < $total; $i++) {
// Match the name of the module
if ($modules[$i]->name === $name || $modules[$i]->module
=== $name) {
// Match the title if we're looking for a specific
instance of the module
if (!$title || $modules[$i]->title === $title) {
// Found it
$result = &$modules[$i];
break;
}
}
}
// If we didn't find it, and the name is mod_something, create
a dummy object
if ($result === null && strpos($name, 'mod_') ===
0) {
$result = static::createDummyModule();
$result->module = $name;
}
return $result;
}
/**
* Get modules by position
*
* @param string $position The position of the module
*
* @return array An array of module objects
*
* @since 1.5
*/
public static function &getModules($position)
{
$position = strtolower($position);
$result = [];
$input = Factory::getApplication()->getInput();
$modules = &static::load();
$total = \count($modules);
for ($i = 0; $i < $total; $i++) {
if ($modules[$i]->position === $position) {
$result[] = &$modules[$i];
}
}
// Prepend a dummy module for template preview if no module is
published in the position
if (empty($result) && $input->getBool('tp')
&&
ComponentHelper::getParams('com_templates')->get('template_positions_display'))
{
$dummy = static::createDummyModule();
$dummy->title = $position;
$dummy->position = $position;
$dummy->content = $position;
$dummy->contentRendered = true;
array_unshift($result, $dummy);
}
return $result;
}
/**
* Checks if a module is enabled. A given module will only be returned
* if it meets the following criteria: it is enabled, it is assigned to
* the current menu item or all items, and the user meets the access
level
* requirements.
*
* @param string $module The module name
*
* @return boolean See description for conditions.
*
* @since 1.5
*/
public static function isEnabled($module)
{
$result = static::getModule($module);
return $result !== null && $result->id !== 0;
}
/**
* Render the module.
*
* @param object $module A module object.
* @param array $attribs An array of attributes for the module
(probably from the XML).
*
* @return string The HTML content of the module output.
*
* @since 1.5
*/
public static function renderModule($module, $attribs = [])
{
$app = Factory::getApplication();
// Check that $module is a valid module object
if (!\is_object($module) || !isset($module->module) ||
!isset($module->params)) {
if (JDEBUG) {
Log::addLogger(['text_file' =>
'jmodulehelper.log.php'], Log::ALL, ['modulehelper']);
$app->getLogger()->debug(
__METHOD__ . '() - The $module parameter should be
a module object.',
['category' => 'modulehelper']
);
}
return '';
}
// Get module parameters
$params = new Registry($module->params);
// Render the module content
static::renderRawModule($module, $params, $attribs);
// Return early if only the content is required
if (!empty($attribs['contentOnly'])) {
return $module->content;
}
if (JDEBUG) {
Profiler::getInstance('Application')->mark('beforeRenderModule
' . $module->module . ' (' . $module->title .
')');
}
// Record the scope.
$scope = $app->scope;
// Set scope to component name
$app->scope = $module->module;
$dispatcher = $app->getDispatcher();
// Get the template
$template = $app->getTemplate();
// Check if the current module has a style param to override
template module style
$paramsChromeStyle = $params->get('style');
$basePath = '';
if ($paramsChromeStyle) {
$paramsChromeStyle = explode('-',
$paramsChromeStyle, 2);
$ChromeStyleTemplate = strtolower($paramsChromeStyle[0]);
$attribs['style'] = $paramsChromeStyle[1];
// Only set $basePath if the specified template isn't the
current or system one.
if ($ChromeStyleTemplate !== $template &&
$ChromeStyleTemplate !== 'system') {
$basePath = JPATH_THEMES . '/' .
$ChromeStyleTemplate . '/html/layouts';
}
}
// Make sure a style is set
if (!isset($attribs['style'])) {
$attribs['style'] = 'none';
}
// Dynamically add outline style
if ($app->getInput()->getBool('tp') &&
ComponentHelper::getParams('com_templates')->get('template_positions_display'))
{
$attribs['style'] .= ' outline';
}
$module->style = $attribs['style'];
// If the $module is nulled it will return an empty content,
otherwise it will render the module normally.
$brEvent = $dispatcher->dispatch('onRenderModule', new
Module\BeforeRenderModuleEvent('onRenderModule', [
'subject' => $module,
'attributes' => &$attribs, // @todo: Remove
reference in Joomla 6, see BeforeRenderModuleEvent::__constructor()
]));
// Get final attributes
$attribs = $brEvent->getArgument('attributes',
$attribs);
if (!isset($module->content)) {
return '';
}
// Prevent double modification of the module content by chrome
style
$module = clone $module;
$displayData = [
'module' => $module,
'params' => $params,
'attribs' => $attribs,
];
foreach (explode(' ', $attribs['style']) as
$style) {
$moduleContent = LayoutHelper::render('chromes.' .
$style, $displayData, $basePath);
if ($moduleContent) {
$module->content = $moduleContent;
}
}
// Revert the scope
$app->scope = $scope;
$dispatcher->dispatch('onAfterRenderModule', new
Module\AfterRenderModuleEvent('onAfterRenderModule', [
'subject' => $module,
'attributes' => $attribs,
]));
if (JDEBUG) {
Profiler::getInstance('Application')->mark('afterRenderModule
' . $module->module . ' (' . $module->title .
')');
}
return $module->content;
}
/**
* Render the module content.
*
* @param object $module A module object
* @param Registry $params A module parameters
* @param array $attribs An array of attributes for the module
(probably from the XML).
*
* @return string
*
* @since 4.0.0
*/
public static function renderRawModule($module, Registry $params,
$attribs = [])
{
if (!empty($module->contentRendered)) {
return $module->content;
}
if (JDEBUG) {
Profiler::getInstance('Application')->mark('beforeRenderRawModule
' . $module->module . ' (' . $module->title .
')');
}
$app = Factory::getApplication();
// Record the scope.
$scope = $app->scope;
// Set scope to component name
$app->scope = $module->module;
// Get module path
$module->module = preg_replace('/[^A-Z0-9_\.-]/i',
'', $module->module);
$dispatcher = $app->bootModule($module->module,
$app->getName())->getDispatcher($module, $app);
// Check if we have a dispatcher
if ($dispatcher) {
ob_start();
$dispatcher->dispatch();
$module->content = ob_get_clean();
}
// Add the flag that the module content has been rendered
$module->contentRendered = true;
// Revert the scope
$app->scope = $scope;
if (JDEBUG) {
Profiler::getInstance('Application')->mark('afterRenderRawModule
' . $module->module . ' (' . $module->title .
')');
}
return $module->content;
}
/**
* Get the path to a layout for a module
*
* @param string $module The name of the module
* @param string $layout The name of the module layout. If
alternative layout, in the form template:filename.
*
* @return string The path to the module layout
*
* @since 1.5
*/
public static function getLayoutPath($module, $layout =
'default')
{
$templateObj = Factory::getApplication()->getTemplate(true);
$defaultLayout = $layout;
$template = $templateObj->template;
if (strpos($layout, ':') !== false) {
// Get the template and file name from the string
$temp = explode(':', $layout);
$template = $temp[0] === '_' ? $template :
$temp[0];
$layout = $temp[1];
$defaultLayout = $temp[1] ?: 'default';
}
$dPath = JPATH_BASE . '/modules/' . $module .
'/tmpl/default.php';
try {
// Build the template and base path for the layout
$tPath = Path::check(JPATH_THEMES . '/' . $template .
'/html/' . $module . '/' . $layout . '.php');
$iPath = Path::check(JPATH_THEMES . '/' .
$templateObj->parent . '/html/' . $module . '/' .
$layout . '.php');
$bPath = Path::check(JPATH_BASE . '/modules/' .
$module . '/tmpl/' . $defaultLayout . '.php');
} catch (\Exception $e) {
// On error fallback to the default path
return $dPath;
}
// If the template has a layout override use it
if (is_file($tPath)) {
return $tPath;
}
if (!empty($templateObj->parent) && is_file($iPath)) {
return $iPath;
}
if (is_file($bPath)) {
return $bPath;
}
return $dPath;
}
/**
* Load published modules.
*
* @return array
*
* @since 3.2
*/
protected static function &load()
{
static $modules;
if (isset($modules)) {
return $modules;
}
$dispatcher = Factory::getApplication()->getDispatcher();
$modules = [];
$modules =
$dispatcher->dispatch('onPrepareModuleList', new
Module\PrepareModuleListEvent('onPrepareModuleList', [
'modules' => &$modules, // @todo: Remove
reference in Joomla 6, see PrepareModuleListEvent::__constructor()
]))->getArgument('modules', $modules);
// If the onPrepareModuleList event returns an array of modules,
then ignore the default module list creation
if (!$modules) {
$modules = static::getModuleList();
}
$modules = $dispatcher->dispatch('onAfterModuleList',
new Module\AfterModuleListEvent('onAfterModuleList', [
'modules' => &$modules, // @todo: Remove
reference in Joomla 6, see AfterModuleListEvent::__constructor()
]))->getArgument('modules', $modules);
$modules = static::cleanModuleList($modules);
$modules =
$dispatcher->dispatch('onAfterCleanModuleList', new
Module\AfterCleanModuleListEvent('onAfterCleanModuleList', [
'modules' => &$modules, // @todo: Remove
reference in Joomla 6, see AfterCleanModuleListEvent::__constructor()
]))->getArgument('modules', $modules);
return $modules;
}
/**
* Module list
*
* @return array
*/
public static function getModuleList()
{
$app = Factory::getApplication();
$itemId = $app->getInput()->getInt('Itemid', 0);
$groups = $app->getIdentity()->getAuthorisedViewLevels();
$clientId = (int) $app->getClientId();
// Build a cache ID for the resulting data object
$cacheId = implode(',', $groups) . '.' .
$clientId . '.' . $itemId;
$db = Factory::getDbo();
$query = $db->getQuery(true);
$nowDate = Factory::getDate()->toSql();
$query->select($db->quoteName(['m.id',
'm.title', 'm.module', 'm.position',
'm.content', 'm.showtitle', 'm.params',
'mm.menuid']))
->from($db->quoteName('#__modules',
'm'))
->join(
'LEFT',
$db->quoteName('#__modules_menu',
'mm'),
$db->quoteName('mm.moduleid') . ' =
' . $db->quoteName('m.id')
)
->join(
'LEFT',
$db->quoteName('#__extensions',
'e'),
$db->quoteName('e.element') . ' = '
. $db->quoteName('m.module')
. ' AND ' .
$db->quoteName('e.client_id') . ' = ' .
$db->quoteName('m.client_id')
)
->where(
[
$db->quoteName('m.published') . ' =
1',
$db->quoteName('e.enabled') . ' =
1',
$db->quoteName('m.client_id') . ' =
:clientId',
]
)
->bind(':clientId', $clientId,
ParameterType::INTEGER)
->whereIn($db->quoteName('m.access'), $groups)
->extendWhere(
'AND',
[
$db->quoteName('m.publish_up') . ' IS
NULL',
$db->quoteName('m.publish_up') . '
<= :publishUp',
],
'OR'
)
->bind(':publishUp', $nowDate)
->extendWhere(
'AND',
[
$db->quoteName('m.publish_down') . '
IS NULL',
$db->quoteName('m.publish_down') . '
>= :publishDown',
],
'OR'
)
->bind(':publishDown', $nowDate)
->extendWhere(
'AND',
[
$db->quoteName('mm.menuid') . ' =
:itemId',
$db->quoteName('mm.menuid') . ' <=
0',
],
'OR'
)
->bind(':itemId', $itemId,
ParameterType::INTEGER);
// Filter by language
if ($app->isClient('site') &&
$app->getLanguageFilter() ||
$app->isClient('administrator') &&
static::isAdminMultilang()) {
$language = $app->getLanguage()->getTag();
$query->whereIn($db->quoteName('m.language'),
[$language, '*'], ParameterType::STRING);
$cacheId .= $language . '*';
}
$query->order($db->quoteName(['m.position',
'm.ordering']));
// Set the query
$db->setQuery($query);
try {
/** @var CallbackController $cache */
$cache =
Factory::getContainer()->get(CacheControllerFactoryInterface::class)
->createCacheController('callback',
['defaultgroup' => 'com_modules']);
$modules = $cache->get([$db, 'loadObjectList'],
[], md5($cacheId), false);
} catch (\RuntimeException $e) {
$app->getLogger()->warning(
Text::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD',
$e->getMessage()),
['category' => 'jerror']
);
return [];
}
return $modules;
}
/**
* Clean the module list
*
* @param array $modules Array with module objects
*
* @return array
*/
public static function cleanModuleList($modules)
{
// Apply negative selections and eliminate duplicates
$Itemid =
Factory::getApplication()->getInput()->getInt('Itemid');
$negId = $Itemid ? -(int) $Itemid : false;
$clean = [];
$dupes = [];
foreach ($modules as $i => $module) {
// The module is excluded if there is an explicit prohibition
$negHit = ($negId === (int) $module->menuid);
if (isset($dupes[$module->id])) {
// If this item has been excluded, keep the duplicate flag
set,
// but remove any item from the modules array.
if ($negHit) {
unset($clean[$module->id]);
}
continue;
}
$dupes[$module->id] = true;
// Only accept modules without explicit exclusions.
if ($negHit) {
continue;
}
$module->name = substr($module->module, 4);
$module->style = null;
$module->position = strtolower($module->position);
$clean[$module->id] = $module;
}
unset($dupes);
// Return to simple indexing that matches the query order.
return array_values($clean);
}
/**
* Module cache helper
*
* Caching modes:
* To be set in XML:
* 'static' One cache file for all pages with the same
module parameters
* 'itemid' Changes on itemid change, to be called from
inside the module:
* 'safeuri' Id created from $cacheparams->modeparams
array,
* 'id' Module sets own cache id's
*
* @param object $module Module object
* @param object $moduleparams Module parameters
* @param object $cacheparams Module cache parameters - id or URL
parameters, depending on the module cache mode
*
* @return string
*
* @see InputFilter::clean()
* @since 1.6
*/
public static function moduleCache($module, $moduleparams,
$cacheparams)
{
if (!isset($cacheparams->modeparams)) {
$cacheparams->modeparams = null;
}
if (!isset($cacheparams->cachegroup)) {
$cacheparams->cachegroup = $module->module;
}
if (!isset($cacheparams->cachesuffix)) {
$cacheparams->cachesuffix = '';
}
$user = Factory::getUser();
$app = Factory::getApplication();
/** @var CallbackController $cache */
$cache =
Factory::getContainer()->get(CacheControllerFactoryInterface::class)
->createCacheController('callback',
['defaultgroup' => $cacheparams->cachegroup]);
// Turn cache off for internal callers if parameters are set to off
and for all logged in users
$ownCacheDisabled = $moduleparams->get('owncache') ===
0 || $moduleparams->get('owncache') === '0';
$cacheDisabled = $moduleparams->get('cache') === 0
|| $moduleparams->get('cache') === '0';
if ($ownCacheDisabled || $cacheDisabled ||
$app->get('caching') == 0 || $user->get('id')) {
$cache->setCaching(false);
}
// Module cache is set in seconds, global cache in minutes,
setLifeTime works in minutes
$cache->setLifeTime($moduleparams->get('cache_time',
$app->get('cachetime') * 60) / 60);
$wrkaroundoptions = ['nopathway' => 1,
'nohead' => 0, 'nomodules' => 1,
'modulemode' => 1, 'mergehead' => 1];
$wrkarounds = true;
$view_levels = md5(serialize($user->getAuthorisedViewLevels()));
switch ($cacheparams->cachemode) {
case 'id':
$ret = $cache->get(
[$cacheparams->class, $cacheparams->method],
$cacheparams->methodparams,
$cacheparams->modeparams .
$cacheparams->cachesuffix,
$wrkarounds,
$wrkaroundoptions
);
break;
case 'safeuri':
$safeuri = new \stdClass();
if (\is_array($cacheparams->modeparams)) {
$input = $app->getInput();
$uri = $input->getArray();
$noHtmlFilter = InputFilter::getInstance();
foreach ($cacheparams->modeparams as $key =>
$value) {
// Use int filter for id/catid to clean out spamy
slugs
if (isset($uri[$key])) {
$safeuri->$key =
$noHtmlFilter->clean($uri[$key], $value);
}
}
}
$secureid = md5(serialize([$safeuri,
$cacheparams->method, $moduleparams]));
$ret = $cache->get(
[$cacheparams->class, $cacheparams->method],
$cacheparams->methodparams,
$module->id . $view_levels . $secureid .
$cacheparams->cachesuffix,
$wrkarounds,
$wrkaroundoptions
);
break;
case 'static':
$ret = $cache->get(
[$cacheparams->class, $cacheparams->method],
$cacheparams->methodparams,
$module->module .
md5(serialize($cacheparams->methodparams)) .
$cacheparams->cachesuffix,
$wrkarounds,
$wrkaroundoptions
);
break;
case 'itemid':
default:
$ret = $cache->get(
[$cacheparams->class, $cacheparams->method],
$cacheparams->methodparams,
$module->id . $view_levels .
$app->getInput()->getInt('Itemid', null) .
$cacheparams->cachesuffix,
$wrkarounds,
$wrkaroundoptions
);
break;
}
return $ret;
}
/**
* Method to determine if filtering by language is enabled in back-end
for modules.
*
* @return boolean True if enabled; false otherwise.
*
* @since 3.8.0
*/
public static function isAdminMultilang()
{
static $enabled = false;
if (\count(LanguageHelper::getInstalledLanguages(1)) > 1) {
$enabled = (bool)
ComponentHelper::getParams('com_modules')->get('adminlangfilter',
0);
}
return $enabled;
}
/**
* Get module by id
*
* @param string $id The id of the module
*
* @return \stdClass The Module object
*
* @since 3.9.0
*/
public static function &getModuleById($id)
{
$modules =& static::load();
$total = \count($modules);
for ($i = 0; $i < $total; $i++) {
// Match the id of the module
if ((string) $modules[$i]->id === $id) {
// Found it
return $modules[$i];
}
}
// If we didn't find it, create a dummy object
$result = static::createDummyModule();
return $result;
}
/**
* Method to create a dummy module.
*
* @return \stdClass The Module object
*
* @since 4.0.0
*/
protected static function createDummyModule(): \stdClass
{
$module = new \stdClass();
$module->id = 0;
$module->title = '';
$module->module = '';
$module->position = '';
$module->content = '';
$module->showtitle = 0;
$module->control = '';
$module->params = '';
return $module;
}
}