first commit

This commit is contained in:
2025-06-17 11:53:18 +02:00
commit 9f0f7ba12b
8804 changed files with 1369176 additions and 0 deletions

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="system" method="upgrade">
<name>plg_system_actionlogs</name>
<author>Joomla! Project</author>
<creationDate>2018-05</creationDate>
<copyright>(C) 2018 Open Source Matters, Inc.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<version>3.9.0</version>
<description>PLG_SYSTEM_ACTIONLOGS_XML_DESCRIPTION</description>
<namespace path="src">Joomla\Plugin\System\ActionLogs</namespace>
<files>
<folder>forms</folder>
<folder plugin="actionlogs">services</folder>
<folder>src</folder>
</files>
<languages>
<language tag="en-GB">language/en-GB/plg_system_actionlogs.ini</language>
<language tag="en-GB">language/en-GB/plg_system_actionlogs.sys.ini</language>
</languages>
</extension>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="actionlogs" label="PLG_SYSTEM_ACTIONLOGS_OPTIONS" addfieldprefix="Joomla\Component\Actionlogs\Administrator\Field">
<fields name="actionlogs">
<field
name="actionlogsNotify"
type="radio"
label="PLG_SYSTEM_ACTIONLOGS_NOTIFICATIONS"
layout="joomla.form.field.radio.switcher"
default="0"
filter="integer"
required="true"
>
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
<field
name="actionlogsExtensions"
type="logtype"
label="PLG_SYSTEM_ACTIONLOGS_EXTENSIONS_NOTIFICATIONS"
multiple="true"
validate="options"
layout="joomla.form.field.list-fancy-select"
showon="actionlogsNotify:1"
default="com_content"
/>
</fields>
</fieldset>
</form>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fields name="params">
<fieldset name="information" label="PLG_SYSTEM_ACTIONLOGS_OPTIONS">
<field addfieldprefix="Joomla\Component\Actionlogs\Administrator\Field"
name="Information"
type="plugininfo"
label="PLG_SYSTEM_ACTIONLOGS_INFO_LABEL"
description="PLG_SYSTEM_ACTIONLOGS_INFO_DESC"
/>
</fieldset>
</fields>
</form>

View File

@ -0,0 +1,50 @@
<?php
/**
* @package Joomla.Plugin
* @subpackage System.actionlogs
*
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
\defined('_JEXEC') or die;
use Joomla\CMS\Extension\PluginInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\User\UserFactoryInterface;
use Joomla\Database\DatabaseInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
use Joomla\Plugin\System\ActionLogs\Extension\ActionLogs;
return new class () implements ServiceProviderInterface {
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 4.4.0
*/
public function register(Container $container): void
{
$container->set(
PluginInterface::class,
function (Container $container) {
$plugin = new ActionLogs(
$container->get(DispatcherInterface::class),
(array) PluginHelper::getPlugin('system', 'actionlogs')
);
$plugin->setApplication(Factory::getApplication());
$plugin->setDatabase($container->get(DatabaseInterface::class));
$plugin->setUserFactory($container->get(UserFactoryInterface::class));
return $plugin;
}
);
}
};

View File

@ -0,0 +1,350 @@
<?php
/**
* @package Joomla.Plugins
* @subpackage System.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\Plugin\System\ActionLogs\Extension;
use Joomla\CMS\Form\Form;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\User\UserFactoryAwareTrait;
use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Database\Exception\ExecutionFailureException;
use Joomla\Database\ParameterType;
use Joomla\Event\DispatcherInterface;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
/**
* Joomla! Users Actions Logging Plugin.
*
* @since 3.9.0
*/
final class ActionLogs extends CMSPlugin
{
use DatabaseAwareTrait;
use UserFactoryAwareTrait;
/**
* Constructor.
*
* @param DispatcherInterface $dispatcher The dispatcher
* @param array $config An optional associative array of configuration settings
*
* @since 3.9.0
*/
public function __construct(DispatcherInterface $dispatcher, array $config)
{
parent::__construct($dispatcher, $config);
// Import actionlog plugin group so that these plugins will be triggered for events
PluginHelper::importPlugin('actionlog');
}
/**
* Adds additional fields to the user editing form for logs e-mail notifications
*
* @param Form $form The form to be altered.
* @param mixed $data The associated data for the form.
*
* @return boolean
*
* @since 3.9.0
*
* @throws \Exception
*/
public function onContentPrepareForm(Form $form, $data)
{
$formName = $form->getName();
$allowedFormNames = [
'com_users.profile',
'com_users.user',
];
if (!\in_array($formName, $allowedFormNames, true)) {
return true;
}
/**
* We only allow users who have Super User permission to change this setting for themselves or for other
* users who have the same Super User permission
*/
$user = $this->getApplication()->getIdentity();
if (!$user || !$user->authorise('core.admin')) {
return true;
}
// Load plugin language files.
$this->loadLanguage();
// If we are on the save command, no data is passed to $data variable, we need to get it directly from request
$jformData = $this->getApplication()->getInput()->get('jform', [], 'array');
if ($jformData && !$data) {
$data = $jformData;
}
if (\is_array($data)) {
$data = (object) $data;
}
if (empty($data->id) || !$this->getUserFactory()->loadUserById($data->id)->authorise('core.admin')) {
return true;
}
Form::addFormPath(JPATH_PLUGINS . '/' . $this->_type . '/' . $this->_name . '/forms');
if ((!PluginHelper::isEnabled('actionlog', 'joomla')) && ($this->getApplication()->isClient('administrator'))) {
$form->loadFile('information', false);
return true;
}
if (!PluginHelper::isEnabled('actionlog', 'joomla')) {
return true;
}
$form->loadFile('actionlogs', false);
return true;
}
/**
* Runs on content preparation
*
* @param string $context The context for the data
* @param object $data An object containing the data for the form.
*
* @return boolean
*
* @since 3.9.0
*/
public function onContentPrepareData($context, $data)
{
if (!\in_array($context, ['com_users.profile', 'com_users.user'])) {
return true;
}
if (\is_array($data)) {
$data = (object) $data;
}
if (empty($data->id) || !$this->getUserFactory()->loadUserById($data->id)->authorise('core.admin')) {
return true;
}
$db = $this->getDatabase();
$id = (int) $data->id;
$query = $db->getQuery(true)
->select($db->quoteName(['notify', 'extensions']))
->from($db->quoteName('#__action_logs_users'))
->where($db->quoteName('user_id') . ' = :userid')
->bind(':userid', $id, ParameterType::INTEGER);
try {
$values = $db->setQuery($query)->loadObject();
} catch (ExecutionFailureException $e) {
return false;
}
if (!$values) {
return true;
}
// Load plugin language files.
$this->loadLanguage();
$data->actionlogs = new \stdClass();
$data->actionlogs->actionlogsNotify = $values->notify;
$data->actionlogs->actionlogsExtensions = $values->extensions;
if (!HTMLHelper::isRegistered('users.actionlogsNotify')) {
HTMLHelper::register('users.actionlogsNotify', [__CLASS__, 'renderActionlogsNotify']);
}
if (!HTMLHelper::isRegistered('users.actionlogsExtensions')) {
HTMLHelper::register('users.actionlogsExtensions', [__CLASS__, 'renderActionlogsExtensions']);
}
return true;
}
/**
* Utility method to act on a user after it has been saved.
*
* @param array $user Holds the new user data.
* @param boolean $isNew True if a new user is stored.
* @param boolean $success True if user was successfully stored in the database.
* @param string $msg Message.
*
* @return void
*
* @since 3.9.0
*/
public function onUserAfterSave($user, $isNew, $success, $msg): void
{
if (!$success) {
return;
}
// Clear access rights in case user groups were changed.
$userObject = $this->getUserFactory()->loadUserById($user['id']);
$userObject->clearAccessRights();
$authorised = $userObject->authorise('core.admin');
$userid = (int) $user['id'];
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select('COUNT(*)')
->from($db->quoteName('#__action_logs_users'))
->where($db->quoteName('user_id') . ' = :userid')
->bind(':userid', $userid, ParameterType::INTEGER);
try {
$exists = (bool) $db->setQuery($query)->loadResult();
} catch (ExecutionFailureException $e) {
return;
}
$query->clear();
// If preferences don't exist, insert.
if (!$exists && $authorised && isset($user['actionlogs'])) {
$notify = (int) $user['actionlogs']['actionlogsNotify'];
$values = [':userid', ':notify'];
$bind = [$userid, $notify];
$columns = ['user_id', 'notify'];
$query->bind($values, $bind, ParameterType::INTEGER);
if (isset($user['actionlogs']['actionlogsExtensions'])) {
$values[] = ':extension';
$columns[] = 'extensions';
$extension = json_encode($user['actionlogs']['actionlogsExtensions']);
$query->bind(':extension', $extension);
}
$query->insert($db->quoteName('#__action_logs_users'))
->columns($db->quoteName($columns))
->values(implode(',', $values));
} elseif ($exists && $authorised && isset($user['actionlogs'])) {
// Update preferences.
$notify = (int) $user['actionlogs']['actionlogsNotify'];
$values = [$db->quoteName('notify') . ' = :notify'];
$query->bind(':notify', $notify, ParameterType::INTEGER);
if (isset($user['actionlogs']['actionlogsExtensions'])) {
$values[] = $db->quoteName('extensions') . ' = :extension';
$extension = json_encode($user['actionlogs']['actionlogsExtensions']);
$query->bind(':extension', $extension);
}
$query->update($db->quoteName('#__action_logs_users'))
->set($values)
->where($db->quoteName('user_id') . ' = :userid')
->bind(':userid', $userid, ParameterType::INTEGER);
} elseif ($exists && !$authorised) {
// Remove preferences if user is not authorised.
$query->delete($db->quoteName('#__action_logs_users'))
->where($db->quoteName('user_id') . ' = :userid')
->bind(':userid', $userid, ParameterType::INTEGER);
} else {
return;
}
try {
$db->setQuery($query)->execute();
} catch (ExecutionFailureException $e) {
// Do nothing.
}
}
/**
* Removes user preferences
*
* Method is called after user data is deleted from the database
*
* @param array $user Holds the user data
* @param boolean $success True if user was successfully stored in the database
* @param string $msg Message
*
* @return void
*
* @since 3.9.0
*/
public function onUserAfterDelete($user, $success, $msg): void
{
if (!$success) {
return;
}
$db = $this->getDatabase();
$userid = (int) $user['id'];
$query = $db->getQuery(true)
->delete($db->quoteName('#__action_logs_users'))
->where($db->quoteName('user_id') . ' = :userid')
->bind(':userid', $userid, ParameterType::INTEGER);
try {
$db->setQuery($query)->execute();
} catch (ExecutionFailureException $e) {
// Do nothing.
}
}
/**
* Method to render a value.
*
* @param integer|string $value The value (0 or 1).
*
* @return string The rendered value.
*
* @since 3.9.16
*/
public static function renderActionlogsNotify($value)
{
return Text::_($value ? 'JYES' : 'JNO');
}
/**
* Method to render a list of extensions.
*
* @param array|string $extensions Array of extensions or an empty string if none selected.
*
* @return string The rendered value.
*
* @since 3.9.16
*/
public static function renderActionlogsExtensions($extensions)
{
// No extensions selected.
if (!$extensions) {
return Text::_('JNONE');
}
foreach ($extensions as &$extension) {
// Load extension language files and translate extension name.
ActionlogsHelper::loadTranslationFiles($extension);
$extension = Text::_($extension);
}
return implode(', ', $extensions);
}
}