first commit
This commit is contained in:
22
plugins/system/actionlogs/actionlogs.xml
Normal file
22
plugins/system/actionlogs/actionlogs.xml
Normal 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>
|
||||
29
plugins/system/actionlogs/forms/actionlogs.xml
Normal file
29
plugins/system/actionlogs/forms/actionlogs.xml
Normal 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>
|
||||
13
plugins/system/actionlogs/forms/information.xml
Normal file
13
plugins/system/actionlogs/forms/information.xml
Normal 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>
|
||||
50
plugins/system/actionlogs/services/provider.php
Normal file
50
plugins/system/actionlogs/services/provider.php
Normal 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;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
350
plugins/system/actionlogs/src/Extension/ActionLogs.php
Normal file
350
plugins/system/actionlogs/src/Extension/ActionLogs.php
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user