J3.x

J3.x:Faites votre propre Plugin Action Log

From Joomla! Documentation

Revision as of 13:26, 12 February 2021 by FuzzyBot (talk | contribs) (Updating to match new version of source page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Joomla! 3.9 et plus permet aux extensions de tracer leurs actions dans User Action Log. Cela est possible en créant un plugin dans le dossier actionlog.

Veuillez prendre en considération que si votre plugin n'est pas dans le dossier actionlog, vous obtiendrez des chaînes de caractères non traduites dans le composant et / ou module User Action Log, quand des actions de votre extension sont affichées.

En tant que développeur, vous devriez être avisé que tous les plugins actionlog publiés sont chargés par le plugin système Joomla Action Log. Cela implique que le constructeur de votre plugin actionlog devrait être réduit au strict minimum et ne pas faire des initialisations qui pourraient avoir un impact sur les performances. Si vous avez besoin de faire toute sorte d'initialisation lourde, essayer de la reporter au dernier moment possible, c'est-à-dire quand vous êtes sur le point de tracer une action.

Le plugin actionlog est destiné à "capturer" les actions de votre extension et de les enregistrer (tracer). La partie capture dépend entièrement de votre extension. L'idée est que chaque action intéressante qui a besoin d'être tracée doit déclencher un événement de plugin qui est géré par votre plugin actionlog et a pour effet de tracer ladite action dans la base de données.

Joomla's MVC only triggers events on content preparation. If you want to see how you can handle those events for your component check the Joomla plugin in the actionlog folder.

For everything else it's advisable to use your own, custom plugin event names. Take extra care to not cause any naming conflicts. For example, a plugin event called onAfterInitialize is BAD because it clashes with Joomla's built-in event by the same name. DO NOT use generic plugin names such as onAfterSave because you are guaranteed to cause a conflict with another extension or Joomla itself. Remember that plugin event names are shared across all plugins in all plugin folders!

The best way to prevent naming clashes is using naming conventions like the following:

  • For components, onComComponentControllerViewnameAfterorbeforeTask e.g. onComExampleControllerItemsAfterBrowse for option=com_example&view=items&task=browse
  • For plugins, onPlgFolderPluginnameAction e.g. onPlgSystemFoobarBaz to log the "baz" action taken by a plugin named foobar in the system folder.

Modules, templates, and libraries are unlikely candidates for actions you might want to log but you can use a similar naming convention:

  • For modules, onModSiteoradminModulenameAction e.g. onModSiteExampleFoo for a frontend (site) module mod_example taking action foo
  • For libraries, onLibLibrarynameAction e.g. onLibExampleFoo for the lib_example library taking action foo
  • For templates, onTplSiteoradminTemplatenameAction e.g. on TplSiteExampleFoo for a frontend template named example taking action foo

If you have a Model used in many of your component's controllers and you would rather log an action taken there you can use the naming convention onComComponentModelModelnameAfterorbeforeMethodname e.g. onComExampleModelItemsBeforeSave to log something that happens after calling the ExampleModelItems::save() method. Again, this convention is arbitrary and the only reason we recommend it is that you can have a reasonable expectation that it won't cause naming clashes. The more specific the event name is the less likely it is to have a conflict with core or third party code.

Logging the actions requires going through a bit of code to perform sanity checks (e.g. correct Joomla version) and do the actual logging. Here is a prototype function you can use in your plugin:

	public function logUserAction($title, $logText, $extension)
	{
		static $joomlaModelAdded = false;

		// User Actions Log is available only under Joomla 3.9+
		if (version_compare(JVERSION, '3.9', 'lt'))
		{
			return;
		}

		// Include required Joomla Model
		if (!$joomlaModelAdded)
		{
			\JModelLegacy::addIncludePath(JPATH_ROOT . '/administrator/components/com_actionlogs/models', 'ActionlogsModel');
			$joomlaModelAdded = true;
		}

		$user = $this->getUser();

		// No log for guest users
		if ($user->guest)
		{
			return;
		}

		$message = array(
			'title'    	  => $title,
			'username' 	  => $user->username,
			'accountlink'     => 'index.php?option=com_users&task=user.edit&id=' . $user->id
		);

		/** @var \ActionlogsModelActionlog $model **/
		try
		{
			$model = \JModelLegacy::getInstance('Actionlog', 'ActionlogsModel');
			$model->addLog(array($message), $logText, $extension, $user->id);
		}
		catch (\Exception $e)
		{
			// Ignore any error
		}
	}

Here is an example plugin method performing user action logging:

/**
	 * Logs the creation of a new backup profile
	 *
	 * @param \Akeeba\Backup\Admin\Controller\Profiles	$controller
	 * @param array										$data
	 * @param int										$id
	 */
	public function onComAkeebaControllerProfilesAfterApplySave($controller, $data, $id)
	{
		// If I have an ID in the request and it's the same of the model, I'm just editing a record
		if (isset($data['id']) && $data['id'] == $id)
		{
			return;
		}

		$profile_title = $data['description'];

		$this->logUserAction($profile_title, 'COM_AKEEBA_LOGS_PROFILE_ADD', 'com_akeeba');
	}

Note that the log title (the second argument to the method) is a translation key. It is defined similar to that:

COM_AKEEBA_LOGS_PROFILE_ADD="User <a href=\"{accountlink}\">{username}</a> created the backup profile {title}"

The {title} variable is the $title parameter in our method. The other two variables are defined and processed by the User Action Logs module and component when rendering the user actions log.

Caveat: Since Joomla 4 has not yet integrated the Action Logs component and plugins the code above will not work on Joomla! 4. If / when Action Logs are ported to Joomla 4 we'll have to revisit this documentation page since neither JModelLegacy is available, nor will the Model name be ActionlogsModelActionlog.