Spade
Mini Shell
| Directory:~$ /home/lmsyaran/public_html/joomla4/ |
| [Home] [System Details] [Kill Me] |
AuthenticationHelper.php000064400000002424151157061210011375
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\Helper;
defined('JPATH_PLATFORM') or die;
/**
* Authentication helper class
*
* @since 3.6.3
*/
abstract class AuthenticationHelper
{
/**
* Get the Two Factor Authentication Methods available.
*
* @return array Two factor authentication methods.
*
* @since 3.6.3
*/
public static function getTwoFactorMethods()
{
// Get all the Two Factor Authentication plugins.
\JPluginHelper::importPlugin('twofactorauth');
// Trigger onUserTwofactorIdentify event and return the two factor
enabled plugins.
$identities =
\JEventDispatcher::getInstance()->trigger('onUserTwofactorIdentify',
array());
// Generate array with two factor auth methods.
$options = array(
\JHtml::_('select.option', 'none',
\JText::_('JGLOBAL_OTPMETHOD_NONE'), 'value',
'text'),
);
if (!empty($identities))
{
foreach ($identities as $identity)
{
if (!is_object($identity))
{
continue;
}
$options[] = \JHtml::_('select.option', $identity->method,
$identity->title, 'value', 'text');
}
}
return $options;
}
}
CMSHelper.php000064400000006201151157061210007035 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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\TableInterface;
use Joomla\Registry\Registry;
/**
* Base Helper class.
*
* @since 3.2
*/
class CMSHelper
{
/**
* Gets the current language
*
* @param boolean $detectBrowser Flag indicating whether to use the
browser language as a fallback.
*
* @return string The language string
*
* @since 3.2
*/
public function getCurrentLanguage($detectBrowser = true)
{
$app = Factory::getApplication();
$langCode = null;
// Get the languagefilter parameters
if (Multilanguage::isEnabled())
{
$plugin = PluginHelper::getPlugin('system',
'languagefilter');
$pluginParams = new Registry($plugin->params);
if ((int) $pluginParams->get('lang_cookie', 1) === 1)
{
$langCode =
$app->input->cookie->getString(ApplicationHelper::getHash('language'));
}
else
{
$langCode =
Factory::getSession()->get('plg_system_languagefilter.language');
}
}
// No cookie - let's try to detect browser language or use site
default
if (!$langCode)
{
if ($detectBrowser)
{
$langCode = LanguageHelper::detectLanguage();
}
else
{
$langCode =
ComponentHelper::getParams('com_languages')->get('site',
'en-GB');
}
}
return $langCode;
}
/**
* Gets the associated language ID
*
* @param string $langCode The language code to look up
*
* @return integer The language ID
*
* @since 3.2
*/
public function getLanguageId($langCode)
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('lang_id')
->from('#__languages')
->where($db->quoteName('lang_code') . ' = ' .
$db->quote($langCode));
$db->setQuery($query);
return $db->loadResult();
}
/**
* Gets a row of data from a table
*
* @param TableInterface $table Table instance for a row.
*
* @return array Associative array of all columns and values for a row
in a table.
*
* @since 3.2
*/
public function getRowData(TableInterface $table)
{
$fields = $table->getFields();
$data = array();
foreach ($fields as &$field)
{
$columnName = $field->Field;
$value = $table->$columnName;
$data[$columnName] = $value;
}
return $data;
}
/**
* Method to get an object containing all of the table columns and values.
*
* @param TableInterface $table Table object.
*
* @return \stdClass Contains all of the columns and values.
*
* @since 3.2
*/
public function getDataObject(TableInterface $table)
{
$fields = $table->getFields();
$dataObject = new \stdClass;
foreach ($fields as $field)
{
$fieldName = $field->Field;
$dataObject->$fieldName = $table->get($fieldName);
}
return $dataObject;
}
}
ContentHelper.php000064400000020556151157061210010036 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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Access\Access;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Table\Table;
use Joomla\Registry\Registry;
/**
* Helper for standard content style extensions.
* This class mainly simplifies static helper methods often repeated in
individual components
*
* @since 3.1
*/
class ContentHelper
{
/**
* Configure the Linkbar. Must be implemented by each extension.
*
* @param string $vName The name of the active view.
*
* @return void
*
* @since 3.1
*/
public static function addSubmenu($vName)
{
}
/**
* Adds Count relations for Category and Tag Managers
*
* @param stdClass[] &$items The category or tag objects
* @param stdClass $config Configuration object allowing to use a
custom relations table
*
* @return stdClass[]
*
* @since 3.9.1
*/
public static function countRelations(&$items, $config)
{
$db = Factory::getDbo();
// Allow custom state / condition values and custom column names to
support custom components
$counter_names = isset($config->counter_names) ?
$config->counter_names : array(
'-2' => 'count_trashed',
'0' => 'count_unpublished',
'1' => 'count_published',
'2' => 'count_archived',
);
// Index category objects by their ID
$records = array();
foreach ($items as $item)
{
$records[(int) $item->id] = $item;
}
// The relation query does not return a value for cases without relations
of a particular state / condition, set zero as default
foreach ($items as $item)
{
foreach ($counter_names as $n)
{
$item->{$n} = 0;
}
}
// Table alias for related data table below will be 'c', and
state / condition column is inside related data table
$related_tbl = $db->quoteName('#__' .
$config->related_tbl, 'c');
$state_col = $db->quoteName('c.' . $config->state_col);
// Supported cases
switch ($config->relation_type)
{
case 'tag_assigments':
$recid_col = $db->quoteName('ct.' .
$config->group_col);
$query = $db->getQuery(true)
->from($db->quoteName('#__contentitem_tag_map',
'ct'))
->join('INNER', $related_tbl . ' ON ' .
$db->quoteName('ct.content_item_id') . ' = ' .
$db->quoteName('c.id') . ' AND ' .
$db->quoteName('ct.type_alias') . ' = ' .
$db->quote($config->extension)
);
break;
case 'category_or_group':
$recid_col = $db->quoteName('c.' . $config->group_col);
$query = $db->getQuery(true)
->from($related_tbl);
break;
default:
return $items;
}
/**
* Get relation counts for all category objects with single query
* NOTE: 'state IN', allows counting specific states /
conditions only, also prevents warnings with custom states / conditions, do
not remove
*/
$query
->select($recid_col . ' AS catid, ' . $state_col . '
AS state, COUNT(*) AS count')
->where($recid_col . ' IN (' . implode(',',
array_keys($records)) . ')')
->where($state_col . ' IN (' . implode(',',
array_keys($counter_names)) . ')')
->group($recid_col . ', ' . $state_col);
$relationsAll = $db->setQuery($query)->loadObjectList();
// Loop through the DB data overwritting the above zeros with the found
count
foreach ($relationsAll as $relation)
{
// Sanity check in case someone removes the state IN above ... and some
views may start throwing warnings
if (isset($counter_names[$relation->state]))
{
$id = (int) $relation->catid;
$cn = $counter_names[$relation->state];
$records[$id]->{$cn} = $relation->count;
}
}
return $items;
}
/**
* Gets a list of the actions that can be performed.
*
* @param integer $categoryId The category ID.
* @param integer $id The item ID.
* @param string $assetName The asset name
*
* @return \JObject
*
* @since 3.1
* @deprecated 3.2 Use ContentHelper::getActions() instead
*/
public static function _getActions($categoryId = 0, $id = 0, $assetName =
'')
{
// Log usage of deprecated function
Log::add(__METHOD__ . '() is deprecated, use
ContentHelper::getActions() with new arguments order instead.',
Log::WARNING, 'deprecated');
// Reverted a change for version 2.5.6
$user = Factory::getUser();
$result = new \JObject;
$path = JPATH_ADMINISTRATOR . '/components/' . $assetName .
'/access.xml';
if (empty($id) && empty($categoryId))
{
$section = 'component';
}
elseif (empty($id))
{
$section = 'category';
$assetName .= '.category.' . (int) $categoryId;
}
else
{
// Used only in com_content
$section = 'article';
$assetName .= '.article.' . (int) $id;
}
$actions = Access::getActionsFromFile($path,
"/access/section[@name='" . $section .
"']/");
foreach ($actions as $action)
{
$result->set($action->name, $user->authorise($action->name,
$assetName));
}
return $result;
}
/**
* Gets a list of the actions that can be performed.
*
* @param string $component The component name.
* @param string $section The access section name.
* @param integer $id The item ID.
*
* @return \JObject
*
* @since 3.2
*/
public static function getActions($component = '', $section =
'', $id = 0)
{
// Check for deprecated arguments order
if (is_int($component) || $component === null)
{
$result = self::_getActions($component, $section, $id);
return $result;
}
$assetName = $component;
if ($section && $id)
{
$assetName .= '.' . $section . '.' . (int) $id;
}
$result = new \JObject;
$user = Factory::getUser();
$actions = Access::getActionsFromFile(
JPATH_ADMINISTRATOR . '/components/' . $component .
'/access.xml',
'/access/section[@name="component"]/'
);
if ($actions === false)
{
Log::add(
\JText::sprintf('JLIB_ERROR_COMPONENTS_ACL_CONFIGURATION_FILE_MISSING_OR_IMPROPERLY_STRUCTURED',
$component), Log::ERROR, 'jerror'
);
return $result;
}
foreach ($actions as $action)
{
$result->set($action->name, $user->authorise($action->name,
$assetName));
}
return $result;
}
/**
* Gets the current language
*
* @param boolean $detectBrowser Flag indicating whether to use the
browser language as a fallback.
*
* @return string The language string
*
* @since 3.1
* @note CmsHelper::getCurrentLanguage is the preferred method
*/
public static function getCurrentLanguage($detectBrowser = true)
{
$app = Factory::getApplication();
$langCode = null;
// Get the languagefilter parameters
if (Multilanguage::isEnabled())
{
$plugin = PluginHelper::getPlugin('system',
'languagefilter');
$pluginParams = new Registry($plugin->params);
if ((int) $pluginParams->get('lang_cookie', 1) === 1)
{
$langCode =
$app->input->cookie->getString(ApplicationHelper::getHash('language'));
}
else
{
$langCode =
Factory::getSession()->get('plg_system_languagefilter.language');
}
}
// No cookie - let's try to detect browser language or use site
default
if (!$langCode)
{
if ($detectBrowser)
{
$langCode = LanguageHelper::detectLanguage();
}
else
{
$langCode =
ComponentHelper::getParams('com_languages')->get('site',
'en-GB');
}
}
return $langCode;
}
/**
* Gets the associated language ID
*
* @param string $langCode The language code to look up
*
* @return integer The language ID
*
* @since 3.1
* @note CmsHelper::getLanguage() is the preferred method.
*/
public static function getLanguageId($langCode)
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select('lang_id')
->from('#__languages')
->where($db->quoteName('lang_code') . ' = ' .
$db->quote($langCode));
$db->setQuery($query);
return $db->loadResult();
}
/**
* Gets a row of data from a table
*
* @param Table $table Table instance for a row.
*
* @return array Associative array of all columns and values for a row
in a table.
*
* @since 3.1
*/
public function getRowData(Table $table)
{
$data = new CMSHelper;
return $data->getRowData($table);
}
}
ContentHistoryHelper.php000064400000011105151157061210011406
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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Table\Table;
/**
* Versions helper class, provides methods to perform various tasks
relevant
* versioning of content.
*
* @since 3.2
*/
class ContentHistoryHelper extends CMSHelper
{
/**
* Alias for storing type in versions table
*
* @var string
* @since 3.2
*/
public $typeAlias = null;
/**
* Constructor
*
* @param string $typeAlias The type of content to be versioned (for
example, 'com_content.article').
*
* @since 3.2
*/
public function __construct($typeAlias = null)
{
$this->typeAlias = $typeAlias;
}
/**
* Method to delete the history for an item.
*
* @param Table $table Table object being versioned
*
* @return boolean true on success, otherwise false.
*
* @since 3.2
*/
public function deleteHistory($table)
{
$key = $table->getKeyName();
$id = $table->$key;
$typeTable = Table::getInstance('Contenttype',
'JTable');
$typeId = $typeTable->getTypeId($this->typeAlias);
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$query->delete($db->quoteName('#__ucm_history'))
->where($db->quoteName('ucm_item_id') . ' = '
. (int) $id)
->where($db->quoteName('ucm_type_id') . ' = '
. (int) $typeId);
$db->setQuery($query);
return $db->execute();
}
/**
* Method to get a list of available versions of this item.
*
* @param integer $typeId Type id for this component item.
* @param mixed $id Primary key of row to get history for.
*
* @return mixed The return value or null if the query failed.
*
* @since 3.2
*/
public function getHistory($typeId, $id)
{
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName('h.version_note') .
',' . $db->quoteName('h.save_date') . ','
. $db->quoteName('u.name'))
->from($db->quoteName('#__ucm_history') . ' AS h
')
->leftJoin($db->quoteName('#__users') . ' AS u ON
' . $db->quoteName('u.id') . ' = ' .
$db->quoteName('h.editor_user_id'))
->where($db->quoteName('ucm_item_id') . ' = '
. $db->quote($id))
->where($db->quoteName('ucm_type_id') . ' = '
. (int) $typeId)
->order($db->quoteName('save_date') . ' DESC
');
$db->setQuery($query);
return $db->loadObjectList();
}
/**
* Method to save a version snapshot to the content history table.
*
* @param Table $table Table object being versioned
*
* @return boolean True on success, otherwise false.
*
* @since 3.2
*/
public function store($table)
{
$dataObject = $this->getDataObject($table);
$historyTable = Table::getInstance('Contenthistory',
'JTable');
$typeTable = Table::getInstance('Contenttype',
'JTable');
$typeTable->load(array('type_alias' =>
$this->typeAlias));
$historyTable->set('ucm_type_id', $typeTable->type_id);
$key = $table->getKeyName();
$historyTable->set('ucm_item_id', $table->$key);
// Don't store unless we have a non-zero item id
if (!$historyTable->ucm_item_id)
{
return true;
}
$historyTable->set('version_data',
json_encode($dataObject));
$input = \JFactory::getApplication()->input;
$data = $input->get('jform', array(), 'array');
$versionName = false;
if (isset($data['version_note']))
{
$versionName =
\JFilterInput::getInstance()->clean($data['version_note'],
'string');
$historyTable->set('version_note', $versionName);
}
// Don't save if hash already exists and same version note
$historyTable->set('sha1_hash',
$historyTable->getSha1($dataObject, $typeTable));
if ($historyRow = $historyTable->getHashMatch())
{
if (!$versionName || ($historyRow->version_note === $versionName))
{
return true;
}
else
{
// Update existing row to set version note
$historyTable->set('version_id',
$historyRow->version_id);
}
}
$result = $historyTable->store();
// Load history_limit config from extension.
$aliasParts = explode('.', $this->typeAlias);
$context = isset($aliasParts[1]) ? $aliasParts[1] : '';
$maxVersionsContext =
ComponentHelper::getParams($aliasParts[0])->get('history_limit'
. '_' . $context, 0);
if ($maxVersionsContext)
{
$historyTable->deleteOldVersions($maxVersionsContext);
}
elseif ($maxVersions =
ComponentHelper::getParams($aliasParts[0])->get('history_limit',
0))
{
$historyTable->deleteOldVersions($maxVersions);
}
return $result;
}
}
LibraryHelper.php000064400000011171151157061210010021 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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\Registry\Registry;
/**
* Library helper class
*
* @since 3.2
*/
class LibraryHelper
{
/**
* The component list cache
*
* @var array
* @since 3.2
*/
protected static $libraries = array();
/**
* Get the library information.
*
* @param string $element Element of the library in the extensions
table.
* @param boolean $strict If set and the library does not exist, the
enabled attribute will be set to false.
*
* @return \stdClass An object with the library's information.
*
* @since 3.2
*/
public static function getLibrary($element, $strict = false)
{
// Is already cached?
if (isset(static::$libraries[$element]) || static::loadLibrary($element))
{
$result = static::$libraries[$element];
// Convert the params to an object.
if (is_string($result->params))
{
$result->params = new Registry($result->params);
}
}
else
{
$result = new \stdClass;
$result->enabled = $strict ? false : true;
$result->params = new Registry;
}
return $result;
}
/**
* Checks if a library is enabled
*
* @param string $element Element of the library in the extensions
table.
*
* @return boolean
*
* @since 3.2
*/
public static function isEnabled($element)
{
return static::getLibrary($element, true)->enabled;
}
/**
* Gets the parameter object for the library
*
* @param string $element Element of the library in the extensions
table.
* @param boolean $strict If set and the library does not exist,
false will be returned
*
* @return Registry A Registry object.
*
* @see Registry
* @since 3.2
*/
public static function getParams($element, $strict = false)
{
return static::getLibrary($element, $strict)->params;
}
/**
* Save the parameters object for the library
*
* @param string $element Element of the library in the extensions
table.
* @param Registry $params Params to save
*
* @return Registry A Registry object.
*
* @see Registry
* @since 3.2
*/
public static function saveParams($element, $params)
{
if (static::isEnabled($element))
{
// Save params in DB
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->update($db->quoteName('#__extensions'))
->set($db->quoteName('params') . ' = ' .
$db->quote($params->toString()))
->where($db->quoteName('type') . ' = ' .
$db->quote('library'))
->where($db->quoteName('element') . ' = ' .
$db->quote($element));
$db->setQuery($query);
$result = $db->execute();
// Update params in libraries cache
if ($result && isset(static::$libraries[$element]))
{
static::$libraries[$element]->params = $params;
}
return $result;
}
return false;
}
/**
* Load the installed library into the libraries property.
*
* @param string $element The element value for the extension
*
* @return boolean True on success
*
* @since 3.2
* @deprecated 4.0 Use LibraryHelper::loadLibrary() instead
*/
protected static function _load($element)
{
return static::loadLibrary($element);
}
/**
* Load the installed library into the libraries property.
*
* @param string $element The element value for the extension
*
* @return boolean True on success
*
* @since 3.7.0
*/
protected static function loadLibrary($element)
{
$loader = function($element)
{
$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('library'))
->where($db->quoteName('element') . ' = ' .
$db->quote($element));
$db->setQuery($query);
return $db->loadObject();
};
/** @var \JCacheControllerCallback $cache */
$cache = \JFactory::getCache('_system', 'callback');
try
{
static::$libraries[$element] = $cache->get($loader, array($element),
__METHOD__ . $element);
}
catch (\JCacheException $e)
{
static::$libraries[$element] = $loader($element);
}
if (empty(static::$libraries[$element]))
{
// Fatal error.
$error =
\JText::_('JLIB_APPLICATION_ERROR_LIBRARY_NOT_FOUND');
\JLog::add(\JText::sprintf('JLIB_APPLICATION_ERROR_LIBRARY_NOT_LOADING',
$element, $error), \JLog::WARNING, 'jerror');
return false;
}
return true;
}
}
MediaHelper.php000064400000025510151157061210007436 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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
/**
* Media helper class
*
* @since 3.2
*/
class MediaHelper
{
/**
* Checks if the file is an image
*
* @param string $fileName The filename
*
* @return boolean
*
* @since 3.2
*/
public function isImage($fileName)
{
static $imageTypes = 'xcf|odg|gif|jpg|png|bmp';
return preg_match("/\.(?:$imageTypes)$/i", $fileName);
}
/**
* Gets the file extension for purposed of using an icon
*
* @param string $fileName The filename
*
* @return string File extension to determine icon
*
* @since 3.2
*/
public static function getTypeIcon($fileName)
{
return strtolower(substr($fileName, strrpos($fileName, '.') +
1));
}
/**
* Get the Mime type
*
* @param string $file The link to the file to be checked
* @param boolean $isImage True if the passed file is an image else
false
*
* @return mixed the mime type detected false on error
*
* @since 3.7.2
*/
private function getMimeType($file, $isImage = false)
{
// If we can't detect anything mime is false
$mime = false;
try
{
if ($isImage && function_exists('exif_imagetype'))
{
$mime = image_type_to_mime_type(exif_imagetype($file));
}
elseif ($isImage && function_exists('getimagesize'))
{
$imagesize = getimagesize($file);
$mime = isset($imagesize['mime']) ?
$imagesize['mime'] : false;
}
elseif (function_exists('mime_content_type'))
{
// We have mime magic.
$mime = mime_content_type($file);
}
elseif (function_exists('finfo_open'))
{
// We have fileinfo
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file);
finfo_close($finfo);
}
}
catch (\Exception $e)
{
// If we have any kind of error here => false;
return false;
}
// If we can't detect the mime try it again
if ($mime === 'application/octet-stream' && $isImage
=== true)
{
$mime = $this->getMimeType($file, false);
}
// We have a mime here
return $mime;
}
/**
* Checks the Mime type
*
* @param string $mime The mime to be checked
* @param string $component The optional name for the component
storing the parameters
*
* @return boolean true if mime type checking is disabled or it passes
the checks else false
*
* @since 3.7
*/
private function checkMimeType($mime, $component = 'com_media')
{
$params = ComponentHelper::getParams($component);
if ($params->get('check_mime', 1))
{
// Get the mime type configuration
$allowedMime = array_map('trim', explode(',',
$params->get('upload_mime')));
// Mime should be available and in the whitelist
return !empty($mime) && in_array($mime, $allowedMime);
}
// We don't check mime at all or it passes the checks
return true;
}
/**
* Checks if the file can be uploaded
*
* @param array $file File information
* @param string $component The option name for the component storing
the parameters
*
* @return boolean
*
* @since 3.2
*/
public function canUpload($file, $component = 'com_media')
{
$app = \JFactory::getApplication();
$params = ComponentHelper::getParams($component);
if (empty($file['name']))
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_UPLOAD_INPUT'),
'error');
return false;
}
jimport('joomla.filesystem.file');
if (str_replace(' ', '', $file['name']) !==
$file['name'] || $file['name'] !==
\JFile::makeSafe($file['name']))
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILENAME'),
'error');
return false;
}
$filetypes = explode('.', $file['name']);
if (count($filetypes) < 2)
{
// There seems to be no extension
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETYPE'),
'error');
return false;
}
array_shift($filetypes);
// Media file names should never have executable extensions buried in
them.
$executable = array(
'php', 'js', 'exe', 'phtml',
'java', 'perl', 'py', 'asp',
'dll', 'go', 'ade', 'adp',
'bat', 'chm', 'cmd', 'com',
'cpl', 'hta', 'ins', 'isp',
'jse', 'lib', 'mde', 'msc',
'msp', 'mst', 'pif', 'scr',
'sct', 'shb', 'sys', 'vb',
'vbe', 'vbs', 'vxd', 'wsc',
'wsf', 'wsh',
);
$check = array_intersect($filetypes, $executable);
if (!empty($check))
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETYPE'),
'error');
return false;
}
$filetype = array_pop($filetypes);
$allowable = array_map('trim', explode(',',
$params->get('upload_extensions')));
$ignored = array_map('trim', explode(',',
$params->get('ignore_extensions')));
if ($filetype == '' || $filetype == false ||
(!in_array($filetype, $allowable) && !in_array($filetype,
$ignored)))
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETYPE'),
'error');
return false;
}
$maxSize = (int) ($params->get('upload_maxsize', 0) * 1024 *
1024);
if ($maxSize > 0 && (int) $file['size'] >
$maxSize)
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETOOLARGE'),
'error');
return false;
}
if ($params->get('restrict_uploads', 1))
{
$images = array_map('trim', explode(',',
$params->get('image_extensions')));
if (in_array($filetype, $images))
{
// If tmp_name is empty, then the file was bigger than the PHP limit
if (!empty($file['tmp_name']))
{
// Get the mime type this is an image file
$mime = $this->getMimeType($file['tmp_name'], true);
// Did we get anything useful?
if ($mime != false)
{
$result = $this->checkMimeType($mime, $component);
// If the mime type is not allowed we don't upload it and show
the mime code error to the user
if ($result === false)
{
$app->enqueueMessage(\JText::sprintf('JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE',
$mime), 'error');
return false;
}
}
// We can't detect the mime type so it looks like an invalid
image
else
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNINVALID_IMG'),
'error');
return false;
}
}
else
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNFILETOOLARGE'),
'error');
return false;
}
}
elseif (!in_array($filetype, $ignored))
{
// Get the mime type this is not an image file
$mime = $this->getMimeType($file['tmp_name'], false);
// Did we get anything useful?
if ($mime != false)
{
$result = $this->checkMimeType($mime, $component);
// If the mime type is not allowed we don't upload it and show
the mime code error to the user
if ($result === false)
{
$app->enqueueMessage(\JText::sprintf('JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE',
$mime), 'error');
return false;
}
}
// We can't detect the mime type so it looks like an invalid file
else
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNINVALID_MIME'),
'error');
return false;
}
if (!\JFactory::getUser()->authorise('core.manage',
$component))
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNNOTADMIN'),
'error');
return false;
}
}
}
$xss_check = file_get_contents($file['tmp_name'], false, null,
-1, 256);
$html_tags = array(
'abbr', 'acronym', 'address',
'applet', 'area', 'audioscope',
'base', 'basefont', 'bdo',
'bgsound', 'big', 'blackface',
'blink',
'blockquote', 'body', 'bq',
'br', 'button', 'caption',
'center', 'cite', 'code', 'col',
'colgroup', 'comment', 'custom',
'dd', 'del',
'dfn', 'dir', 'div', 'dl',
'dt', 'em', 'embed', 'fieldset',
'fn', 'font', 'form', 'frame',
'frameset', 'h1', 'h2', 'h3',
'h4', 'h5', 'h6',
'head', 'hr', 'html', 'iframe',
'ilayer', 'img', 'input', 'ins',
'isindex', 'keygen', 'kbd',
'label', 'layer', 'legend', 'li',
'limittext',
'link', 'listing', 'map',
'marquee', 'menu', 'meta',
'multicol', 'nobr', 'noembed',
'noframes', 'noscript', 'nosmartquotes',
'object',
'ol', 'optgroup', 'option',
'param', 'plaintext', 'pre', 'rt',
'ruby', 's', 'samp', 'script',
'select', 'server', 'shadow',
'sidebar',
'small', 'spacer', 'span',
'strike', 'strong', 'style', 'sub',
'sup', 'table', 'tbody', 'td',
'textarea', 'tfoot', 'th', 'thead',
'title',
'tr', 'tt', 'ul', 'var',
'wbr', 'xml', 'xmp', '!DOCTYPE',
'!--',
);
foreach ($html_tags as $tag)
{
// A tag is '<tagname ', so we need to add < and a space
or '<tagname>'
if (stripos($xss_check, '<' . $tag . ' ') !==
false || stripos($xss_check, '<' . $tag . '>')
!== false)
{
$app->enqueueMessage(\JText::_('JLIB_MEDIA_ERROR_WARNIEXSS'),
'error');
return false;
}
}
return true;
}
/**
* Calculate the size of a resized image
*
* @param integer $width Image width
* @param integer $height Image height
* @param integer $target Target size
*
* @return array The new width and height
*
* @since 3.2
*/
public static function imageResize($width, $height, $target)
{
/*
* Takes the larger size of the width and height and applies the
* formula accordingly. This is so this script will work
* dynamically with any size image
*/
if ($width > $height)
{
$percentage = ($target / $width);
}
else
{
$percentage = ($target / $height);
}
// Gets the new value and applies the percentage, then rounds the value
$width = round($width * $percentage);
$height = round($height * $percentage);
return array($width, $height);
}
/**
* Counts the files and directories in a directory that are not php or
html files.
*
* @param string $dir Directory name
*
* @return array The number of media files and directories in the given
directory
*
* @since 3.2
*/
public function countFiles($dir)
{
$total_file = 0;
$total_dir = 0;
if (is_dir($dir))
{
$d = dir($dir);
while (($entry = $d->read()) !== false)
{
if ($entry[0] !== '.' && strpos($entry,
'.html') === false && strpos($entry, '.php')
=== false && is_file($dir . DIRECTORY_SEPARATOR . $entry))
{
$total_file++;
}
if ($entry[0] !== '.' && is_dir($dir .
DIRECTORY_SEPARATOR . $entry))
{
$total_dir++;
}
}
$d->close();
}
return array($total_file, $total_dir);
}
/**
* Small helper function that properly converts any
* configuration options to their byte representation.
*
* @param string|integer $val The value to be converted to bytes.
*
* @return integer The calculated bytes value from the input.
*
* @since 3.3
*/
public function toBytes($val)
{
switch ($val[strlen($val) - 1])
{
case 'M':
case 'm':
return (int) $val * 1048576;
case 'K':
case 'k':
return (int) $val * 1024;
case 'G':
case 'g':
return (int) $val * 1073741824;
default:
return $val;
}
}
}
ModuleHelper.php000064400000042327151157061210007651 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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\Registry\Registry;
/**
* 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 = new \stdClass;
$result->id = 0;
$result->title = '';
$result->module = $name;
$result->position = '';
$result->content = '';
$result->showtitle = 0;
$result->control = '';
$result->params = '';
}
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 = array();
$input = \JFactory::getApplication()->input;
$modules =& static::load();
$total = count($modules);
for ($i = 0; $i < $total; $i++)
{
if ($modules[$i]->position === $position)
{
$result[] = &$modules[$i];
}
}
if (count($result) === 0)
{
if ($input->getBool('tp') &&
ComponentHelper::getParams('com_templates')->get('template_positions_display'))
{
$result[0] = static::getModule('mod_' . $position);
$result[0]->title = $position;
$result[0]->position = $position;
}
}
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 = array())
{
static $chrome;
// Check that $module is a valid module object
if (!is_object($module) || !isset($module->module) ||
!isset($module->params))
{
if (JDEBUG)
{
\JLog::addLogger(array('text_file' =>
'jmodulehelper.log.php'), \JLog::ALL,
array('modulehelper'));
\JLog::add('ModuleHelper::renderModule($module) expects a module
object', \JLog::DEBUG, 'modulehelper');
}
return;
}
if (JDEBUG)
{
\JProfiler::getInstance('Application')->mark('beforeRenderModule
' . $module->module . ' (' . $module->title .
')');
}
$app = \JFactory::getApplication();
// Record the scope.
$scope = $app->scope;
// Set scope to component name
$app->scope = $module->module;
// Get module parameters
$params = new Registry($module->params);
// Get the template
$template = $app->getTemplate();
// Get module path
$module->module = preg_replace('/[^A-Z0-9_\.-]/i',
'', $module->module);
$path = JPATH_BASE . '/modules/' . $module->module .
'/' . $module->module . '.php';
// Load the module
if (file_exists($path))
{
$lang = \JFactory::getLanguage();
$coreLanguageDirectory = JPATH_BASE;
$extensionLanguageDirectory = dirname($path);
$langPaths = $lang->getPaths();
// Only load the module's language file if it hasn't been
already
if (!$langPaths || (!isset($langPaths[$coreLanguageDirectory])
&& !isset($langPaths[$extensionLanguageDirectory])))
{
// 1.5 or Core then 1.6 3PD
$lang->load($module->module, $coreLanguageDirectory, null, false,
true) ||
$lang->load($module->module, $extensionLanguageDirectory, null,
false, true);
}
$content = '';
ob_start();
include $path;
$module->content = ob_get_contents() . $content;
ob_end_clean();
}
// Load the module chrome functions
if (!$chrome)
{
$chrome = array();
}
include_once JPATH_THEMES . '/system/html/modules.php';
$chromePath = JPATH_THEMES . '/' . $template .
'/html/modules.php';
if (!isset($chrome[$chromePath]))
{
if (file_exists($chromePath))
{
include_once $chromePath;
}
$chrome[$chromePath] = true;
}
// Check if the current module has a style param to override template
module style
$paramsChromeStyle = $params->get('style');
if ($paramsChromeStyle)
{
$attribs['style'] = preg_replace('/^(system|' .
$template . ')\-/i', '', $paramsChromeStyle);
}
// Make sure a style is set
if (!isset($attribs['style']))
{
$attribs['style'] = 'none';
}
// Dynamically add outline style
if ($app->input->getBool('tp') &&
ComponentHelper::getParams('com_templates')->get('template_positions_display'))
{
$attribs['style'] .= ' outline';
}
// If the $module is nulled it will return an empty content, otherwise it
will render the module normally.
$app->triggerEvent('onRenderModule', array(&$module,
&$attribs));
if ($module === null || !isset($module->content))
{
return '';
}
foreach (explode(' ', $attribs['style']) as $style)
{
$chromeMethod = 'modChrome_' . $style;
// Apply chrome and render module
if (function_exists($chromeMethod))
{
$module->style = $attribs['style'];
ob_start();
$chromeMethod($module, $params, $attribs);
$module->content = ob_get_contents();
ob_end_clean();
}
}
// Revert the scope
$app->scope = $scope;
$app->triggerEvent('onAfterRenderModule',
array(&$module, &$attribs));
if (JDEBUG)
{
\JProfiler::getInstance('Application')->mark('afterRenderModule
' . $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')
{
$template = \JFactory::getApplication()->getTemplate();
$defaultLayout = $layout;
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';
}
// Build the template and base path for the layout
$tPath = JPATH_THEMES . '/' . $template . '/html/' .
$module . '/' . $layout . '.php';
$bPath = JPATH_BASE . '/modules/' . $module .
'/tmpl/' . $defaultLayout . '.php';
$dPath = JPATH_BASE . '/modules/' . $module .
'/tmpl/default.php';
// If the template has a layout override use it
if (file_exists($tPath))
{
return $tPath;
}
if (file_exists($bPath))
{
return $bPath;
}
return $dPath;
}
/**
* Load published modules.
*
* @return array
*
* @since 1.5
* @deprecated 4.0 Use ModuleHelper::load() instead
*/
protected static function &_load()
{
return static::load();
}
/**
* Load published modules.
*
* @return array
*
* @since 3.2
*/
protected static function &load()
{
static $modules;
if (isset($modules))
{
return $modules;
}
$app = \JFactory::getApplication();
$modules = null;
$app->triggerEvent('onPrepareModuleList',
array(&$modules));
// If the onPrepareModuleList event returns an array of modules, then
ignore the default module list creation
if (!is_array($modules))
{
$modules = static::getModuleList();
}
$app->triggerEvent('onAfterModuleList',
array(&$modules));
$modules = static::cleanModuleList($modules);
$app->triggerEvent('onAfterCleanModuleList',
array(&$modules));
return $modules;
}
/**
* Module list
*
* @return array
*/
public static function getModuleList()
{
$app = \JFactory::getApplication();
$Itemid = $app->input->getInt('Itemid', 0);
$groups = implode(',',
\JFactory::getUser()->getAuthorisedViewLevels());
$lang = \JFactory::getLanguage()->getTag();
$clientId = (int) $app->getClientId();
// Build a cache ID for the resulting data object
$cacheId = $groups . '.' . $clientId . '.' . $Itemid;
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('m.id, m.title, m.module, m.position, m.content,
m.showtitle, m.params, mm.menuid')
->from('#__modules AS m')
->join('LEFT', '#__modules_menu AS mm ON mm.moduleid =
m.id')
->where('m.published = 1')
->join('LEFT', '#__extensions AS e ON e.element =
m.module AND e.client_id = m.client_id')
->where('e.enabled = 1');
$date = \JFactory::getDate();
$now = $date->toSql();
$nullDate = $db->getNullDate();
$query->where('(m.publish_up = ' . $db->quote($nullDate)
. ' OR m.publish_up <= ' . $db->quote($now) .
')')
->where('(m.publish_down = ' . $db->quote($nullDate) .
' OR m.publish_down >= ' . $db->quote($now) .
')')
->where('m.access IN (' . $groups . ')')
->where('m.client_id = ' . $clientId)
->where('(mm.menuid = ' . $Itemid . ' OR mm.menuid
<= 0)');
// Filter by language
if ($app->isClient('site') &&
$app->getLanguageFilter())
{
$query->where('m.language IN (' . $db->quote($lang) .
',' . $db->quote('*') . ')');
$cacheId .= $lang . '*';
}
if ($app->isClient('administrator') &&
static::isAdminMultilang())
{
$query->where('m.language IN (' . $db->quote($lang) .
',' . $db->quote('*') . ')');
$cacheId .= $lang . '*';
}
$query->order('m.position, m.ordering');
// Set the query
$db->setQuery($query);
try
{
/** @var \JCacheControllerCallback $cache */
$cache = \JFactory::getCache('com_modules',
'callback');
$modules = $cache->get(array($db, 'loadObjectList'),
array(), md5($cacheId), false);
}
catch (\RuntimeException $e)
{
\JLog::add(\JText::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD',
$e->getMessage()), \JLog::WARNING, 'jerror');
return array();
}
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 =
\JFactory::getApplication()->input->getInt('Itemid');
$negId = $Itemid ? -(int) $Itemid : false;
$clean = array();
$dupes = array();
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
* 'oldstatic' 1.5 definition of module caching, one cache
file for all pages
* with the same module id and user aid,
* '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 \JFilterInput::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;
}
$user = \JFactory::getUser();
$conf = \JFactory::getConfig();
/** @var \JCacheControllerCallback $cache */
$cache = \JFactory::getCache($cacheparams->cachegroup,
'callback');
// 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 ||
$conf->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',
$conf->get('cachetime') * 60) / 60);
$wrkaroundoptions = array('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(
array($cacheparams->class, $cacheparams->method),
$cacheparams->methodparams,
$cacheparams->modeparams,
$wrkarounds,
$wrkaroundoptions
);
break;
case 'safeuri':
$secureid = null;
if (is_array($cacheparams->modeparams))
{
$input = \JFactory::getApplication()->input;
$uri = $input->getArray();
$safeuri = new \stdClass;
$noHtmlFilter = \JFilterInput::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(array($safeuri, $cacheparams->method,
$moduleparams)));
$ret = $cache->get(
array($cacheparams->class, $cacheparams->method),
$cacheparams->methodparams,
$module->id . $view_levels . $secureid,
$wrkarounds,
$wrkaroundoptions
);
break;
case 'static':
$ret = $cache->get(
array($cacheparams->class, $cacheparams->method),
$cacheparams->methodparams,
$module->module . md5(serialize($cacheparams->methodparams)),
$wrkarounds,
$wrkaroundoptions
);
break;
// Provided for backward compatibility, not really useful.
case 'oldstatic':
$ret = $cache->get(
array($cacheparams->class, $cacheparams->method),
$cacheparams->methodparams,
$module->id . $view_levels,
$wrkarounds,
$wrkaroundoptions
);
break;
case 'itemid':
default:
$ret = $cache->get(
array($cacheparams->class, $cacheparams->method),
$cacheparams->methodparams,
$module->id . $view_levels .
\JFactory::getApplication()->input->getInt('Itemid', null),
$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 = new \stdClass;
$result->id = 0;
$result->title = '';
$result->module = '';
$result->position = '';
$result->content = '';
$result->showtitle = 0;
$result->control = '';
$result->params = '';
return $result;
}
}
RouteHelper.php000064400000016044151157061210007517 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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Language\Multilanguage;
/**
* Route Helper
*
* A class providing basic routing for urls that are for content types
found in
* the #__content_types table and rows found in the #__ucm_content table.
*
* @since 3.1
*/
class RouteHelper
{
/**
* @var array Holds the reverse lookup
* @since 3.1
*/
protected static $lookup;
/**
* @var string Option for the extension (such as com_content)
* @since 3.1
*/
protected $extension;
/**
* @var string Value of the primary key in the content type table
* @since 3.1
*/
protected $id;
/**
* @var string Name of the view for the url
* @since 3.1
*/
protected $view;
/**
* A method to get the route for a specific item
*
* @param integer $id Value of the primary key for the item in
its content table
* @param string $typealias The type_alias for the item being routed.
Of the form extension.view.
* @param string $link The link to be routed
* @param string $language The language of the content for
multilingual sites
* @param integer $catid Optional category id
*
* @return string The route of the item
*
* @since 3.1
*/
public function getRoute($id, $typealias, $link = '', $language
= null, $catid = null)
{
$typeExploded = explode('.', $typealias);
if (isset($typeExploded[1]))
{
$this->view = $typeExploded[1];
$this->extension = $typeExploded[0];
}
else
{
$this->view =
\JFactory::getApplication()->input->getCmd('view');
$this->extension =
\JFactory::getApplication()->input->getCmd('option');
}
$name = ucfirst(substr_replace($this->extension, '', 0, 4));
$needles = array();
if (isset($this->view))
{
$needles[$this->view] = array((int) $id);
}
if (empty($link))
{
// Create the link
$link = 'index.php?option=' . $this->extension .
'&view=' . $this->view . '&id=' . $id;
}
if ($catid > 1)
{
$categories = \JCategories::getInstance($name);
if ($categories)
{
$category = $categories->get((int) $catid);
if ($category)
{
$needles['category'] =
array_reverse($category->getPath());
$needles['categories'] = $needles['category'];
$link .= '&catid=' . $catid;
}
}
}
// Deal with languages only if needed
if (!empty($language) && $language !== '*' &&
Multilanguage::isEnabled())
{
$link .= '&lang=' . $language;
$needles['language'] = $language;
}
if ($item = $this->findItem($needles))
{
$link .= '&Itemid=' . $item;
}
return $link;
}
/**
* Method to find the item in the menu structure
*
* @param array $needles Array of lookup values
*
* @return mixed
*
* @since 3.1
*/
protected function findItem($needles = array())
{
$app = \JFactory::getApplication();
$menus = $app->getMenu('site');
$language = isset($needles['language']) ?
$needles['language'] : '*';
// $this->extension may not be set if coming from a static method,
check it
if ($this->extension === null)
{
$this->extension = $app->input->getCmd('option');
}
// Prepare the reverse lookup array.
if (!isset(static::$lookup[$language]))
{
static::$lookup[$language] = array();
$component = ComponentHelper::getComponent($this->extension);
$attributes = array('component_id');
$values = array($component->id);
if ($language !== '*')
{
$attributes[] = 'language';
$values[] = array($needles['language'], '*');
}
$items = $menus->getItems($attributes, $values);
foreach ($items as $item)
{
if (isset($item->query) &&
isset($item->query['view']))
{
$view = $item->query['view'];
if (!isset(static::$lookup[$language][$view]))
{
static::$lookup[$language][$view] = array();
}
if (isset($item->query['id']))
{
if (is_array($item->query['id']))
{
$item->query['id'] =
$item->query['id'][0];
}
/*
* Here it will become a bit tricky
* $language != * can override existing entries
* $language == * cannot override existing entries
*/
if ($item->language !== '*' ||
!isset(static::$lookup[$language][$view][$item->query['id']]))
{
static::$lookup[$language][$view][$item->query['id']] =
$item->id;
}
}
}
}
}
if ($needles)
{
foreach ($needles as $view => $ids)
{
if (isset(static::$lookup[$language][$view]))
{
foreach ($ids as $id)
{
if (isset(static::$lookup[$language][$view][(int) $id]))
{
return static::$lookup[$language][$view][(int) $id];
}
}
}
}
}
$active = $menus->getActive();
if ($active && $active->component === $this->extension
&& ($active->language === '*' ||
!Multilanguage::isEnabled()))
{
return $active->id;
}
// If not found, return language specific home link
$default = $menus->getDefault($language);
return !empty($default->id) ? $default->id : null;
}
/**
* Fetches the category route
*
* @param mixed $catid Category ID or \JCategoryNode instance
* @param mixed $language Language code
* @param string $extension Extension to lookup
*
* @return string
*
* @since 3.2
*
* @throws \InvalidArgumentException
*/
public static function getCategoryRoute($catid, $language = 0, $extension
= '')
{
// Note: $extension is required but has to be an optional argument in the
function call due to argument order
if (empty($extension))
{
throw new \InvalidArgumentException(sprintf('$extension is a
required argument in %s()', __METHOD__));
}
if ($catid instanceof \JCategoryNode)
{
$id = $catid->id;
$category = $catid;
}
else
{
$extensionName = ucfirst(substr($extension, 4));
$id = (int) $catid;
$category = \JCategories::getInstance($extensionName)->get($id);
}
if ($id < 1)
{
$link = '';
}
else
{
$link = 'index.php?option=' . $extension .
'&view=category&id=' . $id;
$needles = array(
'category' => array($id),
);
if ($language && $language !== '*' &&
Multilanguage::isEnabled())
{
$link .= '&lang=' . $language;
$needles['language'] = $language;
}
// Create the link
if ($category)
{
$catids = array_reverse($category->getPath());
$needles['category'] = $catids;
$needles['categories'] = $catids;
}
if ($item = static::lookupItem($needles))
{
$link .= '&Itemid=' . $item;
}
}
return $link;
}
/**
* Static alias to findItem() used to find the item in the menu structure
*
* @param array $needles Array of lookup values
*
* @return mixed
*
* @since 3.2
*/
protected static function lookupItem($needles = array())
{
$instance = new static;
return $instance->findItem($needles);
}
}
SearchHelper.php000064400000003557151157061210007633 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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
/**
* Helper class for Joomla! Search components
*
* @since 3.0
*/
class SearchHelper
{
/**
* Method to log search terms to the database
*
* @param string $term The term being searched
* @param string $component The component being used for the search
*
* @return void
*
* @since 3.0
*/
public static function logSearch($term, $component)
{
// Initialise our variables
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$enable_log_searches =
ComponentHelper::getParams($component)->get('enabled');
// Sanitise the term for the database
$search_term = $db->escape(trim(strtolower($term)));
if ($enable_log_searches)
{
// Query the table to determine if the term has been searched previously
$query->select($db->quoteName('hits'))
->from($db->quoteName('#__core_log_searches'))
->where($db->quoteName('search_term') . ' = '
. $db->quote($search_term));
$db->setQuery($query);
$hits = (int) $db->loadResult();
// Reset the $query object
$query->clear();
// Update the table based on the results
if ($hits)
{
$query->update($db->quoteName('#__core_log_searches'))
->set('hits = (hits + 1)')
->where($db->quoteName('search_term') . ' =
' . $db->quote($search_term));
}
else
{
$query->insert($db->quoteName('#__core_log_searches'))
->columns(array($db->quoteName('search_term'),
$db->quoteName('hits')))
->values($db->quote($search_term) . ', 1');
}
// Execute the update query
$db->setQuery($query);
$db->execute();
}
}
}
TagsHelper.php000064400000073134151157061210007322 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\Helper;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Table\TableInterface;
use Joomla\Utilities\ArrayHelper;
/**
* Tags helper class, provides methods to perform various tasks relevant
* tagging of content.
*
* @since 3.1
*/
class TagsHelper extends CMSHelper
{
/**
* Helper object for storing and deleting tag information.
*
* @var boolean
* @since 3.1
*/
protected $tagsChanged = false;
/**
* Whether up replace all tags or just add tags
*
* @var boolean
* @since 3.1
*/
protected $replaceTags = false;
/**
* Alias for querying mapping and content type table.
*
* @var string
* @since 3.1
*/
public $typeAlias = null;
/**
* Method to add tag rows to mapping table.
*
* @param integer $ucmId ID of the #__ucm_content item being
tagged
* @param TableInterface $table Table object being tagged
* @param array $tags Array of tags to be applied.
*
* @return boolean true on success, otherwise false.
*
* @since 3.1
*/
public function addTagMapping($ucmId, TableInterface $table, $tags =
array())
{
$db = $table->getDbo();
$key = $table->getKeyName();
$item = $table->$key;
$typeId = $this->getTypeId($this->typeAlias);
// Insert the new tag maps
if (strpos('#', implode(',', $tags)) === false)
{
$tags = self::createTagsFromField($tags);
}
// Prevent saving duplicate tags
$tags = array_unique($tags);
$query = $db->getQuery(true);
$query->insert('#__contentitem_tag_map');
$query->columns(
array(
$db->quoteName('type_alias'),
$db->quoteName('core_content_id'),
$db->quoteName('content_item_id'),
$db->quoteName('tag_id'),
$db->quoteName('tag_date'),
$db->quoteName('type_id'),
)
);
foreach ($tags as $tag)
{
$query->values(
$db->quote($this->typeAlias)
. ', ' . (int) $ucmId
. ', ' . (int) $item
. ', ' . $db->quote($tag)
. ', ' . $query->currentTimestamp()
. ', ' . (int) $typeId
);
}
$db->setQuery($query);
return (boolean) $db->execute();
}
/**
* Function that converts tags paths into paths of names
*
* @param array $tags Array of tags
*
* @return array
*
* @since 3.1
*/
public static function convertPathsToNames($tags)
{
// We will replace path aliases with tag names
if ($tags)
{
// Create an array with all the aliases of the results
$aliases = array();
foreach ($tags as $tag)
{
if (!empty($tag->path))
{
if ($pathParts = explode('/', $tag->path))
{
$aliases = array_merge($aliases, $pathParts);
}
}
}
// Get the aliases titles in one single query and map the results
if ($aliases)
{
// Remove duplicates
$aliases = array_unique($aliases);
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('alias, title')
->from('#__tags')
->where('alias IN (' . implode(',',
array_map(array($db, 'quote'), $aliases)) . ')');
$db->setQuery($query);
try
{
$aliasesMapper = $db->loadAssocList('alias');
}
catch (\RuntimeException $e)
{
return false;
}
// Rebuild the items path
if ($aliasesMapper)
{
foreach ($tags as $tag)
{
$namesPath = array();
if (!empty($tag->path))
{
if ($pathParts = explode('/', $tag->path))
{
foreach ($pathParts as $alias)
{
if (isset($aliasesMapper[$alias]))
{
$namesPath[] = $aliasesMapper[$alias]['title'];
}
else
{
$namesPath[] = $alias;
}
}
$tag->text = implode('/', $namesPath);
}
}
}
}
}
}
return $tags;
}
/**
* Create any new tags by looking for #new# in the strings
*
* @param array $tags Tags text array from the field
*
* @return mixed If successful, metadata with new tag titles replaced
by tag ids. Otherwise false.
*
* @since 3.1
*/
public function createTagsFromField($tags)
{
if (empty($tags) || $tags[0] == '')
{
return;
}
else
{
// We will use the tags table to store them
Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_tags/tables');
$tagTable = Table::getInstance('Tag', 'TagsTable');
$newTags = array();
$canCreate = \JFactory::getUser()->authorise('core.create',
'com_tags');
foreach ($tags as $key => $tag)
{
// User is not allowed to create tags, so don't create.
if (!$canCreate && strpos($tag, '#new#') !== false)
{
continue;
}
// Remove the #new# prefix that identifies new tags
$tagText = str_replace('#new#', '', $tag);
if ($tagText === $tag)
{
$newTags[] = (int) $tag;
}
else
{
// Clear old data if exist
$tagTable->reset();
// Try to load the selected tag
if ($tagTable->load(array('title' => $tagText)))
{
$newTags[] = (int) $tagTable->id;
}
else
{
// Prepare tag data
$tagTable->id = 0;
$tagTable->title = $tagText;
$tagTable->published = 1;
// $tagTable->language = property_exists ($item,
'language') ? $item->language : '*';
$tagTable->language = '*';
$tagTable->access = 1;
// Make this item a child of the root tag
$tagTable->setLocation($tagTable->getRootId(),
'last-child');
// Try to store tag
if ($tagTable->check())
{
// Assign the alias as path (autogenerated tags have always level 1)
$tagTable->path = $tagTable->alias;
if ($tagTable->store())
{
$newTags[] = (int) $tagTable->id;
}
}
}
}
}
// At this point $tags is an array of all tag ids
$this->tags = $newTags;
$result = $newTags;
}
return $result;
}
/**
* Create any new tags by looking for #new# in the metadata
*
* @param string $metadata Metadata JSON string
*
* @return mixed If successful, metadata with new tag titles replaced
by tag ids. Otherwise false.
*
* @since 3.1
* @deprecated 4.0 This method is no longer used in the CMS and will not
be replaced.
*/
public function createTagsFromMetadata($metadata)
{
$metaObject = json_decode($metadata);
if (empty($metaObject->tags))
{
return $metadata;
}
$tags = $metaObject->tags;
if (empty($tags) || !is_array($tags))
{
$result = $metadata;
}
else
{
// We will use the tags table to store them
Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_tags/tables');
$tagTable = Table::getInstance('Tag', 'TagsTable');
$newTags = array();
foreach ($tags as $tag)
{
// Remove the #new# prefix that identifies new tags
$tagText = str_replace('#new#', '', $tag);
if ($tagText === $tag)
{
$newTags[] = (int) $tag;
}
else
{
// Clear old data if exist
$tagTable->reset();
// Try to load the selected tag
if ($tagTable->load(array('title' => $tagText)))
{
$newTags[] = (int) $tagTable->id;
}
else
{
// Prepare tag data
$tagTable->id = 0;
$tagTable->title = $tagText;
$tagTable->published = 1;
// $tagTable->language = property_exists ($item,
'language') ? $item->language : '*';
$tagTable->language = '*';
$tagTable->access = 1;
// Make this item a child of the root tag
$tagTable->setLocation($tagTable->getRootId(),
'last-child');
// Try to store tag
if ($tagTable->check())
{
// Assign the alias as path (autogenerated tags have always level 1)
$tagTable->path = $tagTable->alias;
if ($tagTable->store())
{
$newTags[] = (int) $tagTable->id;
}
}
}
}
}
// At this point $tags is an array of all tag ids
$metaObject->tags = $newTags;
$result = json_encode($metaObject);
}
return $result;
}
/**
* Method to delete the tag mappings and #__ucm_content record for for an
item
*
* @param TableInterface $table Table object of content table
where delete occurred
* @param integer|array $contentItemId ID of the content item. Or an
array of key/value pairs with array key
* being a primary key name and
value being the content item ID. Note
* multiple primary keys are not
supported
*
* @return boolean true on success, false on failure
*
* @since 3.1
* @throws \InvalidArgumentException
*/
public function deleteTagData(TableInterface $table, $contentItemId)
{
$key = $table->getKeyName();
if (!is_array($contentItemId))
{
$contentItemId = array($key => $contentItemId);
}
// If we have multiple items for the content item primary key we
currently don't support this so
// throw an InvalidArgumentException for now
if (count($contentItemId) != 1)
{
throw new \InvalidArgumentException('Multiple primary keys are not
supported as a content item id');
}
$result = $this->unTagItem($contentItemId[$key], $table);
/** @var \JTableCorecontent $ucmContentTable */
$ucmContentTable = Table::getInstance('Corecontent');
return $result &&
$ucmContentTable->deleteByContentId($contentItemId[$key],
$this->typeAlias);
}
/**
* Method to get a list of tags for an item, optionally with the tag data.
*
* @param string $contentType Content type alias. Dot separated.
* @param integer $id Id of the item to retrieve tags for.
* @param boolean $getTagData If true, data from the tags table will
be included, defaults to true.
*
* @return array Array of of tag objects
*
* @since 3.1
*/
public function getItemTags($contentType, $id, $getTagData = true)
{
// Initialize some variables.
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('m.tag_id'))
->from($db->quoteName('#__contentitem_tag_map') . '
AS m ')
->where(
array(
$db->quoteName('m.type_alias') . ' = ' .
$db->quote($contentType),
$db->quoteName('m.content_item_id') . ' = ' .
(int) $id,
$db->quoteName('t.published') . ' = 1',
)
);
$user = \JFactory::getUser();
$groups = implode(',', $user->getAuthorisedViewLevels());
$query->where('t.access IN (' . $groups . ')');
// Optionally filter on language
$language =
ComponentHelper::getParams('com_tags')->get('tag_list_language_filter',
'all');
if ($language !== 'all')
{
if ($language === 'current_language')
{
$language = $this->getCurrentLanguage();
}
$query->where($db->quoteName('language') . ' IN
(' . $db->quote($language) . ', ' .
$db->quote('*') . ')');
}
if ($getTagData)
{
$query->select($db->quoteName('t') . '.*');
}
$query->join('INNER', $db->quoteName('#__tags')
. ' AS t ' . ' ON ' .
$db->quoteName('m.tag_id') . ' = ' .
$db->quoteName('t.id'));
$db->setQuery($query);
$this->itemTags = $db->loadObjectList();
return $this->itemTags;
}
/**
* Method to get a list of tags for a given item.
* Normally used for displaying a list of tags within a layout
*
* @param mixed $ids The id or array of ids (primary key) of the
item to be tagged.
* @param string $prefix Dot separated string with the option and view
to be used for a url.
*
* @return string Comma separated list of tag Ids.
*
* @since 3.1
*/
public function getTagIds($ids, $prefix)
{
if (empty($ids))
{
return;
}
/**
* Ids possible formats:
* ---------------------
* $id = 1;
* $id = array(1,2);
* $id = array('1,3,4,19');
* $id = '1,3';
*/
$ids = (array) $ids;
$ids = implode(',', $ids);
$ids = explode(',', $ids);
$ids = ArrayHelper::toInteger($ids);
$db = \JFactory::getDbo();
// Load the tags.
$query = $db->getQuery(true)
->select($db->quoteName('t.id'))
->from($db->quoteName('#__tags') . ' AS t ')
->join(
'INNER',
$db->quoteName('#__contentitem_tag_map') . ' AS m'
. ' ON ' . $db->quoteName('m.tag_id') . ' =
' . $db->quoteName('t.id')
. ' AND ' . $db->quoteName('m.type_alias') .
' = ' . $db->quote($prefix)
. ' AND ' . $db->quoteName('m.content_item_id')
. ' IN ( ' . implode(',', $ids) . ')'
);
$db->setQuery($query);
// Add the tags to the content data.
$tagsList = $db->loadColumn();
$this->tags = implode(',', $tagsList);
return $this->tags;
}
/**
* Method to get a query to retrieve a detailed list of items for a tag.
*
* @param mixed $tagId Tag or array of tags to be matched
* @param mixed $typesr Null, type or array of type aliases
for content types to be included in the results
* @param boolean $includeChildren True to include the results from
child tags
* @param string $orderByOption Column to order the results by
* @param string $orderDir Direction to sort the results in
* @param boolean $anyOrAll True to include items matching at
least one tag, false to include
* items all tags in the array.
* @param string $languageFilter Optional filter on language.
Options are 'all', 'current' or any string.
* @param string $stateFilter Optional filtering on publication
state, defaults to published or unpublished.
*
* @return \JDatabaseQuery Query to retrieve a list of tags
*
* @since 3.1
*/
public function getTagItemsQuery($tagId, $typesr = null, $includeChildren
= false, $orderByOption = 'c.core_title', $orderDir =
'ASC',
$anyOrAll = true, $languageFilter = 'all', $stateFilter =
'0,1')
{
// Create a new query object.
$db = \JFactory::getDbo();
$query = $db->getQuery(true);
$user = \JFactory::getUser();
$nullDate = $db->quote($db->getNullDate());
$nowDate = $db->quote(\JFactory::getDate()->toSql());
// Force ids to array and sanitize
$tagIds = (array) $tagId;
$tagIds = implode(',', $tagIds);
$tagIds = explode(',', $tagIds);
$tagIds = ArrayHelper::toInteger($tagIds);
$ntagsr = count($tagIds);
// If we want to include children we have to adjust the list of tags.
// We do not search child tags when the match all option is selected.
if ($includeChildren)
{
$tagTreeArray = array();
foreach ($tagIds as $tag)
{
$this->getTagTreeArray($tag, $tagTreeArray);
}
$tagIds = array_unique(array_merge($tagIds, $tagTreeArray));
}
// Sanitize filter states
$stateFilters = explode(',', $stateFilter);
$stateFilters = ArrayHelper::toInteger($stateFilters);
// M is the mapping table. C is the core_content table. Ct is the
content_types table.
$query
->select(
'm.type_alias'
. ', ' . 'm.content_item_id'
. ', ' . 'm.core_content_id'
. ', ' . 'count(m.tag_id) AS match_count'
. ', ' . 'MAX(m.tag_date) as tag_date'
. ', ' . 'MAX(c.core_title) AS core_title'
. ', ' . 'MAX(c.core_params) AS core_params'
)
->select('MAX(c.core_alias) AS core_alias, MAX(c.core_body) AS
core_body, MAX(c.core_state) AS core_state, MAX(c.core_access) AS
core_access')
->select(
'MAX(c.core_metadata) AS core_metadata'
. ', ' . 'MAX(c.core_created_user_id) AS
core_created_user_id'
. ', ' . 'MAX(c.core_created_by_alias) AS
core_created_by_alias'
)
->select('MAX(c.core_created_time) as core_created_time,
MAX(c.core_images) as core_images')
->select('CASE WHEN c.core_modified_time = ' . $nullDate .
' THEN c.core_created_time ELSE c.core_modified_time END as
core_modified_time')
->select('MAX(c.core_language) AS core_language,
MAX(c.core_catid) AS core_catid')
->select('MAX(c.core_publish_up) AS core_publish_up,
MAX(c.core_publish_down) as core_publish_down')
->select('MAX(ct.type_title) AS content_type_title,
MAX(ct.router) AS router')
->from('#__contentitem_tag_map AS m')
->join(
'INNER',
'#__ucm_content AS c ON m.type_alias = c.core_type_alias AND
m.core_content_id = c.core_content_id AND c.core_state IN ('
. implode(',', $stateFilters) . ')'
. (in_array('0', $stateFilters) ? '' : ' AND
(c.core_publish_up = ' . $nullDate
. ' OR c.core_publish_up <= ' . $nowDate . ') '
. ' AND (c.core_publish_down = ' . $nullDate . ' OR
c.core_publish_down >= ' . $nowDate . ')')
)
->join('INNER', '#__content_types AS ct ON
ct.type_alias = m.type_alias')
// Join over categories for get only tags from published categories
->join('LEFT', '#__categories AS tc ON tc.id =
c.core_catid')
// Join over the users for the author and email
->select("CASE WHEN c.core_created_by_alias > ' '
THEN c.core_created_by_alias ELSE ua.name END AS author")
->select('ua.email AS author_email')
->join('LEFT', '#__users AS ua ON ua.id =
c.core_created_user_id')
->where('m.tag_id IN (' . implode(',', $tagIds) .
')')
->where('(c.core_catid = 0 OR tc.published = 1)');
// Optionally filter on language
if (empty($language))
{
$language = $languageFilter;
}
if ($language !== 'all')
{
if ($language === 'current_language')
{
$language = $this->getCurrentLanguage();
}
$query->where($db->quoteName('c.core_language') . '
IN (' . $db->quote($language) . ', ' .
$db->quote('*') . ')');
}
// Get the type data, limited to types in the request if there are any
specified.
$typesarray = self::getTypes('assocList', $typesr, false);
$typeAliases = array();
foreach ($typesarray as $type)
{
$typeAliases[] = $db->quote($type['type_alias']);
}
$query->where('m.type_alias IN (' . implode(',',
$typeAliases) . ')');
$groups = '0,' . implode(',',
array_unique($user->getAuthorisedViewLevels()));
$query->where('c.core_access IN (' . $groups .
')')
->group('m.type_alias, m.content_item_id, m.core_content_id,
core_modified_time, core_created_time, core_created_by_alias, author,
author_email');
// Use HAVING if matching all tags and we are matching more than one tag.
if ($ntagsr > 1 && $anyOrAll != 1 && $includeChildren
!= 1)
{
// The number of results should equal the number of tags requested.
$query->having("COUNT('m.tag_id') = " . (int)
$ntagsr);
}
// Set up the order by using the option chosen
if ($orderByOption === 'match_count')
{
$orderBy = 'COUNT(m.tag_id)';
}
else
{
$orderBy = 'MAX(' . $db->quoteName($orderByOption) .
')';
}
$query->order($orderBy . ' ' . $orderDir);
return $query;
}
/**
* Function that converts tag ids to their tag names
*
* @param array $tagIds Array of integer tag ids.
*
* @return array An array of tag names.
*
* @since 3.1
*/
public function getTagNames($tagIds)
{
$tagNames = array();
if (is_array($tagIds) && count($tagIds) > 0)
{
$tagIds = ArrayHelper::toInteger($tagIds);
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('title'))
->from($db->quoteName('#__tags'))
->where($db->quoteName('id') . ' IN (' .
implode(',', $tagIds) . ')');
$query->order($db->quoteName('title'));
$db->setQuery($query);
$tagNames = $db->loadColumn();
}
return $tagNames;
}
/**
* Method to get an array of tag ids for the current tag and its children
*
* @param integer $id An optional ID
* @param array &$tagTreeArray Array containing the tag tree
*
* @return mixed
*
* @since 3.1
*/
public function getTagTreeArray($id, &$tagTreeArray = array())
{
// Get a level row instance.
Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_tags/tables');
$table = Table::getInstance('Tag', 'TagsTable');
if ($table->isLeaf($id))
{
$tagTreeArray[] = $id;
return $tagTreeArray;
}
$tagTree = $table->getTree($id);
// Attempt to load the tree
if ($tagTree)
{
foreach ($tagTree as $tag)
{
$tagTreeArray[] = $tag->id;
}
return $tagTreeArray;
}
}
/**
* Method to get the type id for a type alias.
*
* @param string $typeAlias A type alias.
*
* @return string Name of the table for a type
*
* @since 3.1
* @deprecated 4.0 Use \JUcmType::getTypeId() instead
*/
public function getTypeId($typeAlias)
{
$contentType = new \JUcmType;
return $contentType->getTypeId($typeAlias);
}
/**
* Method to get a list of types with associated data.
*
* @param string $arrayType Optionally specify that the returned
list consist of objects, associative arrays, or arrays.
* Options are: rowList, assocList, and
objectList
* @param array $selectTypes Optional array of type ids to limit the
results to. Often from a request.
* @param boolean $useAlias If true, the alias is used to match, if
false the type_id is used.
*
* @return array Array of of types
*
* @since 3.1
*/
public static function getTypes($arrayType = 'objectList',
$selectTypes = null, $useAlias = true)
{
// Initialize some variables.
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('*');
if (!empty($selectTypes))
{
$selectTypes = (array) $selectTypes;
if ($useAlias)
{
$selectTypes = array_map(array($db, 'quote'), $selectTypes);
$query->where($db->quoteName('type_alias') . ' IN
(' . implode(',', $selectTypes) . ')');
}
else
{
$selectTypes = ArrayHelper::toInteger($selectTypes);
$query->where($db->quoteName('type_id') . ' IN
(' . implode(',', $selectTypes) . ')');
}
}
$query->from($db->quoteName('#__content_types'));
$db->setQuery($query);
switch ($arrayType)
{
case 'assocList':
$types = $db->loadAssocList();
break;
case 'rowList':
$types = $db->loadRowList();
break;
case 'objectList':
default:
$types = $db->loadObjectList();
break;
}
return $types;
}
/**
* Function that handles saving tags used in a table class after a store()
*
* @param TableInterface $table Table being processed
* @param array $newTags Array of new tags
* @param boolean $replace Flag indicating if all existing tags
should be replaced
*
* @return boolean
*
* @since 3.1
*/
public function postStoreProcess(TableInterface $table, $newTags =
array(), $replace = true)
{
if (!empty($table->newTags) && empty($newTags))
{
$newTags = $table->newTags;
}
// If existing row, check to see if tags have changed.
$newTable = clone $table;
$newTable->reset();
$result = true;
// Process ucm_content and ucm_base if either tags have changed or we
have some tags.
if ($this->tagsChanged || (!empty($newTags) && $newTags[0] !=
''))
{
if (!$newTags && $replace == true)
{
// Delete all tags data
$key = $table->getKeyName();
$result = $this->deleteTagData($table, $table->$key);
}
else
{
// Process the tags
$data = $this->getRowData($table);
$ucmContentTable = Table::getInstance('Corecontent');
$ucm = new \JUcmContent($table, $this->typeAlias);
$ucmData = $data ? $ucm->mapData($data) : $ucm->ucmData;
$primaryId =
$ucm->getPrimaryKey($ucmData['common']['core_type_id'],
$ucmData['common']['core_content_item_id']);
$result = $ucmContentTable->load($primaryId);
$result = $result &&
$ucmContentTable->bind($ucmData['common']);
$result = $result && $ucmContentTable->check();
$result = $result && $ucmContentTable->store();
$ucmId = $ucmContentTable->core_content_id;
// Store the tag data if the article data was saved and run related
methods.
$result = $result && $this->tagItem($ucmId, $table,
$newTags, $replace);
}
}
return $result;
}
/**
* Function that preProcesses data from a table prior to a store() to
ensure proper tag handling
*
* @param TableInterface $table Table being processed
* @param array $newTags Array of new tags
*
* @return null
*
* @since 3.1
*/
public function preStoreProcess(TableInterface $table, $newTags = array())
{
if ($newTags != array())
{
$this->newTags = $newTags;
}
// If existing row, check to see if tags have changed.
$oldTable = clone $table;
$oldTable->reset();
$key = $oldTable->getKeyName();
$typeAlias = $this->typeAlias;
if ($oldTable->$key && $oldTable->load())
{
$this->oldTags = $this->getTagIds($oldTable->$key, $typeAlias);
}
// New items with no tags bypass this step.
if ((!empty($newTags) && is_string($newTags) ||
(isset($newTags[0]) && $newTags[0] != '')) ||
isset($this->oldTags))
{
if (is_array($newTags))
{
$newTags = implode(',', $newTags);
}
// We need to process tags if the tags have changed or if we have a new
row
$this->tagsChanged = (empty($this->oldTags) &&
!empty($newTags)) ||(!empty($this->oldTags) && $this->oldTags
!= $newTags) || !$table->$key;
}
}
/**
* Function to search tags
*
* @param array $filters Filter to apply to the search
*
* @return array
*
* @since 3.1
*/
public static function searchTags($filters = array())
{
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('a.id AS value')
->select('a.path AS text')
->select('a.path')
->from('#__tags AS a')
->join('LEFT', $db->quoteName('#__tags',
'b') . ' ON a.lft > b.lft AND a.rgt < b.rgt');
// Filter language
if (!empty($filters['flanguage']))
{
$query->where('a.language IN (' .
$db->quote($filters['flanguage']) . ',' .
$db->quote('*') . ') ');
}
// Do not return root
$query->where($db->quoteName('a.alias') . ' <>
' . $db->quote('root'));
// Search in title or path
if (!empty($filters['like']))
{
$query->where(
'(' . $db->quoteName('a.title') . ' LIKE
' . $db->quote('%' . $filters['like'] .
'%')
. ' OR ' . $db->quoteName('a.path') . '
LIKE ' . $db->quote('%' . $filters['like'] .
'%') . ')'
);
}
// Filter title
if (!empty($filters['title']))
{
$query->where($db->quoteName('a.title') . ' =
' . $db->quote($filters['title']));
}
// Filter on the published state
if (isset($filters['published']) &&
is_numeric($filters['published']))
{
$query->where('a.published = ' . (int)
$filters['published']);
}
// Filter on the access level
if (isset($filters['access']) &&
is_array($filters['access']) &&
count($filters['access']))
{
$groups = ArrayHelper::toInteger($filters['access']);
$query->where('a.access IN (' . implode(",",
$groups) . ')');
}
// Filter by parent_id
if (isset($filters['parent_id']) &&
is_numeric($filters['parent_id']))
{
Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_tags/tables');
$tagTable = Table::getInstance('Tag', 'TagsTable');
if ($children = $tagTable->getTree($filters['parent_id']))
{
foreach ($children as $child)
{
$childrenIds[] = $child->id;
}
$query->where('a.id IN (' . implode(',',
$childrenIds) . ')');
}
}
$query->group('a.id, a.title, a.level, a.lft, a.rgt, a.parent_id,
a.published, a.path')
->order('a.lft ASC');
// Get the options.
$db->setQuery($query);
try
{
$results = $db->loadObjectList();
}
catch (\RuntimeException $e)
{
return array();
}
// We will replace path aliases with tag names
return self::convertPathsToNames($results);
}
/**
* Method to delete all instances of a tag from the mapping table.
Generally used when a tag is deleted.
*
* @param integer $tagId The tag_id (primary key) for the deleted tag.
*
* @return void
*
* @since 3.1
*/
public function tagDeleteInstances($tagId)
{
// Delete the old tag maps.
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->delete($db->quoteName('#__contentitem_tag_map'))
->where($db->quoteName('tag_id') . ' = ' .
(int) $tagId);
$db->setQuery($query);
$db->execute();
}
/**
* Method to add or update tags associated with an item.
*
* @param integer $ucmId Id of the #__ucm_content item being
tagged
* @param TableInterface $table Table object being tagged
* @param array $tags Array of tags to be applied.
* @param boolean $replace Flag indicating if all existing tags
should be replaced
*
* @return boolean true on success, otherwise false.
*
* @since 3.1
*/
public function tagItem($ucmId, TableInterface $table, $tags = array(),
$replace = true)
{
$key = $table->get('_tbl_key');
$oldTags = $this->getTagIds((int) $table->$key,
$this->typeAlias);
$oldTags = explode(',', $oldTags);
$result = $this->unTagItem($ucmId, $table);
if ($replace)
{
$newTags = $tags;
}
else
{
if ($tags == array())
{
$newTags = $table->newTags;
}
else
{
$newTags = $tags;
}
if ($oldTags[0] != '')
{
$newTags = array_unique(array_merge($newTags, $oldTags));
}
}
if (is_array($newTags) && count($newTags) > 0 &&
$newTags[0] != '')
{
$result = $result && $this->addTagMapping($ucmId, $table,
$newTags);
}
return $result;
}
/**
* Method to untag an item
*
* @param integer $contentId ID of the content item being
untagged
* @param TableInterface $table Table object being untagged
* @param array $tags Array of tags to be untagged. Use
an empty array to untag all existing tags.
*
* @return boolean true on success, otherwise false.
*
* @since 3.1
*/
public function unTagItem($contentId, TableInterface $table, $tags =
array())
{
$key = $table->getKeyName();
$id = $table->$key;
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->delete('#__contentitem_tag_map')
->where($db->quoteName('type_alias') . ' = ' .
$db->quote($this->typeAlias))
->where($db->quoteName('content_item_id') . ' =
' . (int) $id);
if (is_array($tags) && count($tags) > 0)
{
$tags = ArrayHelper::toInteger($tags);
$query->where($db->quoteName('tag_id') . ' IN
(' . implode(',', $tags) . ')');
}
$db->setQuery($query);
return (boolean) $db->execute();
}
}
UserGroupsHelper.php000064400000013057151157061210010540 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\Helper;
defined('JPATH_PLATFORM') or die;
/**
* Helper to deal with user groups.
*
* @since 3.6.3
*/
final class UserGroupsHelper
{
/**
* Indicates the current helper instance is the singleton instance.
*
* @var integer
* @since 3.6.3
*/
const MODE_SINGLETON = 1;
/**
* Indicates the current helper instance is a standalone class instance.
*
* @var integer
* @since 3.6.3
*/
const MODE_INSTANCE = 2;
/**
* Singleton instance.
*
* @var array
* @since 3.6.3
*/
private static $instance;
/**
* Available user groups
*
* @var array
* @since 3.6.3
*/
private $groups = array();
/**
* Mode this class is working: singleton or std instance
*
* @var integer
* @since 3.6.3
*/
private $mode;
/**
* Total available groups
*
* @var integer
* @since 3.6.3
*/
private $total;
/**
* Constructor
*
* @param array $groups Array of groups
* @param integer $mode Working mode for this class
*
* @since 3.6.3
*/
public function __construct(array $groups = array(), $mode =
self::MODE_INSTANCE)
{
$this->mode = (int) $mode;
if ($groups)
{
$this->setGroups($groups);
}
}
/**
* Count loaded user groups.
*
* @return integer
*
* @since 3.6.3
*/
public function count()
{
return count($this->groups);
}
/**
* Get the helper instance.
*
* @return self
*
* @since 3.6.3
*/
public static function getInstance()
{
if (static::$instance === null)
{
// Only here to avoid code style issues...
$groups = array();
static::$instance = new static($groups, static::MODE_SINGLETON);
}
return static::$instance;
}
/**
* Get a user group by its id.
*
* @param integer $id Group identifier
*
* @return mixed stdClass on success. False otherwise
*
* @since 3.6.3
*/
public function get($id)
{
if ($this->has($id))
{
return $this->groups[$id];
}
// Singleton will load groups as they are requested
if ($this->isSingleton())
{
$this->groups[$id] = $this->load($id);
return $this->groups[$id];
}
return false;
}
/**
* Get the list of existing user groups.
*
* @return array
*
* @since 3.6.3
*/
public function getAll()
{
if ($this->isSingleton() && $this->total() !==
$this->count())
{
$this->loadAll();
}
return $this->groups;
}
/**
* Check if a group is in the list.
*
* @param integer $id Group identifier
*
* @return boolean
*
* @since 3.6.3
*/
public function has($id)
{
return (array_key_exists($id, $this->groups) &&
$this->groups[$id] !== false);
}
/**
* Check if this instance is a singleton.
*
* @return boolean
*
* @since 3.6.3
*/
private function isSingleton()
{
return $this->mode === static::MODE_SINGLETON;
}
/**
* Get total available user groups in database.
*
* @return integer
*
* @since 3.6.3
*/
public function total()
{
if ($this->total === null)
{
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('count(id)')
->from('#__usergroups');
$db->setQuery($query);
$this->total = (int) $db->loadResult();
}
return $this->total;
}
/**
* Load a group from database.
*
* @param integer $id Group identifier
*
* @return mixed
*
* @since 3.6.3
*/
public function load($id)
{
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('*')
->from('#__usergroups')
->where('id = ' . (int) $id);
$db->setQuery($query);
$group = $db->loadObject();
if (!$group)
{
return false;
}
return $this->populateGroupData($group);
}
/**
* Load all user groups from the database.
*
* @return self
*
* @since 3.6.3
*/
public function loadAll()
{
$this->groups = array();
$db = \JFactory::getDbo();
$query = $db->getQuery(true)
->select('*')
->from('#__usergroups')
->order('lft ASC');
$db->setQuery($query);
$groups = $db->loadObjectList('id');
$this->groups = $groups ?: array();
$this->populateGroupsData();
return $this;
}
/**
* Populates extra information for groups.
*
* @return array
*
* @since 3.6.3
*/
private function populateGroupsData()
{
foreach ($this->groups as $group)
{
$this->populateGroupData($group);
}
return $this->groups;
}
/**
* Populate data for a specific user group.
*
* @param \stdClass $group Group
*
* @return \stdClass
*
* @since 3.6.3
*/
public function populateGroupData($group)
{
if (!$group || property_exists($group, 'path'))
{
return $group;
}
$parentId = (int) $group->parent_id;
if ($parentId === 0)
{
$group->path = array($group->id);
$group->level = 0;
return $group;
}
$parentGroup = $this->has($parentId) ? $this->get($parentId) :
$this->load($parentId);
if (!property_exists($parentGroup, 'path'))
{
$parentGroup = $this->populateGroupData($parentGroup);
}
$group->path = array_merge($parentGroup->path,
array($group->id));
$group->level = count($group->path) - 1;
return $group;
}
/**
* Set the groups to be used as source.
*
* @param array $groups Array of user groups.
*
* @return self
*
* @since 3.6.3
*/
public function setGroups(array $groups)
{
$this->groups = $groups;
$this->populateGroupsData();
$this->total = count($groups);
return $this;
}
}