Spade
Mini Shell
| Directory:~$ /home/lmsyaran/www/joomla5/administrator/components/com_actionlogs/src/Helper/ |
| [Home] [System Details] [Kill Me] |
<?php
/**
* @package Joomla.Administrator
* @subpackage com_actionlogs
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
namespace Joomla\Component\Actionlogs\Administrator\Helper;
use Joomla\CMS\Date\Date;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Router\Route;
use Joomla\Filesystem\Path;
use Joomla\String\StringHelper;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Actionlogs component helper.
*
* @since 3.9.0
*/
class ActionlogsHelper
{
/**
* Array of characters starting a formula
*
* @var array
*
* @since 3.9.7
*/
private static $characters = ['=', '+',
'-', '@'];
/**
* Method to convert logs objects array to an iterable type for use
with a CSV export
*
* @param array|\Traversable $data The logs data objects to be
exported
*
* @return \Generator
*
* @since 3.9.0
*
* @throws \InvalidArgumentException
*/
public static function getCsvData($data): \Generator
{
if (!is_iterable($data)) {
throw new \InvalidArgumentException(
sprintf(
'%s() requires an array or object implementing the
Traversable interface, a %s was given.',
__METHOD__,
\is_object($data) ? \get_class($data) : \gettype($data)
)
);
}
$disabledText = Text::_('COM_ACTIONLOGS_DISABLED');
// Header row
yield ['Id', 'Action', 'Extension',
'Date', 'Name', 'IP Address'];
foreach ($data as $log) {
$extension = strtok($log->extension, '.');
static::loadTranslationFiles($extension);
yield [
'id' => $log->id,
'message' =>
self::escapeCsvFormula(strip_tags(static::getHumanReadableLogMessage($log,
false))),
'extension' =>
self::escapeCsvFormula(Text::_($extension)),
'date' => (new Date($log->log_date,
new \DateTimeZone('UTC')))->format('Y-m-d H:i:s T'),
'name' =>
self::escapeCsvFormula($log->name),
'ip_address' =>
self::escapeCsvFormula($log->ip_address ===
'COM_ACTIONLOGS_DISABLED' ? $disabledText : $log->ip_address),
];
}
}
/**
* Load the translation files for an extension
*
* @param string $extension Extension name
*
* @return void
*
* @since 3.9.0
*/
public static function loadTranslationFiles($extension)
{
static $cache = [];
$extension = strtolower($extension);
if (isset($cache[$extension])) {
return;
}
$lang = Factory::getLanguage();
$source = '';
switch (substr($extension, 0, 3)) {
case 'com':
default:
$source = JPATH_ADMINISTRATOR . '/components/' .
$extension;
break;
case 'lib':
$source = JPATH_LIBRARIES . '/' .
substr($extension, 4);
break;
case 'mod':
$source = JPATH_SITE . '/modules/' . $extension;
break;
case 'plg':
$parts = explode('_', $extension, 3);
if (\count($parts) > 2) {
$source = JPATH_PLUGINS . '/' . $parts[1] .
'/' . $parts[2];
}
break;
case 'pkg':
$source = JPATH_SITE;
break;
case 'tpl':
$source = JPATH_BASE . '/templates/' .
substr($extension, 4);
break;
}
$lang->load($extension, JPATH_ADMINISTRATOR)
|| $lang->load($extension, $source);
if (!$lang->hasKey(strtoupper($extension))) {
$lang->load($extension . '.sys',
JPATH_ADMINISTRATOR)
|| $lang->load($extension . '.sys', $source);
}
$cache[$extension] = true;
}
/**
* Get parameters to be
*
* @param string $context The context of the content
*
* @return mixed An object contains content type parameters, or null
if not found
*
* @since 3.9.0
*
* @deprecated 4.3 will be removed in 6.0
* Use the action log config model instead
* Example:
Factory::getApplication()->bootComponent('actionlogs')->getMVCFactory()
* ->createModel('ActionlogConfig',
'Administrator')->getLogContentTypeParams($context);
*/
public static function getLogContentTypeParams($context)
{
return
Factory::getApplication()->bootComponent('actionlogs')->getMVCFactory()
->createModel('ActionlogConfig',
'Administrator')->getLogContentTypeParams($context);
}
/**
* Get human readable log message for a User Action Log
*
* @param \stdClass $log A User Action log message record
* @param boolean $generateLinks Flag to disable link generation
when creating a message
*
* @return string
*
* @since 3.9.0
*/
public static function getHumanReadableLogMessage($log, $generateLinks
= true)
{
static::loadActionLogPluginsLanguage();
static $links = [];
$message = Text::_($log->message_language_key);
$messageData = json_decode($log->message, true);
// Special handling for translation extension name
if (isset($messageData['extension_name'])) {
static::loadTranslationFiles($messageData['extension_name']);
$messageData['extension_name'] =
Text::_($messageData['extension_name']);
}
// Translating application
if (isset($messageData['app'])) {
$messageData['app'] =
Text::_($messageData['app']);
}
// Translating type
if (isset($messageData['type'])) {
$messageData['type'] =
Text::_($messageData['type']);
}
// Remove links from the message template, if we should not
generate links.
if (!$generateLinks) {
$message = preg_replace('/<a
href=["\'].+?["\']>/', '', $message);
$message = str_replace('</a>', '',
$message);
}
$linkMode =
Factory::getApplication()->get('force_ssl', 0) >= 1 ?
Route::TLS_FORCE : Route::TLS_IGNORE;
foreach ($messageData as $key => $value) {
// Escape any markup in the values to prevent XSS attacks
$value = $value !== null ? htmlspecialchars($value, ENT_QUOTES,
'UTF-8') : '';
// Convert relative url to absolute url so that it is clickable
in action logs notification email
if ($generateLinks && StringHelper::strpos($value,
'index.php?') === 0) {
if (!isset($links[$value])) {
$links[$value] = Route::link('administrator',
$value, false, $linkMode, true);
}
$value = $links[$value];
}
$message = str_replace('{' . $key . '}',
$value, $message);
}
return $message;
}
/**
* Get link to an item of given content type
*
* @param string $component
* @param string $contentType
* @param integer $id
* @param string $urlVar
* @param CMSObject $object
*
* @return string Link to the content item
*
* @since 3.9.0
*/
public static function getContentTypeLink($component, $contentType,
$id, $urlVar = 'id', $object = null)
{
// Try to find the component helper.
$eName = str_replace('com_', '', $component);
$file = Path::clean(JPATH_ADMINISTRATOR . '/components/'
. $component . '/helpers/' . $eName . '.php');
if (file_exists($file)) {
$prefix = ucfirst(str_replace('com_', '',
$component));
$cName = $prefix . 'Helper';
\JLoader::register($cName, $file);
if (class_exists($cName) && \is_callable([$cName,
'getContentTypeLink'])) {
return $cName::getContentTypeLink($contentType, $id,
$object);
}
}
if (empty($urlVar)) {
$urlVar = 'id';
}
// Return default link to avoid having to implement
getContentTypeLink in most of our components
return 'index.php?option=' . $component .
'&task=' . $contentType . '.edit&' . $urlVar .
'=' . $id;
}
/**
* Load both enabled and disabled actionlog plugins language file.
*
* It is used to make sure actions log is displayed properly instead of
only language items displayed when a plugin is disabled.
*
* @return void
*
* @since 3.9.0
*/
public static function loadActionLogPluginsLanguage()
{
$lang = Factory::getLanguage();
$db = Factory::getDbo();
// Get all (both enabled and disabled) actionlog plugins
$query = $db->getQuery(true)
->select(
$db->quoteName(
[
'folder',
'element',
'params',
'extension_id',
],
[
'type',
'name',
'params',
'id',
]
)
)
->from($db->quoteName('#__extensions'))
->where($db->quoteName('type') . ' =
' . $db->quote('plugin'))
->where($db->quoteName('folder') . ' =
' . $db->quote('actionlog'))
->whereIn($db->quoteName('state'), [0, 1])
->order($db->quoteName('ordering'));
$db->setQuery($query);
try {
$rows = $db->loadObjectList();
} catch (\RuntimeException $e) {
$rows = [];
}
if (empty($rows)) {
return;
}
foreach ($rows as $row) {
$name = $row->name;
$type = $row->type;
$extension = 'Plg_' . $type . '_' . $name;
$extension = strtolower($extension);
// If language already loaded, don't load it again.
if ($lang->getPaths($extension)) {
continue;
}
$lang->load($extension, JPATH_ADMINISTRATOR)
|| $lang->load($extension, JPATH_PLUGINS . '/'
. $type . '/' . $name);
}
// Load plg_system_actionlogs too
$lang->load('plg_system_actionlogs',
JPATH_ADMINISTRATOR);
// Load plg_system_privacyconsent too
$lang->load('plg_system_privacyconsent',
JPATH_ADMINISTRATOR);
// Load plg_user_terms too
$lang->load('plg_user_terms', JPATH_ADMINISTRATOR);
// Load com_privacy too.
$lang->load('com_privacy', JPATH_ADMINISTRATOR);
}
/**
* Escapes potential characters that start a formula in a CSV value to
prevent injection attacks
*
* @param mixed $value csv field value
*
* @return mixed
*
* @since 3.9.7
*/
protected static function escapeCsvFormula($value)
{
if ($value == '') {
return $value;
}
if (\in_array($value[0], self::$characters, true)) {
$value = ' ' . $value;
}
return $value;
}
}