From cb5ae9c69d82a991aa6be336a9513869125b785a Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Wed, 24 Aug 2022 16:32:26 +0200 Subject: [PATCH 01/18] synch extension to log with email notification --- plugins/system/actionlogs/actionlogs.php | 65 ++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/plugins/system/actionlogs/actionlogs.php b/plugins/system/actionlogs/actionlogs.php index aced528c949e9..900e15c82580d 100644 --- a/plugins/system/actionlogs/actionlogs.php +++ b/plugins/system/actionlogs/actionlogs.php @@ -10,6 +10,7 @@ defined('_JEXEC') or die; use Joomla\CMS\Cache\Cache; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\HTML\HTMLHelper; @@ -546,4 +547,68 @@ public static function renderActionlogsExtensions($extensions) return implode(', ', $extensions); } + + /** + * On Saving extensions logging method + * Method is called when an extension is being saved + * + * @param string $context The extension + * @param Table $table DataBase Table object + * @param boolean $isNew If the extension is new or not + * + * @return void + * + * @since __DEPLOY + */ + public function onExtensionAfterSave($context, $table, $isNew): void + { + if ($table->name !== 'com_actionlogs') + { + return; + } + + $params = ComponentHelper::getParams('com_actionlogs'); + $globalExt = (array) $params->get('loggable_extensions', []); + + $db = $this->db; + + $query = $db->getQuery(true) + ->select($db->quoteName(['user_id', 'notify', 'extensions'])) + ->from($db->quoteName('#__action_logs_users')); + + try + { + $values = $db->setQuery($query)->loadObjectList(); + } + catch (ExecutionFailureException $e) + { + return; + } + + foreach ($values as $item) + { + $userExt = substr($item->extensions, 2); + $userExt = substr($userExt,0 , -2); + $user = explode('","', $userExt); + $common = array_intersect($globalExt, $user); + + $extension = '["' . implode('","', $common) . '"]'; + + $query->clear() + ->update($db->quoteName('#__action_logs_users')) + ->set($db->quoteName('extensions') . ' = :extension') + ->where($db->quoteName('user_id') . ' = :userid') + ->bind(':userid', $item->user_id, ParameterType::INTEGER) + ->bind(':extension', $extension); + + try + { + $db->setQuery($query)->execute(); + } + catch (ExecutionFailureException $e) + { + // Do nothing. + } + } + } } From f9802e816c3d52e8c03768ded4b8b0eb43044755 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Wed, 24 Aug 2022 16:34:22 +0200 Subject: [PATCH 02/18] synch extension to log with email notification --- plugins/system/actionlogs/forms/actionlogs.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/system/actionlogs/forms/actionlogs.xml b/plugins/system/actionlogs/forms/actionlogs.xml index 7309cf3081ced..07840b824ed05 100644 --- a/plugins/system/actionlogs/forms/actionlogs.xml +++ b/plugins/system/actionlogs/forms/actionlogs.xml @@ -16,7 +16,7 @@ Date: Wed, 24 Aug 2022 16:36:48 +0200 Subject: [PATCH 03/18] synch extension to log with email notification --- .../src/Field/UserlogtypeField.php | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 administrator/components/com_actionlogs/src/Field/UserlogtypeField.php diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php new file mode 100644 index 0000000000000..6bf8cefe9dfb5 --- /dev/null +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -0,0 +1,74 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Actionlogs\Administrator\Field; + +use Joomla\CMS\Application\ApplicationHelper; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\Form\Field\ListField; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Text; +use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper; +use Joomla\Database\ParameterType; + +/** + * Field to load a list of all users that have logged actions + * + * @since __DEPLOY_VERSION__ + */ +class UserlogtypeField extends ListField +{ + /** + * The form field type. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $type = 'UserLogType'; + + /** + * Method to get the field options. + * + * @return array The field option objects. + * + * @since __DEPLOY_VERSION__ + */ + public function getOptions() + { + $db = $this->getDatabase(); + $user = Factory::getApplication()->getIdentity(); + $query = $db->getQuery(true) + ->select($db->quoteName('extensions')) + ->from($db->quoteName('#__action_logs_users')) + ->where($db->quoteName('user_id') . ' = :userid') + ->bind(':userid', $user->id, ParameterType::INTEGER); + + $extensions = $db->setQuery($query)->loadColumn(); + $params = ComponentHelper::getParams('com_actionlogs'); + $globalExt = $params->get('loggable_extensions', []); + $userExt = substr($extensions[0], 2); + $userExt = substr($userExt,0 , -2); + $userExt = explode('","', $userExt); + $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); + + $options = []; + + foreach ($common as $extension) { + ActionlogsHelper::loadTranslationFiles($extension); + $extensionName = Text::_($extension); + $options[ApplicationHelper::stringURLSafe($extensionName) . '_' . $extension] = HTMLHelper::_('select.option', $extension, $extensionName); + } + + ksort($options); + + return array_merge(parent::getOptions(), array_values($options)); + } +} From 5714980f99215c44f6ab3d53830ea88eb0c1c114 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Thu, 25 Aug 2022 08:21:10 +0200 Subject: [PATCH 04/18] Update administrator/components/com_actionlogs/src/Field/UserlogtypeField.php Co-authored-by: heelc29 <66922325+heelc29@users.noreply.github.com> --- .../components/com_actionlogs/src/Field/UserlogtypeField.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php index 6bf8cefe9dfb5..f8ec6d42a1165 100644 --- a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -4,7 +4,8 @@ * @package Joomla.Administrator * @subpackage com_actionlogs * - * @copyright (C) 2018 Open Source Matters, Inc. + * @copyright (C) 2022 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt */ From cbca7ed85ad0c966047bec6133fc5baa483227e0 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Thu, 25 Aug 2022 08:21:20 +0200 Subject: [PATCH 05/18] Update administrator/components/com_actionlogs/src/Field/UserlogtypeField.php Co-authored-by: heelc29 <66922325+heelc29@users.noreply.github.com> --- .../components/com_actionlogs/src/Field/UserlogtypeField.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php index f8ec6d42a1165..b41a75ef0c1ec 100644 --- a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -56,7 +56,8 @@ public function getOptions() $params = ComponentHelper::getParams('com_actionlogs'); $globalExt = $params->get('loggable_extensions', []); $userExt = substr($extensions[0], 2); - $userExt = substr($userExt,0 , -2); + $userExt = substr($userExt, 0, -2); + $userExt = explode('","', $userExt); $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); From 0b57a124cd110539b86eb063fcc6fba3d14fd4b9 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Thu, 25 Aug 2022 08:21:36 +0200 Subject: [PATCH 06/18] Update plugins/system/actionlogs/actionlogs.php Co-authored-by: heelc29 <66922325+heelc29@users.noreply.github.com> --- plugins/system/actionlogs/actionlogs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/system/actionlogs/actionlogs.php b/plugins/system/actionlogs/actionlogs.php index 900e15c82580d..eaae3dd8f42c9 100644 --- a/plugins/system/actionlogs/actionlogs.php +++ b/plugins/system/actionlogs/actionlogs.php @@ -558,7 +558,7 @@ public static function renderActionlogsExtensions($extensions) * * @return void * - * @since __DEPLOY + * @since __DEPLOY_VERSION__ */ public function onExtensionAfterSave($context, $table, $isNew): void { From 55d5916ba0dd45a52ecf8648f79f5f8bb0b6c7d2 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Thu, 25 Aug 2022 08:21:46 +0200 Subject: [PATCH 07/18] Update plugins/system/actionlogs/actionlogs.php Co-authored-by: heelc29 <66922325+heelc29@users.noreply.github.com> --- plugins/system/actionlogs/actionlogs.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/system/actionlogs/actionlogs.php b/plugins/system/actionlogs/actionlogs.php index eaae3dd8f42c9..ab7f58d7b948b 100644 --- a/plugins/system/actionlogs/actionlogs.php +++ b/plugins/system/actionlogs/actionlogs.php @@ -588,8 +588,8 @@ public function onExtensionAfterSave($context, $table, $isNew): void foreach ($values as $item) { $userExt = substr($item->extensions, 2); - $userExt = substr($userExt,0 , -2); - $user = explode('","', $userExt); + $userExt = substr($userExt, 0, -2); + $user = explode('","', $userExt); $common = array_intersect($globalExt, $user); $extension = '["' . implode('","', $common) . '"]'; From 10cb7a22ac0a1eb6cf101ca4628ec0a737375359 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Thu, 25 Aug 2022 09:25:41 +0200 Subject: [PATCH 08/18] Update administrator/components/com_actionlogs/src/Field/UserlogtypeField.php Co-authored-by: heelc29 <66922325+heelc29@users.noreply.github.com> --- .../components/com_actionlogs/src/Field/UserlogtypeField.php | 1 - 1 file changed, 1 deletion(-) diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php index b41a75ef0c1ec..3435f90d31201 100644 --- a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -5,7 +5,6 @@ * @subpackage com_actionlogs * * @copyright (C) 2022 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt */ From 282e5d6e4051d94d9381ad95aefcb964dde13a82 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Thu, 25 Aug 2022 09:25:49 +0200 Subject: [PATCH 09/18] Update administrator/components/com_actionlogs/src/Field/UserlogtypeField.php Co-authored-by: heelc29 <66922325+heelc29@users.noreply.github.com> --- .../components/com_actionlogs/src/Field/UserlogtypeField.php | 1 - 1 file changed, 1 deletion(-) diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php index 3435f90d31201..97fc602980ee4 100644 --- a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -56,7 +56,6 @@ public function getOptions() $globalExt = $params->get('loggable_extensions', []); $userExt = substr($extensions[0], 2); $userExt = substr($userExt, 0, -2); - $userExt = explode('","', $userExt); $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); From 1c7edf415b179616190c35a3d9fbaeecd99328cf Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Sat, 3 Sep 2022 08:08:44 +0200 Subject: [PATCH 10/18] check --- plugins/system/actionlogs/actionlogs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/system/actionlogs/actionlogs.php b/plugins/system/actionlogs/actionlogs.php index ab7f58d7b948b..82cc6389d9859 100644 --- a/plugins/system/actionlogs/actionlogs.php +++ b/plugins/system/actionlogs/actionlogs.php @@ -562,7 +562,7 @@ public static function renderActionlogsExtensions($extensions) */ public function onExtensionAfterSave($context, $table, $isNew): void { - if ($table->name !== 'com_actionlogs') + if ($context !== 'com_config.component' || $table->name !== 'com_actionlogs') { return; } From 87372745fae5f619bc8fd38410c091fdc0c8e683 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Mon, 1 May 2023 08:46:40 +0200 Subject: [PATCH 11/18] 4.3 --- plugins/system/actionlogs/actionlogs.php | 1079 ++++++++++------------ 1 file changed, 508 insertions(+), 571 deletions(-) diff --git a/plugins/system/actionlogs/actionlogs.php b/plugins/system/actionlogs/actionlogs.php index 82cc6389d9859..628f0a830c090 100644 --- a/plugins/system/actionlogs/actionlogs.php +++ b/plugins/system/actionlogs/actionlogs.php @@ -5,9 +5,9 @@ * * @copyright (C) 2018 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt - */ -defined('_JEXEC') or die; + * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace + */ use Joomla\CMS\Cache\Cache; use Joomla\CMS\Component\ComponentHelper; @@ -22,6 +22,10 @@ use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + /** * Joomla! Users Actions Logging Plugin. * @@ -29,524 +33,465 @@ */ class PlgSystemActionLogs extends CMSPlugin { - /** - * @var \Joomla\CMS\Application\CMSApplication - * - * @since 3.9.0 - */ - protected $app; - - /** - * @var \Joomla\Database\DatabaseDriver - * - * @since 3.9.0 - */ - protected $db; - - /** - * Constructor. - * - * @param object $subject The object to observe. - * @param array $config An optional associative array of configuration settings. - * - * @since 3.9.0 - */ - public function __construct(&$subject, $config) - { - parent::__construct($subject, $config); - - // Import actionlog plugin group so that these plugins will be triggered for events - PluginHelper::importPlugin('actionlog'); - } - - /** - * Listener for the `onAfterInitialise` event - * - * @return void - * - * @since 4.0.0 - */ - public function onAfterInitialise() - { - // Load plugin language files. - $this->loadLanguage(); - } - - /** - * 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 = Factory::getUser(); - - if (!$user->authorise('core.admin')) - { - return true; - } - - // If we are on the save command, no data is passed to $data variable, we need to get it directly from request - $jformData = $this->app->input->get('jform', [], 'array'); - - if ($jformData && !$data) - { - $data = $jformData; - } - - if (is_array($data)) - { - $data = (object) $data; - } - - if (empty($data->id) || !User::getInstance($data->id)->authorise('core.admin')) - { - return true; - } - - Form::addFormPath(__DIR__ . '/forms'); - - if ((!PluginHelper::isEnabled('actionlog', 'joomla')) && (Factory::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 (!User::getInstance($data->id)->authorise('core.admin')) - { - return true; - } - - $db = $this->db; - $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; - } - - $data->actionlogs = new stdClass; - $data->actionlogs->actionlogsNotify = $values->notify; - $data->actionlogs->actionlogsExtensions = $values->extensions; - - if (!HTMLHelper::isRegistered('users.actionlogsNotify')) - { - HTMLHelper::register('users.actionlogsNotify', array(__CLASS__, 'renderActionlogsNotify')); - } - - if (!HTMLHelper::isRegistered('users.actionlogsExtensions')) - { - HTMLHelper::register('users.actionlogsExtensions', array(__CLASS__, 'renderActionlogsExtensions')); - } - - return true; - } - - /** - * Runs after the HTTP response has been sent to the client and delete log records older than certain days - * - * @return void - * - * @since 3.9.0 - */ - public function onAfterRespond() - { - $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0); - - if ($daysToDeleteAfter <= 0) - { - return; - } - - // The delete frequency will be once per day - $deleteFrequency = 3600 * 24; - - // Do we need to run? Compare the last run timestamp stored in the plugin's options with the current - // timestamp. If the difference is greater than the cache timeout we shall not execute again. - $now = time(); - $last = (int) $this->params->get('lastrun', 0); - - if (abs($now - $last) < $deleteFrequency) - { - return; - } - - // Update last run status - $this->params->set('lastrun', $now); - - $db = $this->db; - $params = $this->params->toString('JSON'); - $query = $db->getQuery(true) - ->update($db->quoteName('#__extensions')) - ->set($db->quoteName('params') . ' = :params') - ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) - ->where($db->quoteName('element') . ' = ' . $db->quote('actionlogs')) - ->bind(':params', $params); - - try - { - // Lock the tables to prevent multiple plugin executions causing a race condition - $db->lockTable('#__extensions'); - } - catch (Exception $e) - { - // If we can't lock the tables it's too risky to continue execution - return; - } - - try - { - // Update the plugin parameters - $result = $db->setQuery($query)->execute(); - - $this->clearCacheGroups(['com_plugins'], [0, 1]); - } - catch (Exception $exc) - { - // If we failed to execute - $db->unlockTables(); - $result = false; - } - - try - { - // Unlock the tables after writing - $db->unlockTables(); - } - catch (Exception $e) - { - // If we can't lock the tables assume we have somehow failed - $result = false; - } - - // Abort on failure - if (!$result) - { - return; - } - - $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0); - $now = Factory::getDate()->toSql(); - - if ($daysToDeleteAfter > 0) - { - $days = -1 * $daysToDeleteAfter; - - $query->clear() - ->delete($db->quoteName('#__action_logs')) - ->where($db->quoteName('log_date') . ' < ' . $query->dateAdd($db->quote($now), $days, 'DAY')); - - $db->setQuery($query); - - try - { - $db->execute(); - } - catch (RuntimeException $e) - { - // Ignore it - return; - } - } - } - - /** - * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp. - * - * @param array $clearGroups The cache groups to clean - * @param array $cacheClients The cache clients (site, admin) to clean - * - * @return void - * - * @since 3.9.0 - */ - private function clearCacheGroups(array $clearGroups, array $cacheClients = [0, 1]) - { - foreach ($clearGroups as $group) - { - foreach ($cacheClients as $clientId) - { - try - { - $options = [ - 'defaultgroup' => $group, - 'cachebase' => $clientId ? JPATH_ADMINISTRATOR . '/cache' : - Factory::getApplication()->get('cache_path', JPATH_SITE . '/cache'), - ]; - - $cache = Cache::getInstance('callback', $options); - $cache->clean(); - } - catch (Exception $e) - { - // Ignore it - } - } - } - } - - /** - * 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 = new User($user['id']); - $userObject->clearAccessRights(); - - $authorised = $userObject->authorise('core.admin'); - $userid = (int) $user['id']; - $db = $this->db; - - $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->db; - $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'); - } - - // Load the helper. - JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php'); - - foreach ($extensions as &$extension) - { - // Load extension language files and translate extension name. - ActionlogsHelper::loadTranslationFiles($extension); - $extension = Text::_($extension); - } - - return implode(', ', $extensions); - } + /** + * @var \Joomla\CMS\Application\CMSApplication + * + * @since 3.9.0 + */ + protected $app; + + /** + * @var \Joomla\Database\DatabaseDriver + * + * @since 3.9.0 + */ + protected $db; + + /** + * Constructor. + * + * @param object $subject The object to observe. + * @param array $config An optional associative array of configuration settings. + * + * @since 3.9.0 + */ + public function __construct(&$subject, $config) + { + parent::__construct($subject, $config); + + // Import actionlog plugin group so that these plugins will be triggered for events + PluginHelper::importPlugin('actionlog'); + } + + /** + * Listener for the `onAfterInitialise` event + * + * @return void + * + * @since 4.0.0 + */ + public function onAfterInitialise() + { + // Load plugin language files. + $this->loadLanguage(); + } + + /** + * 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 = Factory::getUser(); + + if (!$user->authorise('core.admin')) { + return true; + } + + // If we are on the save command, no data is passed to $data variable, we need to get it directly from request + $jformData = $this->app->getInput()->get('jform', [], 'array'); + + if ($jformData && !$data) { + $data = $jformData; + } + + if (is_array($data)) { + $data = (object) $data; + } + + if (empty($data->id) || !User::getInstance($data->id)->authorise('core.admin')) { + return true; + } + + Form::addFormPath(__DIR__ . '/forms'); + + if ((!PluginHelper::isEnabled('actionlog', 'joomla')) && (Factory::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 (!User::getInstance($data->id)->authorise('core.admin')) { + return true; + } + + $db = $this->db; + $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; + } + + $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; + } + + /** + * Runs after the HTTP response has been sent to the client and delete log records older than certain days + * + * @return void + * + * @since 3.9.0 + */ + public function onAfterRespond() + { + $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0); + + if ($daysToDeleteAfter <= 0) { + return; + } + + // The delete frequency will be once per day + $deleteFrequency = 3600 * 24; + + // Do we need to run? Compare the last run timestamp stored in the plugin's options with the current + // timestamp. If the difference is greater than the cache timeout we shall not execute again. + $now = time(); + $last = (int) $this->params->get('lastrun', 0); + + if (abs($now - $last) < $deleteFrequency) { + return; + } + + // Update last run status + $this->params->set('lastrun', $now); + + $db = $this->db; + $params = $this->params->toString('JSON'); + $query = $db->getQuery(true) + ->update($db->quoteName('#__extensions')) + ->set($db->quoteName('params') . ' = :params') + ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) + ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) + ->where($db->quoteName('element') . ' = ' . $db->quote('actionlogs')) + ->bind(':params', $params); + + try { + // Lock the tables to prevent multiple plugin executions causing a race condition + $db->lockTable('#__extensions'); + } catch (Exception $e) { + // If we can't lock the tables it's too risky to continue execution + return; + } + + try { + // Update the plugin parameters + $result = $db->setQuery($query)->execute(); + + $this->clearCacheGroups(['com_plugins'], [0, 1]); + } catch (Exception $exc) { + // If we failed to execute + $db->unlockTables(); + $result = false; + } + + try { + // Unlock the tables after writing + $db->unlockTables(); + } catch (Exception $e) { + // If we can't lock the tables assume we have somehow failed + $result = false; + } + + // Abort on failure + if (!$result) { + return; + } + + $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0); + $now = Factory::getDate()->toSql(); + + if ($daysToDeleteAfter > 0) { + $days = -1 * $daysToDeleteAfter; + + $query->clear() + ->delete($db->quoteName('#__action_logs')) + ->where($db->quoteName('log_date') . ' < ' . $query->dateAdd($db->quote($now), $days, 'DAY')); + + $db->setQuery($query); + + try { + $db->execute(); + } catch (RuntimeException $e) { + // Ignore it + return; + } + } + } + + /** + * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp. + * + * @param array $clearGroups The cache groups to clean + * @param array $cacheClients The cache clients (site, admin) to clean + * + * @return void + * + * @since 3.9.0 + */ + private function clearCacheGroups(array $clearGroups, array $cacheClients = [0, 1]) + { + foreach ($clearGroups as $group) { + foreach ($cacheClients as $clientId) { + try { + $options = [ + 'defaultgroup' => $group, + 'cachebase' => $clientId ? JPATH_ADMINISTRATOR . '/cache' : + Factory::getApplication()->get('cache_path', JPATH_SITE . '/cache'), + ]; + + $cache = Cache::getInstance('callback', $options); + $cache->clean(); + } catch (Exception $e) { + // Ignore it + } + } + } + } + + /** + * 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 = new User($user['id']); + $userObject->clearAccessRights(); + + $authorised = $userObject->authorise('core.admin'); + $userid = (int) $user['id']; + $db = $this->db; + + $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->db; + $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'); + } + + // Load the helper. + JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php'); + + foreach ($extensions as &$extension) { + // Load extension language files and translate extension name. + ActionlogsHelper::loadTranslationFiles($extension); + $extension = Text::_($extension); + } + + return implode(', ', $extensions); + } /** * On Saving extensions logging method @@ -560,55 +505,47 @@ public static function renderActionlogsExtensions($extensions) * * @since __DEPLOY_VERSION__ */ - public function onExtensionAfterSave($context, $table, $isNew): void - { - if ($context !== 'com_config.component' || $table->name !== 'com_actionlogs') - { - return; - } - - $params = ComponentHelper::getParams('com_actionlogs'); - $globalExt = (array) $params->get('loggable_extensions', []); - - $db = $this->db; - - $query = $db->getQuery(true) - ->select($db->quoteName(['user_id', 'notify', 'extensions'])) - ->from($db->quoteName('#__action_logs_users')); - - try - { - $values = $db->setQuery($query)->loadObjectList(); - } - catch (ExecutionFailureException $e) - { - return; - } - - foreach ($values as $item) - { - $userExt = substr($item->extensions, 2); - $userExt = substr($userExt, 0, -2); - $user = explode('","', $userExt); - $common = array_intersect($globalExt, $user); - - $extension = '["' . implode('","', $common) . '"]'; - - $query->clear() - ->update($db->quoteName('#__action_logs_users')) - ->set($db->quoteName('extensions') . ' = :extension') - ->where($db->quoteName('user_id') . ' = :userid') - ->bind(':userid', $item->user_id, ParameterType::INTEGER) - ->bind(':extension', $extension); - - try - { - $db->setQuery($query)->execute(); - } - catch (ExecutionFailureException $e) - { - // Do nothing. - } - } - } + public function onExtensionAfterSave($context, $table, $isNew): void + { + if ($context !== 'com_config.component' || $table->name !== 'com_actionlogs') { + return; + } + + $params = ComponentHelper::getParams('com_actionlogs'); + $globalExt = (array) $params->get('loggable_extensions', []); + + $db = $this->db; + + $query = $db->getQuery(true) + ->select($db->quoteName(['user_id', 'notify', 'extensions'])) + ->from($db->quoteName('#__action_logs_users')); + + try { + $values = $db->setQuery($query)->loadObjectList(); + } catch (ExecutionFailureException $e) { + return; + } + + foreach ($values as $item) { + $userExt = substr($item->extensions, 2); + $userExt = substr($userExt, 0, -2); + $user = explode('","', $userExt); + $common = array_intersect($globalExt, $user); + + $extension = '["' . implode('","', $common) . '"]'; + + $query->clear() + ->update($db->quoteName('#__action_logs_users')) + ->set($db->quoteName('extensions') . ' = :extension') + ->where($db->quoteName('user_id') . ' = :userid') + ->bind(':userid', $item->user_id, ParameterType::INTEGER) + ->bind(':extension', $extension); + + try { + $db->setQuery($query)->execute(); + } catch (ExecutionFailureException $e) { + // Do nothing. + } + } + } } From 1de5a7dbee4e907234df20606aea62cab398335d Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Sat, 16 Sep 2023 09:43:28 +0200 Subject: [PATCH 12/18] confllict --- plugins/system/actionlogs/actionlogs.php | 552 ----------------------- 1 file changed, 552 deletions(-) delete mode 100644 plugins/system/actionlogs/actionlogs.php diff --git a/plugins/system/actionlogs/actionlogs.php b/plugins/system/actionlogs/actionlogs.php deleted file mode 100644 index 88c03adac41c1..0000000000000 --- a/plugins/system/actionlogs/actionlogs.php +++ /dev/null @@ -1,552 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - - * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace - */ - -use Joomla\CMS\Cache\Cache; -use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Factory; -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\User; -use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper; -use Joomla\Database\Exception\ExecutionFailureException; -use Joomla\Database\ParameterType; - -// phpcs:disable PSR1.Files.SideEffects -\defined('_JEXEC') or die; -// phpcs:enable PSR1.Files.SideEffects - -/** - * Joomla! Users Actions Logging Plugin. - * - * @since 3.9.0 - */ -class PlgSystemActionLogs extends CMSPlugin -{ - /** - * @var \Joomla\CMS\Application\CMSApplication - * - * @since 3.9.0 - */ - protected $app; - - /** - * @var \Joomla\Database\DatabaseDriver - * - * @since 3.9.0 - */ - protected $db; - - /** - * Constructor. - * - * @param object $subject The object to observe. - * @param array $config An optional associative array of configuration settings. - * - * @since 3.9.0 - */ - public function __construct(&$subject, $config) - { - parent::__construct($subject, $config); - - // Import actionlog plugin group so that these plugins will be triggered for events - PluginHelper::importPlugin('actionlog'); - } - - /** - * Listener for the `onAfterInitialise` event - * - * @return void - * - * @since 4.0.0 - */ - public function onAfterInitialise() - { - // Load plugin language files. - $this->loadLanguage(); - } - - /** - * 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 = Factory::getUser(); - - if (!$user->authorise('core.admin')) { - return true; - } - - // If we are on the save command, no data is passed to $data variable, we need to get it directly from request - $jformData = $this->app->getInput()->get('jform', [], 'array'); - - if ($jformData && !$data) { - $data = $jformData; - } - - if (is_array($data)) { - $data = (object) $data; - } - - if (empty($data->id) || !User::getInstance($data->id)->authorise('core.admin')) { - return true; - } - - Form::addFormPath(__DIR__ . '/forms'); - - if ((!PluginHelper::isEnabled('actionlog', 'joomla')) && (Factory::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 (!User::getInstance($data->id)->authorise('core.admin')) { - return true; - } - - $db = $this->db; - $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; - } - - $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; - } - - /** - * Runs after the HTTP response has been sent to the client and delete log records older than certain days - * - * @return void - * - * @since 3.9.0 - */ - public function onAfterRespond() - { - $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0); - - if ($daysToDeleteAfter <= 0) { - return; - } - - // The delete frequency will be once per day - $deleteFrequency = 3600 * 24; - - // Do we need to run? Compare the last run timestamp stored in the plugin's options with the current - // timestamp. If the difference is greater than the cache timeout we shall not execute again. - $now = time(); - $last = (int) $this->params->get('lastrun', 0); - - if (abs($now - $last) < $deleteFrequency) { - return; - } - - // Update last run status - $this->params->set('lastrun', $now); - - $db = $this->db; - $params = $this->params->toString('JSON'); - $query = $db->getQuery(true) - ->update($db->quoteName('#__extensions')) - ->set($db->quoteName('params') . ' = :params') - ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) - ->where($db->quoteName('element') . ' = ' . $db->quote('actionlogs')) - ->bind(':params', $params); - - try { - // Lock the tables to prevent multiple plugin executions causing a race condition - $db->lockTable('#__extensions'); - } catch (Exception $e) { - // If we can't lock the tables it's too risky to continue execution - return; - } - - try { - // Update the plugin parameters - $result = $db->setQuery($query)->execute(); - - $this->clearCacheGroups(['com_plugins'], [0, 1]); - } catch (Exception $exc) { - // If we failed to execute - $db->unlockTables(); - $result = false; - } - - try { - // Unlock the tables after writing - $db->unlockTables(); - } catch (Exception $e) { - // If we can't lock the tables assume we have somehow failed - $result = false; - } - - // Abort on failure - if (!$result) { - return; - } - - $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0); - $now = Factory::getDate()->toSql(); - - if ($daysToDeleteAfter > 0) { - $days = -1 * $daysToDeleteAfter; - - $query->clear() - ->delete($db->quoteName('#__action_logs')) - ->where($db->quoteName('log_date') . ' < ' . $query->dateAdd($db->quote($now), $days, 'DAY')); - - $db->setQuery($query); - - try { - $db->execute(); - } catch (RuntimeException $e) { - // Ignore it - return; - } - } - } - - /** - * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp. - * - * @param array $clearGroups The cache groups to clean - * @param array $cacheClients The cache clients (site, admin) to clean - * - * @return void - * - * @since 3.9.0 - */ - private function clearCacheGroups(array $clearGroups, array $cacheClients = [0, 1]) - { - foreach ($clearGroups as $group) { - foreach ($cacheClients as $clientId) { - try { - $options = [ - 'defaultgroup' => $group, - 'cachebase' => $clientId ? JPATH_ADMINISTRATOR . '/cache' : - Factory::getApplication()->get('cache_path', JPATH_SITE . '/cache'), - ]; - - $cache = Cache::getInstance('callback', $options); - $cache->clean(); - } catch (Exception $e) { - // Ignore it - } - } - } - } - - /** - * 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 = new User($user['id']); - $userObject->clearAccessRights(); - - $authorised = $userObject->authorise('core.admin'); - $userid = (int) $user['id']; - $db = $this->db; - - $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->db; - $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'); - } - - // Load the helper. - JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php'); - - foreach ($extensions as &$extension) { - // Load extension language files and translate extension name. - ActionlogsHelper::loadTranslationFiles($extension); - $extension = Text::_($extension); - } - - return implode(', ', $extensions); - } - - /** - * On Saving extensions logging method - * Method is called when an extension is being saved - * - * @param string $context The extension - * @param Table $table DataBase Table object - * @param boolean $isNew If the extension is new or not - * - * @return void - * - * @since __DEPLOY_VERSION__ - */ - public function onExtensionAfterSave($context, $table, $isNew): void - { - if ($context !== 'com_config.component' || $table->name !== 'com_actionlogs') { - return; - } - - $params = ComponentHelper::getParams('com_actionlogs'); - $globalExt = (array) $params->get('loggable_extensions', []); - - $db = $this->db; - - $query = $db->getQuery(true) - ->select($db->quoteName(['user_id', 'notify', 'extensions'])) - ->from($db->quoteName('#__action_logs_users')); - - try { - $values = $db->setQuery($query)->loadObjectList(); - } catch (ExecutionFailureException $e) { - return; - } - - foreach ($values as $item) { - $userExt = substr($item->extensions, 2); - $userExt = substr($userExt, 0, -2); - $user = explode('","', $userExt); - $common = array_intersect($globalExt, $user); - - $extension = '["' . implode('","', $common) . '"]'; - - $query->clear() - ->update($db->quoteName('#__action_logs_users')) - ->set($db->quoteName('extensions') . ' = :extension') - ->where($db->quoteName('user_id') . ' = :userid') - ->bind(':userid', $item->user_id, ParameterType::INTEGER) - ->bind(':extension', $extension); - - try { - $db->setQuery($query)->execute(); - } catch (ExecutionFailureException $e) { - // Do nothing. - } - } - } -} From 351c99c62d72c24524b0e468680e43488b375f49 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Sat, 16 Sep 2023 09:50:57 +0200 Subject: [PATCH 13/18] move --- .../actionlogs/src/Extension/ActionLogs.php | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/plugins/system/actionlogs/src/Extension/ActionLogs.php b/plugins/system/actionlogs/src/Extension/ActionLogs.php index 22e0a8c1d14f2..7fb901d01f257 100644 --- a/plugins/system/actionlogs/src/Extension/ActionLogs.php +++ b/plugins/system/actionlogs/src/Extension/ActionLogs.php @@ -10,6 +10,7 @@ namespace Joomla\Plugin\System\ActionLogs\Extension; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Form\Form; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; @@ -354,4 +355,60 @@ public static function renderActionlogsExtensions($extensions) return implode(', ', $extensions); } + + /** + * On Saving extensions logging method + * Method is called when an extension is being saved + * + * @param string $context The extension + * @param Table $table DataBase Table object + * @param boolean $isNew If the extension is new or not + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function onExtensionAfterSave($context, $table, $isNew): void + { + if ($context !== 'com_config.component' || $table->name !== 'com_actionlogs') { + return; + } + + $params = ComponentHelper::getParams('com_actionlogs'); + $globalExt = (array) $params->get('loggable_extensions', []); + + $db = $this->getDatabase(); + + $query = $db->getQuery(true) + ->select($db->quoteName(['user_id', 'notify', 'extensions'])) + ->from($db->quoteName('#__action_logs_users')); + + try { + $values = $db->setQuery($query)->loadObjectList(); + } catch (ExecutionFailureException $e) { + return; + } + + foreach ($values as $item) { + $userExt = substr($item->extensions, 2); + $userExt = substr($userExt, 0, -2); + $user = explode('","', $userExt); + $common = array_intersect($globalExt, $user); + + $extension = '["' . implode('","', $common) . '"]'; + + $query->clear() + ->update($db->quoteName('#__action_logs_users')) + ->set($db->quoteName('extensions') . ' = :extension') + ->where($db->quoteName('user_id') . ' = :userid') + ->bind(':userid', $item->user_id, ParameterType::INTEGER) + ->bind(':extension', $extension); + + try { + $db->setQuery($query)->execute(); + } catch (ExecutionFailureException $e) { + // Do nothing. + } + } + } } From b87ea5b4e120a4352f134e1fdc0a3278787c188a Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Sat, 16 Sep 2023 10:47:48 +0200 Subject: [PATCH 14/18] synch --- .../com_actionlogs/src/Field/UserlogtypeField.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php index 97fc602980ee4..969fed70edc5e 100644 --- a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -52,13 +52,17 @@ public function getOptions() ->bind(':userid', $user->id, ParameterType::INTEGER); $extensions = $db->setQuery($query)->loadColumn(); + $userExt = []; $params = ComponentHelper::getParams('com_actionlogs'); $globalExt = $params->get('loggable_extensions', []); - $userExt = substr($extensions[0], 2); - $userExt = substr($userExt, 0, -2); - $userExt = explode('","', $userExt); - $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); + if (!empty($extensions)) { + $userExt = substr($extensions[0], 2); + $userExt = substr($userExt, 0, -2); + $userExt = explode('","', $userExt); + } + + $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); $options = []; foreach ($common as $extension) { From c290806deef0716ecf4554172e8e596486bb5917 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Sat, 16 Sep 2023 10:57:14 +0200 Subject: [PATCH 15/18] LF From 6dec70f6184e7a2d6e5ba65b2afe3fbbb66920a3 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Sun, 17 Sep 2023 08:20:28 +0200 Subject: [PATCH 16/18] cs --- .../components/com_actionlogs/src/Field/UserlogtypeField.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php index 969fed70edc5e..0751c187e0928 100644 --- a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -62,12 +62,12 @@ public function getOptions() $userExt = explode('","', $userExt); } - $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); + $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); $options = []; foreach ($common as $extension) { ActionlogsHelper::loadTranslationFiles($extension); - $extensionName = Text::_($extension); + $extensionName = Text::_($extension); $options[ApplicationHelper::stringURLSafe($extensionName) . '_' . $extension] = HTMLHelper::_('select.option', $extension, $extensionName); } From be0a10a502b070d67ff8edec080ae816a08d2ec4 Mon Sep 17 00:00:00 2001 From: alikon Date: Sun, 17 Sep 2023 10:08:59 +0200 Subject: [PATCH 17/18] cs --- .../src/Field/UserlogtypeField.php | 156 +++++++++--------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php index 0751c187e0928..985c81c7a5682 100644 --- a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -1,78 +1,78 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -namespace Joomla\Component\Actionlogs\Administrator\Field; - -use Joomla\CMS\Application\ApplicationHelper; -use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Factory; -use Joomla\CMS\Form\Field\ListField; -use Joomla\CMS\HTML\HTMLHelper; -use Joomla\CMS\Language\Text; -use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper; -use Joomla\Database\ParameterType; - -/** - * Field to load a list of all users that have logged actions - * - * @since __DEPLOY_VERSION__ - */ -class UserlogtypeField extends ListField -{ - /** - * The form field type. - * - * @var string - * @since __DEPLOY_VERSION__ - */ - protected $type = 'UserLogType'; - - /** - * Method to get the field options. - * - * @return array The field option objects. - * - * @since __DEPLOY_VERSION__ - */ - public function getOptions() - { - $db = $this->getDatabase(); - $user = Factory::getApplication()->getIdentity(); - $query = $db->getQuery(true) - ->select($db->quoteName('extensions')) - ->from($db->quoteName('#__action_logs_users')) - ->where($db->quoteName('user_id') . ' = :userid') - ->bind(':userid', $user->id, ParameterType::INTEGER); - - $extensions = $db->setQuery($query)->loadColumn(); - $userExt = []; - $params = ComponentHelper::getParams('com_actionlogs'); - $globalExt = $params->get('loggable_extensions', []); - - if (!empty($extensions)) { - $userExt = substr($extensions[0], 2); - $userExt = substr($userExt, 0, -2); - $userExt = explode('","', $userExt); - } - - $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); - $options = []; - - foreach ($common as $extension) { - ActionlogsHelper::loadTranslationFiles($extension); - $extensionName = Text::_($extension); - $options[ApplicationHelper::stringURLSafe($extensionName) . '_' . $extension] = HTMLHelper::_('select.option', $extension, $extensionName); - } - - ksort($options); - - return array_merge(parent::getOptions(), array_values($options)); - } -} + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Actionlogs\Administrator\Field; + +use Joomla\CMS\Application\ApplicationHelper; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\Form\Field\ListField; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Text; +use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper; +use Joomla\Database\ParameterType; + +/** + * Field to load a list of all users that have logged actions + * + * @since __DEPLOY_VERSION__ + */ +class UserlogtypeField extends ListField +{ + /** + * The form field type. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $type = 'UserLogType'; + + /** + * Method to get the field options. + * + * @return array The field option objects. + * + * @since __DEPLOY_VERSION__ + */ + public function getOptions() + { + $db = $this->getDatabase(); + $user = Factory::getApplication()->getIdentity(); + $query = $db->getQuery(true) + ->select($db->quoteName('extensions')) + ->from($db->quoteName('#__action_logs_users')) + ->where($db->quoteName('user_id') . ' = :userid') + ->bind(':userid', $user->id, ParameterType::INTEGER); + + $extensions = $db->setQuery($query)->loadColumn(); + $userExt = []; + $params = ComponentHelper::getParams('com_actionlogs'); + $globalExt = $params->get('loggable_extensions', []); + + if (!empty($extensions)) { + $userExt = substr($extensions[0], 2); + $userExt = substr($userExt, 0, -2); + $userExt = explode('","', $userExt); + } + + $common = array_merge($globalExt, array_intersect($globalExt, $userExt)); + $options = []; + + foreach ($common as $extension) { + ActionlogsHelper::loadTranslationFiles($extension); + $extensionName = Text::_($extension); + $options[ApplicationHelper::stringURLSafe($extensionName) . '_' . $extension] = HTMLHelper::_('select.option', $extension, $extensionName); + } + + ksort($options); + + return array_merge(parent::getOptions(), array_values($options)); + } +} From 9c973a3b7dddba07b8aa8398869b4cc3d7836235 Mon Sep 17 00:00:00 2001 From: Nicola Galgano Date: Mon, 18 Sep 2023 09:53:22 +0200 Subject: [PATCH 18/18] json_encode --- plugins/system/actionlogs/src/Extension/ActionLogs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/system/actionlogs/src/Extension/ActionLogs.php b/plugins/system/actionlogs/src/Extension/ActionLogs.php index 7fb901d01f257..8fc71c8224866 100644 --- a/plugins/system/actionlogs/src/Extension/ActionLogs.php +++ b/plugins/system/actionlogs/src/Extension/ActionLogs.php @@ -395,7 +395,7 @@ public function onExtensionAfterSave($context, $table, $isNew): void $user = explode('","', $userExt); $common = array_intersect($globalExt, $user); - $extension = '["' . implode('","', $common) . '"]'; + $extension = json_encode(array_values($common)); $query->clear() ->update($db->quoteName('#__action_logs_users'))