Intégrer des extensions au composant de confidentialité
From Joomla! Documentation
Les informations ci-dessous sont fournies aux développeurs d'extensions pour les aider à créer les intégrations de la Suite Outils de Confidentialité.
Fonctions d'Extension liées à la Confidentialité
Le nouveau composant de confidentialité comporte une section Capacités qui permet aux extensions de signaler les fonctionnalités liées à la confidentialité. L'objectif de cette section est d'aider les utilisateurs à comprendre ce qu'une extension peut faire en rapport avec les données personnelles des utilisateurs et d'aider les propriétaires de sites à planifier leurs tâches en conséquence. Pour plus de détails sur cette section, y compris sur la manière dont un plug-in doit s'intégrer, consultez la page Capacités d'Extension de Rapport dans le Composant de Confidentialité.
Vérifier une Politique de Confidentialité Publiée
Le bilan de santé du composant de confidentialité informe les utilisateurs s'il existe une politique de confidentialité publiée sur le site web. Cette vérification est effectuée par l’événement onPrivacyCheckPrivacyPolicyPublished auquel peuvent s’abonner les plug-ins des groupes de plug-in : confidentialité, système et utilisateur. L'événement reçoit un tableau associatif par référence avec deux clés comme argument:
- "published" - Valeur booléenne indiquant qu'il existe une politique publiée
- "editLink" - L'URL permettant de modifier l'élément de stratégie, elle s'affiche si une politique de confidentialité est publiée
- "articlePublished" - Le statut de l'article lorsqu'il existe en base de données
En guise de meilleure pratique, il est suggéré que les plug-ins vérifient d’abord si l’indicateur "published" est déjà défini sur true et ne modifient pas le tableau de données si tel est le cas. Notez que le plugin central Système - Consentement de Confidentialité traitera cet événement.
public function onPrivacyCheckPrivacyPolicyPublished(&$policy)
{
// If another plugin has already indicated a policy is published, we won't change anything here
if ($policy['published'])
{
return;
}
// Do stuff to find the privacy policy data
// For core, we check if the article exists in the database and is published or not
$query = $this->db->getQuery(true)
->select($this->db->quoteName(array('id', 'state')))
->from($this->db->quoteName('#__content'))
->where($this->db->quoteName('id') . ' = ' . (int) $articleId);
$this->db->setQuery($query);
$article = $this->db->loadObject();
// Check if the article exists
if (!$article)
{
return;
}
// Check if the article is published
if ($article->state == 1)
{
$policy['articlePublished'] = true;
}
$policy['published'] = true;
$policy['editLink'] = ''; // The link to the item's edit page, processed through JRoute, i.e. JRoute::_('index.php?option=com_content&task=article.edit&id=1');
}
Ajouter des Données aux Demandes d'Exportation
Pour plus de commodité, il existe plusieurs méthodes d'assistance dans la classe PrivacyPlugin et il est recommandé que les plug-ins de confidentialité étendent cette classe pour hériter de ces assistances (cette classe est similaire à la classe FinderIndexerAdapter des Plugins Recherche Intelligente par exemple).
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');
class PlgPrivacyContent extends PrivacyPlugin {}
Pour ajouter des données à une demande d'exportation, un plug-in dans les groupes de plug-in de confidentialité ou système doit s'inscrire à l'événement onPrivacyExportRequest.
L'événement reçoit deux arguments:
- $request - Un objet PrivacyTableRequest contenant l'enregistrement de demande d'informations de la base de données
- $user - S'il existe un compte pour l'adresse e-mail de la demande d'informations, un objet Joomla\CMS\User\User contenant les données du compte utilisateur est fourni.
L'événement doit renvoyer un tableau d'objets PrivacyExportDomain contenant les données à exporter pour un domaine donné. Si le plugin n'a pas de données, il doit retourner un tableau vide.
Un objet de données PrivacyExportDomain représente généralement les données trouvées dans une table de la base de données et se compose de trois éléments:
- Nom de domaine - Nom permettant d'identifier le domaine
- Description du domaine - Une brève description des données contenues dans le domaine
- Eléments du domaine - Tableau d'objets de données PrivacyExportItem contenant tous les éléments du domaine
Un objet de données PrivacyExportItem représente un élément unique dans le domaine de données et se compose de deux éléments:
- ID d'élément - Identificateur principal de cet élément dans le domaine. Il s'agit généralement de la clé primaire de l'enregistrement dans la base de données.
- Champs d'élément - Un tableau d'objets de données PrivacyExportField contenant chaque champ pour l'élément
Un objet de données PrivacyExportField représente un champ unique dans un élément et se compose de deux éléments:
- Nom du champ - Le nom du champ
- Valeur du champ - La valeur du champ
Le flux de travail général pour le processus d'exportation est le suivant:
- Valider le plugin doit réellement traiter les données
- Interroger les données de la base de données
- Créer un domaine pour les résultats (la méthode createDomain héritée de la classe PrivacyPlugin peut vous aider)
- Ajouter des éléments pour chaque ligne
- La méthode createItemFromArray héritée de la classe PrivacyPlugin peut être utilisée pour créer un objet PrivacyExportItem à partir d’un tableau (ceci doit être utilisé avec la méthode de la base de données loadAssocList)
- La méthode createItemForTable héritée de la classe PrivacyPlugin peut être utilisée pour créer un objet PrivacyExportItem</ tt> à partir d’un objet Joomla\CMS\Table\Table
- Renvoyer le domaine
Vous trouverez ci-dessous un exemple d'exportation d'articles créés par un utilisateur, y compris des données de champs personnalisés.
use Joomla\CMS\User\User;
JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');
class PlgPrivacyContent extends PrivacyPlugin
{
/**
* @var JDatabaseDriver
*/
protected $db;
/**
* @var array
*/
protected $contents = array();
public function onPrivacyExportRequest(PrivacyTableRequest $request, User $user = null)
{
// This plugin only processes data for registered user accounts
if (!$user)
{
return array();
}
$domains = array();
$domains[] = $this->createContentDomain($user);
// Create domains for each article's custom fields
foreach ($this->contents as $content)
{
$domains[] = $this->createContentCustomFieldsDomain($content);
}
return $domains;
}
private function createContentDomain(User $user)
{
$domain = $this->createDomain('user_content', 'joomla_user_content_data');
$query = $this->db->getQuery(true)
->select('*')
->from($this->db->quoteName('#__content'))
->where($this->db->quoteName('created_by') . ' = ' . (int) $user->id)
->order($this->db->quoteName('ordering') . ' ASC');
$items = $this->db->setQuery($query)->loadAssocList();
// Add each article to the domain
foreach ($items as $item)
{
$domain->addItem($this->createItemFromArray($item));
// Store the article for use in the custom fields processing
$this->contents[] = (object) $item;
}
return $domain;
}
private function createContentCustomFieldsDomain($content)
{
$domain = $this->createDomain('content_custom_fields', 'joomla_content_custom_fields_data');
// Get item's fields, also preparing their value property for manual display
$fields = FieldsHelper::getFields('com_content.article', $content);
foreach ($fields as $field)
{
$fieldValue = is_array($field->value) ? implode(', ', $field->value) : $field->value;
$data = array(
'content_id' => $content->id,
'field_name' => $field->name,
'field_title' => $field->title,
'field_value' => $fieldValue,
);
$domain->addItem($this->createItemFromArray($data));
}
return $domain;
}
}
Processus de Requêtes de Suppression
Le traitement d'une demande de suppression nécessite deux étapes: Validation de la suppression des données du sujet qui peuvent être supprimées et suppression effective. Encore une fois, il est suggéré que les plug-ins étendent la classe PrivacyPlugin, mais ce n’est pas une nécessité absolue.
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');
class PlgPrivacyUser extends PrivacyPlugin {}
Valider les Données qui Peuvent Être Supprimées
Si le plug-in peut avoir besoin de bloquer la suppression des données d'un sujet, il doit souscrire à l'événement onPrivacyCanRemoveData. En général, une suppression doit être bloquée s'il existe des raisons juridiques valides de conserver les données ou si la suppression peut endommager définitivement le site (par exemple, le principal Confidentialité - Comptes d'utilisateurs interdit la suppression d'un compte super utilisateur) .
L'événement reçoit deux arguments:
- $request - Un objet PrivacyTableRequest contenant l’enregistrement de la demande d’informations de la base de données
- $user - S'il existe un compte pour l'adresse e-mail de la demande d'informations, un objet Joomla\CMS\User\User contenant les données du compte utilisateur est fourni.
L'événement doit renvoyer un objet de données PrivacyRemovalStatus qui spécifie si les données ne peuvent pas être supprimées et une raison pour l'impossibilité de supprimer les données.
use Joomla\CMS\Language\Text;
use Joomla\CMS\User\User;
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');
JLoader::register('PrivacyRemovalStatus', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/removal/status.php');
class PlgPrivacyUser extends PrivacyPlugin
{
public function onPrivacyCanRemoveData(PrivacyTableRequest $request, User $user = null)
{
$status = new PrivacyRemovalStatus;
// We only need to check if there is an associated user account
if (!$user)
{
return $status;
}
// We will not remove a super user account from the site
if ($user->authorise('core.admin'))
{
$status->canRemove = false;
$status->reason = Text::_('PLG_PRIVACY_USER_ERROR_CANNOT_REMOVE_SUPER_USER');
}
return $status;
}
}
Supprimer ou Anonymiser les Données
Si le plug-in gère la suppression ou l'anonymisation des données, il doit s'inscrire à l'événement onPrivacyRemoveData.
L'événement reçoit deux arguments:
- $request - Un objet PrivacyTableRequest contenant l'enregistrement de demande d'informations de la base de données
- $user - S'il existe un compte pour l'adresse e-mail de la demande d'informations, un objet Joomla\CMS\User\User contenant les données du compte utilisateur est fourni.
Contrairement aux autres événements de ce composant, les plug-ins ne sont censés renvoyer aucune donnée.
Selon les exigences des données sous-jacentes, les plug-ins doivent anonymiser les informations conservées et supprimer toutes les données qui ne sont plus nécessaires. Si nécessaire, le plug-in peut effectuer d'autres actions liées à la requête et/ou au compte utilisateur.
L'exemple ci-dessous montre comment Joomla anonymise et supprime les données liées au compte utilisateur principal.
use Joomla\CMS\Factory;
use Joomla\CMS\User\User;
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/plugin.php');
class PlgPrivacyUser extends PrivacyPlugin
{
/**
* @var JDatabaseDriver
*/
protected $db;
public function onPrivacyRemoveData(PrivacyTableRequest $request, User $user = null)
{
// This plugin only processes data for registered user accounts
if (!$user)
{
return;
}
$pseudoanonymisedData = array(
'name' => 'User ID ' . $user->id,
'username' => bin2hex(random_bytes(12)), // Generates a random username
'email' => 'UserID' . $user->id . 'removed@email.invalid',
'block' => true,
);
$user->bind($pseudoanonymisedData);
$user->save();
// Destroy all sessions for the user account
$sessionIds = $this->db->setQuery(
$this->db->getQuery(true)
->select($this->db->quoteName('session_id'))
->from($this->db->quoteName('#__session'))
->where($this->db->quoteName('userid') . ' = ' . (int) $user->id)
)->loadColumn();
// If there aren't any active sessions then there's nothing to do here
if (empty($sessionIds))
{
return;
}
$storeName = Factory::getConfig()->get('session_handler', 'none');
$store = JSessionStorage::getInstance($storeName);
$quotedIds = array();
// Destroy the sessions and quote the IDs to purge the session table
foreach ($sessionIds as $sessionId)
{
$store->destroy($sessionId);
$quotedIds[] = $this->db->quote($sessionId);
}
$this->db->setQuery(
$this->db->getQuery(true)
->delete($this->db->quoteName('#__session'))
->where($this->db->quoteName('session_id') . ' IN (' . implode(', ', $quotedIds) . ')')
)->execute();
}
}