diff --git a/_init.php b/_init.php
index 89a16e9..74a0ef4 100644
--- a/_init.php
+++ b/_init.php
@@ -17,6 +17,5 @@ if (!defined('DC_RC_PATH')) {
class initActivityReport
{
public const ACTIVITY_TABLE_NAME = 'activity';
- public const SETTING_TABLE_NAME = 'activity_setting';
public const CACHE_DIR_NAME = 'activityreport';
}
diff --git a/icon.png b/icon.png
deleted file mode 100644
index 8bdd330..0000000
Binary files a/icon.png and /dev/null differ
diff --git a/icon.svg b/icon.svg
new file mode 100644
index 0000000..476b01c
--- /dev/null
+++ b/icon.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/js/backend.js b/js/backend.js
new file mode 100644
index 0000000..fd73b0a
--- /dev/null
+++ b/js/backend.js
@@ -0,0 +1,10 @@
+/*global $, dotclear */
+'use strict';
+
+Object.assign(dotclear.msg, dotclear.getData('activityReport'));
+
+$(() => {
+ $('#form-logs').on('submit', function () {
+ return window.confirm(dotclear.msg.confirm_delete);
+ });
+});
\ No newline at end of file
diff --git a/js/main.js b/js/main.js
deleted file mode 100644
index 42b9906..0000000
--- a/js/main.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -- BEGIN LICENSE BLOCK ----------------------------------
- * This file is part of activityReport, a plugin for Dotclear 2.
- *
- * Copyright (c) 2009-2010 JC Denis and contributors
- * jcdenis@gdwd.com
- *
- * Licensed under the GPL version 2.0 license.
- * A copy of this license is available in LICENSE file or at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * -- END LICENSE BLOCK ------------------------------------*/
-
-$(function(){
- /* tools */
- dotclear.jcTools = new jcToolsBox();
-
- /* setting blog */
- var bForm=$('#setting-blog-form');
- if ($(bForm).attr('id')!=undefined){
- dotclear.jcTools.formFieldsetToMenu(bForm);
- $(bForm).submit(function(){dotclear.jcTools.waitMessage();return true;});
- }
- /* setting global */
- var gForm=$('#setting-super-form');
- if ($(gForm).attr('id')!=undefined){
- dotclear.jcTools.formFieldsetToMenu(gForm);
- $(gForm).submit(function(){dotclear.jcTools.waitMessage();return true;});
- }
-});
-
-function jcToolsBox(){}
-
-jcToolsBox.prototype={
- text_wait:'Please wait',
- section:'',
-
- formFieldsetToMenu:function(form){
- var This=this;
- var section=$(form).children('fieldset[id='+This.section+']').attr('id');
- var hidden_section=$(form).children('input[name=section]').attr('value');
- var formMenu=$(form).children('p.formMenu').get(0);
- if (formMenu==undefined) {
- $(form).prepend($('
').addClass('formMenu'));
- }
- $(form).children('fieldset').each(function(){
- var Fieldset=this;
- $(Fieldset).hide();
- var title=$(Fieldset).children('legend').text();
- var menu=$(' ').text(title).addClass('button').attr('tabindex','2').click(
- function(){
- var fieldset_visible=$(form).children('fieldset:visible');
- if (fieldset_visible==undefined){
- $(Fieldset).slideDown('slow');$(form).children('input[type=submit]').show();
- }else{
- $(fieldset_visible).fadeOut('fast',function(){$(Fieldset).fadeIn('fast');$(form).children('input[type=submit]').show();})
- }
- if (hidden_section==undefined){
- $(form).children('input[name=section]').remove();
- $(form).append($(' ').attr('name','section').attr('value',$(Fieldset).attr('id')));
- }
- $('.message').fadeOut('slow',function(){$(this).slideUp('slow',function(){$(this).remove();})});
- }
- );
- $(form).children('.formMenu').append(menu).append(' ');
- });
- if (section!=undefined){
- $(form).children('fieldset[id='+section+']').show();
- }else{
- $(form).children('fieldset:first').show();
- }
- },
-
- waitMessage:function(){
- var This=this;
- var content=$('div[id=content]');
- if (content!=undefined){
- $(content).hide();
- }else{
- $('input').hide();$('select').hide();
- content=$('body');
- }
- var text=$('
').addClass('message').text(This.text_wait);
- This.blinkItem(text);
- var box=$('
').attr('style','margin: 60px auto auto;width:200px;').append(text);
- $(content).before($(box));
- },
-
- blinkItem:function(item){
- var This=this;
- $(item).fadeOut('slow',function(){$(this).fadeIn('slow',function(){This.blinkItem(this);})});
- }
-}
\ No newline at end of file
diff --git a/locales/fr/main.lang.php b/locales/fr/main.lang.php
new file mode 100644
index 0000000..6384cfb
--- /dev/null
+++ b/locales/fr/main.lang.php
@@ -0,0 +1,108 @@
+ 1);\n"
-msgid "Activity report"
-msgstr "Rapport d'activité"
-
-msgid "View all logs"
-msgstr "Voir tous les logs"
-
-msgid "Number of activities to show on dashboard:"
-msgstr "Nombre d'activités à afficher sur le tableau de bord :"
-
-msgid "Do not show activity report"
-msgstr "Ne pas afficher le rapport d'activité"
-
-msgid "every hour"
-msgstr "toutes les heures"
-
-msgid "every 2 hours"
-msgstr "toutes les 2 heures"
-
-msgid "2 times by day"
-msgstr "2 fois par jour"
-
-msgid "every day"
-msgstr "tous les jours"
-
-msgid "every 2 days"
-msgstr "tous les 2 jours"
-
-msgid "every week"
-msgstr "toutes les semaines"
-
-msgid "every 2 weeks"
-msgstr "toutes les 2 semaines"
-
-msgid "every 4 weeks"
-msgstr "toutes les 4 semaines"
-
-msgid "Plain text"
-msgstr "Texte brut"
-
-msgid "HTML"
-msgstr "HTML"
-
-msgid "Report successfully sent."
-msgstr "Rapport envoyé avec succès."
-
-msgid "Logs successfully deleted."
-msgstr "Logs effacés avec succès."
-
-msgid "never"
-msgstr "jamais"
-
-msgid "on new activity"
-msgstr "lors d'une nouvelle activité"
-
-msgid "Configure activity report for %s"
-msgstr "Configurer le rapport d'activité pour %s"
-
-msgid "current blog"
-msgstr "le blog courant"
-
-msgid "all blogs"
-msgstr "tous les blogs"
-
-msgid "This server has no mail function, activityReport does not send email report."
-msgstr "Ce server n'a pas de fonction d'envoie de mail, le rapport ne sera pas envoyer."
-
-msgid "Enable super administrator report"
-msgstr "Autoriser le rapport de super administrateur"
-
-msgid "Enable report on this blog"
-msgstr "Autoriser le rapport sur ce blog"
-
-msgid "Automatic cleaning of old logs:"
-msgstr "Nettoyage automatique des anciennes activités:"
-
-msgid "Use Dotclear date formaters. ex: %B %d at %H:%M"
-msgstr "Utiliser le formatage des dates de Dotclear. ex: %d %B à %H:%M"
-
-msgid "RSS feed"
-msgstr "Flux RSS"
-
-msgid "Rss2 feed for activity on this blog"
-msgstr "Flux Rss2 pour l'activité de ce blog"
-
-msgid "Atom feed"
-msgstr "Flux Atom"
-
-msgid "Atom feed for activity on this blog"
-msgstr "Flux Atom pour l'activité de ce blog"
-
-msgid "Send report:"
-msgstr "Rapport envoyé :"
-
-msgid "Recipients:"
-msgstr "Destinataires :"
-
-msgid "Separate multiple email addresses with a semicolon \";\""
-msgstr "Séparer les adresses email par un point-virgule \";\""
-
-msgid "Report format:"
-msgstr "Format du rapport :"
-
-msgid "Last report by email:"
-msgstr "Dernier rapport par email :"
-
-msgid "Next report by email:"
-msgstr "Prochain rapport par email :"
-
-msgid "Select blogs to add to report"
-msgstr "Sélectionner les blogs à ajouter au rapport"
-
-msgid "Report"
-msgstr "Rapport"
-
-msgid "Select actions by activity type to add to report"
-msgstr "Sélectionner les actions par type d'activité à ajouter au rapport"
-
-msgid "Send report now"
-msgstr "Envoyer un rapport maintenant"
-
-msgid "Delete all logs now"
-msgstr "Effacer tous les logs maintenant"
-
+#: src/ActivityBehaviors.php:32
msgid "ActivityReport messages"
msgstr "Messages de l'extension"
-msgid "Special messages"
-msgstr "Messages spéciaux"
-
-msgid "%s"
-msgstr "%s"
-
+#: src/ActivityBehaviors.php:33
msgid "Actions on blog"
msgstr "Actions sur le blog"
-msgid "updating blog"
-msgstr "Mise à jour du blog"
-
-msgid "Blog was updated by \"%s\""
-msgstr "Blog mis à jour par \"%s\""
-
-msgid "404 error"
-msgstr "Erreur 404"
-
-msgid "New 404 error page at \"%s\""
-msgstr "Nouvelle erreur 404 à l'adresse \"%s\""
-
+#: src/ActivityBehaviors.php:34
msgid "Actions on posts"
msgstr "Actions sur les billets"
-msgid "post creation"
-msgstr "Création de billet"
-
-msgid "A new post called \"%s\" was created by \"%s\" at %s"
-msgstr "Un nouveau billet nommé \"%s\" a été créé par \"%s\" à l'adresse \"%s\""
-
-msgid "updating post"
-msgstr "Mise à jour de billet"
-
-msgid "Post called \"%s\" has been updated by \"%s\" at %s"
-msgstr "Le billet nommé \"%s\" a été mis à jour par \"%s\" à l'adresse \"%s\""
-
-msgid "post deletion"
-msgstr "Suppression de billet"
-
-msgid "Post called \"%s\" has been deleted by \"%s\""
-msgstr "Le billet nommé \"%s\" a été supprimé par \"%s\""
-
-msgid "Post protection"
-msgstr "Protection des billets"
-
-msgid "An attempt failed on a passworded post with password \"%s\" at \"%s\""
-msgstr "Une tentative a échoué sur un billet protégé par mot de passe avec l'essai \"%s\" à l'adresse \"%s\""
-
+#: src/ActivityBehaviors.php:35
msgid "Actions on comments"
msgstr "Actions sur les commentaires"
-msgid "comment creation"
-msgstr "Création de commentaire"
-
-msgid "A new comment was created by \"%s\" on post \"%s\" at %s"
-msgstr "Un nouveau commentaire a été créé par \"%s\" sur le billet \"%s\""
-
-msgid "updating comment"
-msgstr "Mise à jour de commentaire"
-
-msgid "Comment has been updated by \"%s\" at %s"
-msgstr "Un commentaire a été mise à jour par \"%s\" à l'adresse \"%s\""
-
-msgid "trackback creation"
-msgstr "Création de trackback"
-
-msgid "A new trackback to \"%\" at \"%s\" was created on post \"%s\" at %s"
-msgstr "Un nouveau rétrolien vers \"%s\" a été créé sur le billet \"%s\" à l'adresse \"%s\""
-
+#: src/ActivityBehaviors.php:36
msgid "Actions on categories"
msgstr "Actions sur les catégories"
-msgid "category creation"
-msgstr "Création de catégorie"
-
-msgid "A new category called \"%s\" was created by \"%s\" at %s"
-msgstr "Un nouvelle catégorie nommée \"%s\" a été créé par \"%s\" à l'adresse \"%s\""
-
-msgid "updating category"
-msgstr "Mise à jour de catégorie"
-
-msgid "Category called \"%s\" has been updated by \"%s\" at %s"
-msgstr "La catégorie nommée \"%s\" a été mise à jour par \"%s\" à l'adresse \"%s\""
-
+#: src/ActivityBehaviors.php:37
msgid "Actions on users"
msgstr "Actions sur les utilisateurs"
+#: src/ActivityBehaviors.php:43
+msgid "Special messages"
+msgstr "Messages spéciaux"
+
+#: src/ActivityBehaviors.php:44
+msgid "%s"
+msgstr "%s"
+
+#: src/ActivityBehaviors.php:54
+msgid "updating blog"
+msgstr "Mise à jour du blog"
+
+#: src/ActivityBehaviors.php:55
+msgid "Blog was updated by \"%s\""
+msgstr "Blog mis à jour par \"%s\""
+
+#: src/ActivityBehaviors.php:63
+msgid "404 error"
+msgstr "Erreur 404"
+
+#: src/ActivityBehaviors.php:64
+msgid "New 404 error page at \"%s\""
+msgstr "Nouvelle erreur 404 à l'adresse \"%s\""
+
+#: src/ActivityBehaviors.php:74
+msgid "post creation"
+msgstr "Création de billet"
+
+#: src/ActivityBehaviors.php:75
+msgid "A new post called \"%s\" was created by \"%s\" at %s"
+msgstr "Un nouveau billet nommé \"%s\" a été créé par \"%s\" à l'adresse \"%s\""
+
+#: src/ActivityBehaviors.php:94
+msgid "updating post"
+msgstr "Mise à jour de billet"
+
+#: src/ActivityBehaviors.php:95
+msgid "Post called \"%s\" has been updated by \"%s\" at %s"
+msgstr "Le billet nommé \"%s\" a été mis à jour par \"%s\" à l'adresse \"%s\""
+
+#: src/ActivityBehaviors.php:103
+msgid "post deletion"
+msgstr "Suppression de billet"
+
+#: src/ActivityBehaviors.php:104
+msgid "Post called \"%s\" has been deleted by \"%s\""
+msgstr "Le billet nommé \"%s\" a été supprimé par \"%s\""
+
+#: src/ActivityBehaviors.php:113
+msgid "Post protection"
+msgstr "Protection des billets"
+
+#: src/ActivityBehaviors.php:114
+msgid "An attempt failed on a passworded post with password \"%s\" at \"%s\""
+msgstr "Une tentative a échoué sur un billet protégé par mot de passe avec l'essai \"%s\" à l'adresse \"%s\""
+
+#: src/ActivityBehaviors.php:124
+msgid "comment creation"
+msgstr "Création de commentaire"
+
+#: src/ActivityBehaviors.php:125
+msgid "A new comment was created by \"%s\" on post \"%s\" at %s"
+msgstr "Un nouveau commentaire a été créé par \"%s\" sur le billet \"%s\""
+
+#: src/ActivityBehaviors.php:134
+msgid "updating comment"
+msgstr "Mise à jour de commentaire"
+
+#: src/ActivityBehaviors.php:135
+msgid "Comment has been updated by \"%s\" at %s"
+msgstr "Un commentaire a été mise à jour par \"%s\" à l'adresse \"%s\""
+
+#: src/ActivityBehaviors.php:147
+msgid "trackback creation"
+msgstr "Création de trackback"
+
+#: src/ActivityBehaviors.php:148
+msgid "A new trackback to \"%\" at \"%s\" was created on post \"%s\" at %s"
+msgstr "Un nouveau rétrolien vers \"%s\" a été créé sur le billet \"%s\" à l'adresse \"%s\""
+
+#: src/ActivityBehaviors.php:156
+msgid "category creation"
+msgstr "Création de catégorie"
+
+#: src/ActivityBehaviors.php:157
+msgid "A new category called \"%s\" was created by \"%s\" at %s"
+msgstr "Un nouvelle catégorie nommée \"%s\" a été créé par \"%s\" à l'adresse \"%s\""
+
+#: src/ActivityBehaviors.php:165
+msgid "updating category"
+msgstr "Mise à jour de catégorie"
+
+#: src/ActivityBehaviors.php:166
+msgid "Category called \"%s\" has been updated by \"%s\" at %s"
+msgstr "La catégorie nommée \"%s\" a été mise à jour par \"%s\" à l'adresse \"%s\""
+
+#: src/ActivityBehaviors.php:176
msgid "user creation"
msgstr "Création d'utilisateur"
+#: src/ActivityBehaviors.php:177
msgid "A new user named \"%s\" was created by \"%s\""
msgstr "Un nouvel utilisateur a été ajouté par \"%s\""
+#: src/ActivityBehaviors.php:185
msgid "updating user"
msgstr "Mise à jour d'utilisateur"
+#: src/ActivityBehaviors.php:186
msgid "User named \"%s\" has been updated by \"%s\""
msgstr "L'utilisateur \"%s\" a été mis à jour par \"%s\""
+#: src/ActivityBehaviors.php:217
msgid "user deletion"
msgstr "Suppression d'utilisateur"
+#: src/ActivityBehaviors.php:218
msgid "User named \"%s\" has been deleted by \"%\""
msgstr "L'utilisateur nommé \"%s\" a été supprimé par \"%s\""
+#: src/ActivityBehaviors.php:235
+msgid "HTML"
+msgstr "HTML"
+
+#: src/ActivityBehaviors.php:248
+#: src/ActivityReport.php:341
+msgid "Activity report"
+msgstr "Rapport d'activité"
+
+#: src/ActivityReport.php:331
msgid "An error occured when parsing report."
msgstr "Une erreur est survenue lors de la compilation du rapport."
+#: src/ActivityReport.php:347
msgid "You received a message from your blog's activity report module."
msgstr "Vous recevez un message du module de rapport d'activité de votre blog."
+#: src/ActivityReport.php:356
msgid "Period from %s to %s"
msgstr "Période du %s au %s"
+#: src/ActivityReport.php:404
msgid "Activity report deletes some old logs."
msgstr "L'extension a automatiquement effacé des anciennes activités."
-msgid "Blog activity report"
-msgstr "Rapport d'activité du blog"
+#: src/ActivityReport.php:661
+msgid "Blog \"%s\" activity report"
+msgstr "Rapport d'activité du blog \"%s\""
-msgid "Logs"
-msgstr "Enregistrements"
+#: src/Backend.php:126
+msgid "View all logs"
+msgstr "Voir tous les logs"
+#: src/Backend.php:142
+msgid "Number of activities to show on dashboard:"
+msgstr "Nombre d'activités à afficher sur le tableau de bord :"
+
+#: src/Backend.php:144
+msgid "Do not show activity report"
+msgstr "Ne pas afficher le rapport d'activité"
+
+#: src/Backend.php:170
+#: src/ManageList.php:48
+msgid "Group"
+msgstr "Groupe"
+
+#: src/Backend.php:177
+msgid "logs per page"
+msgstr "enregistrements par page"
+
+#: src/Combo.php:45
+msgid "every hour"
+msgstr "toutes les heures"
+
+#: src/Combo.php:46
+msgid "every 2 hours"
+msgstr "toutes les 2 heures"
+
+#: src/Combo.php:47
+msgid "2 times by day"
+msgstr "2 fois par jour"
+
+#: src/Combo.php:48
+msgid "every day"
+msgstr "tous les jours"
+
+#: src/Combo.php:49
+msgid "every 2 days"
+msgstr "tous les 2 jours"
+
+#: src/Combo.php:50
+msgid "every week"
+msgstr "toutes les semaines"
+
+#: src/Combo.php:68
+msgid "every 2 weeks"
+msgstr "toutes les 2 semaines"
+
+#: src/Combo.php:69
+msgid "every 4 weeks"
+msgstr "toutes les 4 semaines"
+
+#: src/Config.php:85
+msgid "Report successfully sent."
+msgstr "Rapport envoyé avec succès."
+
+#: src/Config.php:92
+msgid "Logs successfully deleted."
+msgstr "Logs effacés avec succès."
+
+#: src/Config.php:116
+msgid "never"
+msgstr "jamais"
+
+#: src/Config.php:117
+msgid "on new activity"
+msgstr "lors d'une nouvelle activité"
+
+#: src/Config.php:133
+msgid "This server has no mail function, activityReport does not send email report."
+msgstr "Ce server n'a pas de fonction d'envoie de mail, le rapport ne sera pas envoyer."
+
+#: src/Config.php:140
+msgid "Mail report"
+msgstr "Rapport par email"
+
+#: src/Config.php:142
+msgid "Send report:"
+msgstr "Rapport envoyé :"
+
+#: src/Config.php:146
+msgid "Recipients:"
+msgstr "Destinataires :"
+
+#: src/Config.php:149
+msgid "Separate multiple email addresses with a semicolon \";\""
+msgstr "Séparer les adresses email par un point-virgule \";\""
+
+#: src/Config.php:150
+msgid "Leave it empty to disable mail report."
+msgstr "Laisser vide pour désactiver le rapport par email."
+
+#: src/Config.php:155
+msgid "Use Dotclear date formaters. ex: %B %d at %H:%M"
+msgstr "Utiliser le formatage des dates de Dotclear. ex: %d %B à %H:%M"
+
+#: src/Config.php:157
+msgid "Report format:"
+msgstr "Format du rapport :"
+
+#: src/Config.php:162
+msgid "Last report by email:"
+msgstr "Dernier rapport par email :"
+
+#: src/Config.php:163
+msgid "Next report by email:"
+msgstr "Prochain rapport par email :"
+
+#: src/Config.php:167
+msgid "Feeds"
+msgstr "Flux"
+
+#: src/Config.php:170
+msgid "Enable activity feed"
+msgstr "Activer le flux d'activités"
+
+#: src/Config.php:174
+msgid "RSS feed"
+msgstr "Flux RSS"
+
+#: src/Config.php:177
+msgid "Rss2 activities feed"
+msgstr "Flux RSS2 d'activités"
+
+#: src/Config.php:178
+msgid "Atom feed"
+msgstr "Flux Atom"
+
+#: src/Config.php:181
+msgid "Atom activities feed"
+msgstr "Flux Atom d'activités"
+
+#: src/Config.php:188
+msgid "Activities"
+msgstr "Activités"
+
+#: src/Config.php:189
+msgid "Select actions by activity type to add to report"
+msgstr "Sélectionner les actions par type d'activité à ajouter au rapport"
+
+#: src/Config.php:214
+msgid "Automatic cleaning of old logs:"
+msgstr "Nettoyage automatique des anciennes activités:"
+
+#: src/Config.php:219
+msgid "Send report now"
+msgstr "Envoyer un rapport maintenant"
+
+#: src/Config.php:223
+msgid "Delete all logs now"
+msgstr "Effacer tous les logs maintenant"
+
+#: src/Format.php:68
+msgid "Plain text"
+msgstr "Texte brut"
+
+#: src/Manage.php:58
+msgid "Logs successfully deleted"
+msgstr "Enregistrements effacés avec succès"
+
+#: src/Manage.php:91
+msgid "Are you sure you want to delete logs?"
+msgstr "Êtes-vous sure de vouloir effacer les enregistrements ?"
+
+#: src/Manage.php:114
+msgid "Delete all aticivity logs"
+msgstr "Effacer tous les enregistrements d'activités"
+
+#: src/Manage.php:115
+msgid "Delete all allready reported logs"
+msgstr "Effacer les enregistrements d'activités déjà envoyé par email"
+
+#: src/ManageList.php:33
+msgid "No log matches the filter"
+msgstr "Aucun enregistrement ne correspond au filtre"
+
+#: src/ManageList.php:35
msgid "No log"
msgstr "Pas d'enregistrement"
+#: src/ManageList.php:43
+msgid "List of %s logs matching the filter."
+msgstr "Liste des %s logs correspondants au filtre."
+
+#: src/ManageList.php:44
+msgid "List of %s logs."
+msgstr "Listes des %s enregistrements"
+
+#: src/ManageList.php:50
msgid "Message"
msgstr "Message"
-msgid "Activity report module"
-msgstr "Module de rapport d'activité"
+#: src/ManageList.php:79
+msgid "undefined"
+msgstr "inconnu"
+
+#: src/ManageList.php:85
+msgid "reported"
+msgstr "envoyé"
+
+msgid "Activity log"
+msgstr "Journal d'activité"
+
+msgid "Log and receive your blog activity by email, feed, or on dashboard"
+msgstr "Enregistrer et recevoir l'activité de votre blog par mail, flux ou sur le tableau de bord"
diff --git a/src/Action.php b/src/Action.php
new file mode 100644
index 0000000..5225f54
--- /dev/null
+++ b/src/Action.php
@@ -0,0 +1,45 @@
+addBehavior($behavior, $function);
+ }
+ }
+}
diff --git a/src/ActivityBehaviors.php b/src/ActivityBehaviors.php
index f283658..6778273 100644
--- a/src/ActivityBehaviors.php
+++ b/src/ActivityBehaviors.php
@@ -10,393 +10,470 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_RC_PATH')) {
- return null;
-}
+declare(strict_types=1);
-if (!defined('ACTIVITY_REPORT_V2')) {
- return null;
-}
+namespace Dotclear\Plugin\activityReport;
-class activityReportBehaviors
+use ArrayObject;
+use cursor;
+use dcBlog;
+use dcCore;
+use dcRecord;
+use dcUtils;
+use Dotclear\Helper\Network\Http;
+
+/**
+ * Register default activities and export mail formats.
+ */
+class ActivityBehaviors
{
- public static function registerBehaviors()
+ public static function register(): void
{
- // ActivityReport plugin
- dcCore::app()->activityReport->addGroup(basename(dirname(__DIR__)), __('ActivityReport messages'));
+ $my = new Group(My::id(), __('ActivityReport messages'));
+ $blog = new Group('blog', __('Actions on blog'));
+ $post = new Group('post', __('Actions on posts'));
+ $comment = new Group('comment', __('Actions on comments'));
+ $category = new Group('category', __('Actions on categories'));
+ $user = new Group('user', __('Actions on users'));
- dcCore::app()->activityReport->addAction(
- basename(dirname(__DIR__)),
+ // ActivityReport plugin
+
+ $my->add(new Action(
'message',
__('Special messages'),
__('%s'),
'messageActivityReport',
- ['activityReportBehaviors', 'messageActivityReport']
- );
-
- // Blog
- dcCore::app()->activityReport->addGroup('blog', __('Actions on blog'));
+ [self::class, 'messageActivityReport']
+ ));
// Not use as it is global : BEHAVIOR adminAfterBlogCreate in admin/blog.php
// from BEHAVIOR adminAfterBlogUpdate in admin/blog_pref.php
- dcCore::app()->activityReport->addAction(
- 'blog',
+ $blog->add(new Action(
'update',
__('updating blog'),
__('Blog was updated by "%s"'),
'adminAfterBlogUpdate',
- ['activityReportBehaviors', 'blogUpdate']
- );
+ [self::class, 'blogUpdate']
+ ));
// from BEHAVIOR publicHeadContent in template
- dcCore::app()->activityReport->addAction(
- 'blog',
+ $blog->add(new Action(
'p404',
__('404 error'),
__('New 404 error page at "%s"'),
'publicHeadContent',
- ['activityReportBehaviors', 'blogP404']
- );
-
- // Post
- dcCore::app()->activityReport->addGroup('post', __('Actions on posts'));
+ [self::class, 'blogP404']
+ ));
// from BEHAVIOR coreAfterPostCreate in inc/core/class.dc.blog.php (DC 2.2)
// duplicate adminAfterPostCreate in admin/post.php
// duplicate adminAfterPostCreate in admin/services.php
- dcCore::app()->activityReport->addAction(
- 'post',
+ $post->add(new Action(
'create',
__('post creation'),
__('A new post called "%s" was created by "%s" at %s'),
'adminAfterPostCreate',
- ['activityReportBehaviors', 'postCreate']
- );
+ [self::class, 'postCreate']
+ ));
// Plugin contribute
// from BEHAVIOR publicAfterPostCreate in plugins/contribute/_public.php
- dcCore::app()->activityReport->addAction(
- 'post',
+ $post->add(new Action(
'create',
__('post creation'),
__('A new post called "%s" was created by "%s" at %s'),
'publicAfterPostCreate',
- ['activityReportBehaviors', 'postCreate']
- );
+ [self::class, 'postCreate']
+ ));
// from BEHAVIOR coreAfterPostUpdate in inc/core/class.dc.blog.php (DC2.2)
// duplicate adminAfterPostUpdate in admin/post.php
- dcCore::app()->activityReport->addAction(
- 'post',
+ $post->add(new Action(
'update',
__('updating post'),
__('Post called "%s" has been updated by "%s" at %s'),
'adminAfterPostUpdate',
- ['activityReportBehaviors', 'postUpdate']
- );
+ [self::class, 'postUpdate']
+ ));
// from BEHAVIOR adminBeforePostDelete in admin/post.php
- dcCore::app()->activityReport->addAction(
- 'post',
+ $post->add(new Action(
'delete',
__('post deletion'),
__('Post called "%s" has been deleted by "%s"'),
'adminBeforePostDelete',
- ['activityReportBehaviors', 'postDelete']
- );
+ [self::class, 'postDelete']
+ ));
// Wrong attempt on passworded enrty
// from BEHAVIOR urlHandlerServeDocument in inc/public/lib.urlhandlers.php
- dcCore::app()->activityReport->addAction(
- 'post',
+ $post->add(new Action(
'protection',
__('Post protection'),
__('An attempt failed on a passworded post with password "%s" at "%s"'),
'urlHandlerServeDocument',
- ['activityReportBehaviors', 'postPasswordAttempt']
- );
-
- // Comment
- dcCore::app()->activityReport->addGroup('comment', __('Actions on comments'));
+ [self::class, 'postPasswordAttempt']
+ ));
// from BEHAVIOR coreAfterCommentCreate in inc/core/class.dc.blog.php
// duplicate adminAfterCommentCreate in admin/comment.php
// duplicate publicAfterCommentCreate in inc/public/lib.urlhandlers.php
- dcCore::app()->activityReport->addAction(
- 'comment',
+ $comment->add(new Action(
'create',
__('comment creation'),
__('A new comment was created by "%s" on post "%s" at %s'),
'coreAfterCommentCreate',
- ['activityReportBehaviors', 'commentCreate']
- );
+ [self::class, 'commentCreate']
+ ));
// from BEHAVIOR coreAfterCommentUpdate in inc/core/class.dc.blog.php
// duplicate adminAfterCommentUpdate in admin/comment.php
- dcCore::app()->activityReport->addAction(
- 'comment',
+ $comment->add(new Action(
'update',
__('updating comment'),
__('Comment has been updated by "%s" at %s'),
'coreAfterCommentUpdate',
- ['activityReportBehaviors', 'commentUpdate']
- );
+ [self::class, 'commentUpdate']
+ ));
// Missing coreBeforeCommentDelete in inc/core/class.dc.blog.php
// Missing adminBeforeCommentDelete in admin/comment.php
// from BEHAVIOR coreAfterCommentCreate in inc/core/class.dc.blog.php
// duplicate publicAfterTrackbackCreate in inc/core/class.dc.trackback.php
- dcCore::app()->activityReport->addAction(
- 'comment',
+ $comment->add(new Action(
'trackback',
__('trackback creation'),
__('A new trackback to "%" at "%s" was created on post "%s" at %s'),
'coreAfterCommentCreate',
- ['activityReportBehaviors', 'trackbackCreate']
- );
-
- // Category
- dcCore::app()->activityReport->addGroup('category', __('Actions on categories'));
+ [self::class, 'trackbackCreate']
+ ));
// from BEHAVIOR adminAfterCategoryCreate in admin/category.php
- dcCore::app()->activityReport->addAction(
- 'category',
+ $category->add(new Action(
'create',
__('category creation'),
__('A new category called "%s" was created by "%s" at %s'),
'adminAfterCategoryCreate',
- ['activityReportBehaviors', 'categoryCreate']
- );
+ [self::class, 'categoryCreate']
+ ));
// from BEHAVIOR adminAfterCategoryUpdate in admin/category.php
- dcCore::app()->activityReport->addAction(
- 'category',
+ $category->add(new Action(
'update',
__('updating category'),
__('Category called "%s" has been updated by "%s" at %s'),
'adminAfterCategoryUpdate',
- ['activityReportBehaviors', 'categoryUpdate']
- );
+ [self::class, 'categoryUpdate']
+ ));
// Missing adminBeforeCategoryDelete in admin/category.php
- // User
- dcCore::app()->activityReport->addGroup('user', __('Actions on users'));
-
// from BEHAVIOR adminAfterUserCreate in admin/user.php
- dcCore::app()->activityReport->addAction(
- 'user',
+ $user->add(new Action(
'create',
__('user creation'),
__('A new user named "%s" was created by "%s"'),
'adminAfterUserCreate',
- ['activityReportBehaviors', 'userCreate']
- );
+ [self::class, 'userCreate']
+ ));
// from BEHAVIOR adminAfterUserUpdated in admin/user.php
- dcCore::app()->activityReport->addAction(
- 'user',
+ $user->add(new Action(
'update',
__('updating user'),
__('User named "%s" has been updated by "%s"'),
'adminAfterUserUpdate',
- ['activityReportBehaviors', 'userUpdate']
- );
+ [self::class, 'userUpdate']
+ ));
+
+ // from BEHAVIOR adminAfterUserProfileUpdate in admin/preferences.php
+ $user->add(new Action(
+ 'preference',
+ __('updating user preference'),
+ __('User named "%s" preference has been updated by "%s"'),
+ 'adminAfterUserProfileUpdate',
+ [self::class, 'userPreference']
+ ));
+ $user->add(new Action(
+ 'preference',
+ __('updating user preference'),
+ __('User named "%s" preference has been updated by "%s"'),
+ 'adminAfterUserOptionsUpdate',
+ [self::class, 'userPreference']
+ ));
+ $user->add(new Action(
+ 'preference',
+ __('updating user preference'),
+ __('User named "%s" preference has been updated by "%s"'),
+ 'adminAfterDashboardOptionsUpdate',
+ [self::class, 'userPreference']
+ ));
// from BEHAVIOR adminBeforeUserDelete in admin/users.php
- dcCore::app()->activityReport->addAction(
- 'user',
+ $user->add(new Action(
'delete',
__('user deletion'),
__('User named "%s" has been deleted by "%"'),
'adminBeforeUserDelete',
- ['activityReportBehaviors', 'userDelete']
- );
+ [self::class, 'userDelete']
+ ));
+
+ ActivityReport::instance()->groups
+ ->add($my)
+ ->add($blog)
+ ->add($post)
+ ->add($comment)
+ ->add($category)
+ ->add($user);
+
+ // Add default email report formats
+ ActivityReport::instance()->formats
+ ->add(new Format('plain', [])) // plain text format is build with default values
+ ->add(new Format('html', [
+ 'name' => __('HTML'),
+ 'blog_title' => '',
+ 'group_title' => '%TEXT% ',
+ 'group_open' => '',
+ 'action' => '%TIME% %TEXT% ',
+ 'error' => '%TEXT%
',
+ 'period_title' => '%TEXT% ',
+ 'period_open' => '',
+ 'info' => '%TEXT% ',
+ 'page' => '' . "\n" .
+ '' . "\n" .
+ '' . __('Activity report') . ' ' .
+ '' .
+ '' .
+ '%PERIOD%
%TEXT%
' .
+ '' .
+ '',
+ ]));
}
- public static function messageActivityReport($message)
+ public static function messageActivityReport(string $message): void
{
$logs = [$message];
- dcCore::app()->activityReport->addLog(basename(dirname(__DIR__)), 'message', $logs);
+ ActivityReport::instance()->addLog(My::id(), 'message', $logs);
}
- public static function blogUpdate($cur, $blog_id)
+ public static function blogUpdate(cursor $cur, string $blog_id): void
{
- $logs = [dcCore::app()->auth->getInfo('user_cn')];
- dcCore::app()->activityReport->addLog('blog', 'update', $logs);
+ $logs = [(string) dcCore::app()->auth?->getInfo('user_cn')];
+ ActivityReport::instance()->addLog('blog', 'update', $logs);
}
- public static function blogP404()
+ public static function blogP404(): void
{
if (dcCore::app()->url->type != '404') {
- return null;
+ return;
}
- $logs = [dcCore::app()->blog->url . $_SERVER['QUERY_STRING']];
- dcCore::app()->activityReport->addLog('blog', 'p404', $logs);
+ $logs = [(string) dcCore::app()->blog?->url . $_SERVER['QUERY_STRING']];
+ ActivityReport::instance()->addLog('blog', 'p404', $logs);
}
- public static function postCreate($cur, $post_id)
+ public static function postCreate(cursor $cur, int $post_id): void
{
- $type = $cur->post_type ? $cur->post_type : 'post';
- $post_url = dcCore::app()->blog->getPostURL('', $cur->post_dt, $cur->post_title, $post_id);
+ $type = $cur->getField('post_type') ?? 'post';
+ $post_url = dcCore::app()->blog?->getPostURL('', $cur->getField('post_dt'), $cur->getField('post_title'), $post_id);
$logs = [
- $cur->post_title,
- dcCore::app()->auth->getInfo('user_cn'),
- dcCore::app()->blog->url . dcCore::app()->url->getBase($type) . '/' . $post_url,
+ (string) $cur->getField('post_title'),
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
+ (string) dcCore::app()->blog?->url . dcCore::app()->url->getBase($type) . '/' . $post_url,
];
- dcCore::app()->activityReport->addLog('post', 'create', $logs);
+ ActivityReport::instance()->addLog('post', 'create', $logs);
}
- public static function postUpdate($cur, $post_id)
+ public static function postUpdate(cursor $cur, int $post_id): void
{
- $type = $cur->post_type ? $cur->post_type : 'post';
- $post_url = dcCore::app()->blog->getPostURL('', $cur->post_dt, $cur->post_title, $post_id);
+ $type = $cur->getField('post_type') ?? 'post';
+ $post_url = dcCore::app()->blog?->getPostURL('', $cur->getField('post_dt'), $cur->getField('post_title'), $post_id);
$logs = [
- $cur->post_title,
- dcCore::app()->auth->getInfo('user_cn'),
- dcCore::app()->blog->url . dcCore::app()->url->getBase($type) . '/' . $post_url,
+ (string) $cur->getField('post_title'),
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
+ (string) dcCore::app()->blog?->url . dcCore::app()->url->getBase($type) . '/' . $post_url,
];
- dcCore::app()->activityReport->addLog('post', 'update', $logs);
+ ActivityReport::instance()->addLog('post', 'update', $logs);
}
- public static function postDelete($post_id)
+ public static function postDelete(int $post_id): void
{
- $posts = dcCore::app()->blog->getPosts(['post_id' => $post_id, 'limit' => 1]);
- $logs = [
- $posts->post_title,
- dcCore::app()->auth->getInfo('user_cn'),
+ $posts = dcCore::app()->blog?->getPosts(['post_id' => $post_id, 'limit' => 1]);
+ if (!$posts || $posts->isEmpty()) {
+ return;
+ }
+ $logs = [
+ (string) $posts->f('post_title'),
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
];
- dcCore::app()->activityReport->addLog('post', 'delete', $logs);
+ ActivityReport::instance()->addLog('post', 'delete', $logs);
}
- public static function postPasswordAttempt($result)
+ public static function postPasswordAttempt(ArrayObject $result): void
{
if ($result['tpl'] != 'password-form.html' || empty($_POST['password'])) {
- return null;
+ return;
}
$logs = [
$_POST['password'],
- http::getSelfURI(),
+ Http::getSelfURI(),
];
- dcCore::app()->activityReport->addLog('post', 'protection', $logs);
+ ActivityReport::instance()->addLog('post', 'protection', $logs);
}
- public static function commentCreate($blog, $cur)
+ public static function commentCreate(dcBlog $blog, cursor $cur): void
{
- if ($cur->comment_trackback) {
- return null;
+ if ($cur->getField('comment_trackback')) {
+ return;
}
- $posts = dcCore::app()->blog->getPosts(['post_id' => $cur->post_id, 'limit' => 1]);
- $logs = [
- $cur->comment_author,
- $posts->post_title,
- dcCore::app()->blog->url . dcCore::app()->url->getBase($posts->post_type) .
- '/' . $posts->post_url . '#c' . $cur->comment_id,
- ];
- dcCore::app()->activityReport->addLog('comment', 'create', $logs);
- }
-
- public static function commentUpdate($blog, $cur, $old)
- {
- $posts = dcCore::app()->blog->getPosts(['post_id' => $old->post_id, 'limit' => 1]);
-
- $logs = [
- dcCore::app()->auth->getInfo('user_cn'),
- $posts->post_title,
- dcCore::app()->blog->url . dcCore::app()->url->getBase($posts->post_type) .
- '/' . $posts->post_url . '#c' . $old->comment_id,
- ];
- dcCore::app()->activityReport->addLog('comment', 'update', $logs);
- }
-
- public static function trackbackCreate($cur, $comment_id)
- {
- // From blog args are $blog, $cur #thks to bruno
- $c = $cur instanceof dcBlog ? $comment_id : $cur;
- if (!$c->comment_trackback || !$c->comment_site) {
- return null;
- }
- $posts = dcCore::app()->blog->getPosts(
- ['post_id' => $c->post_id, 'no_content' => true, 'limit' => 1]
+ $posts = dcCore::app()->blog?->getPosts(
+ ['post_id' => $cur->getField('post_id'), 'limit' => 1, 'post_type' => '']
);
- if ($posts->isEmpty()) {
- return null;
+ if (!$posts || $posts->isEmpty()) {
+ return;
}
+
$logs = [
- $c->comment_author,
- $c->comment_site,
- $posts->post_title,
- dcCore::app()->blog->url . dcCore::app()->url->getBase($posts->post_type) .
- '/' . $posts->post_url,
+ (string) $cur->getField('comment_author'),
+ (string) $posts->f('post_title'),
+ (string) dcCore::app()->blog?->url . dcCore::app()->url->getBase((string) $posts->f('post_type')) .
+ '/' . $posts->f('post_url') . '#c' . $cur->getField('comment_id'),
];
- dcCore::app()->activityReport->addLog('comment', 'trackback', $logs);
+ ActivityReport::instance()->addLog('comment', 'create', $logs);
}
- public static function categoryCreate($cur, $cat_id)
+ public static function commentUpdate(dcBlog $blog, cursor $cur, dcRecord $old): void
+ {
+ $posts = dcCore::app()->blog?->getPosts(
+ ['post_id' => $old->f('post_id'), 'limit' => 1]
+ );
+ if (!$posts || $posts->isEmpty()) {
+ return;
+ }
+
+ $logs = [
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
+ (string) $posts->f('post_title'),
+ (string) dcCore::app()->blog?->url . dcCore::app()->url->getBase((string) $posts->f('post_type')) .
+ '/' . $posts->f('post_url') . '#c' . $old->f('comment_id'),
+ ];
+ ActivityReport::instance()->addLog('comment', 'update', $logs);
+ }
+
+ public static function trackbackCreate(dcBlog $blog, cursor $cur): void
+ {
+ if (!$cur->getField('comment_trackback')) {
+ return;
+ }
+
+ $posts = dcCore::app()->blog?->getPosts(
+ ['post_id' => $cur->getField('post_id'), 'no_content' => true, 'limit' => 1]
+ );
+ if (!$posts || $posts->isEmpty()) {
+ return;
+ }
+
+ $logs = [
+ (string) $cur->getField('comment_author'),
+ (string) $cur->getField('comment_site'),
+ (string) $posts->f('post_title'),
+ (string) dcCore::app()->blog?->url . dcCore::app()->url->getBase($posts->f('post_type')) .
+ '/' . $posts->f('post_url'),
+ ];
+ ActivityReport::instance()->addLog('comment', 'trackback', $logs);
+ }
+
+ public static function categoryCreate(cursor $cur, int $cat_id): void
{
$logs = [
- $cur->cat_title,
- dcCore::app()->auth->getInfo('user_cn'),
- dcCore::app()->blog->url . dcCore::app()->url->getBase('category') . '/' . $cur->cat_url,
+ (string) $cur->getField('cat_title'),
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
+ (string) dcCore::app()->blog?->url . dcCore::app()->url->getBase('category') . '/' . $cur->getField('cat_url'),
];
- dcCore::app()->activityReport->addLog('category', 'create', $logs);
+ ActivityReport::instance()->addLog('category', 'create', $logs);
}
- public static function categoryUpdate($cur, $cat_id)
+ public static function categoryUpdate(cursor $cur, int $cat_id): void
{
$logs = [
- $cur->cat_title,
- dcCore::app()->auth->getInfo('user_cn'),
- dcCore::app()->blog->url . dcCore::app()->url->getBase('category') . '/' . $cur->cat_url,
+ (string) $cur->getField('cat_title'),
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
+ (string) dcCore::app()->blog?->url . dcCore::app()->url->getBase('category') . '/' . $cur->getField('cat_url'),
];
- dcCore::app()->activityReport->addLog('category', 'update', $logs);
+ ActivityReport::instance()->addLog('category', 'update', $logs);
}
- public static function userCreate($cur, $user_id)
+ public static function userCreate(cursor $cur, string $user_id): void
{
$user_cn = dcUtils::getUserCN(
- $cur->user_id,
- $cur->user_name,
- $cur->user_firstname,
- $cur->user_displayname
+ $cur->getField('user_id'),
+ $cur->getField('user_name'),
+ $cur->getField('user_firstname'),
+ $cur->getField('user_displayname')
);
$logs = [
- $user_cn,
- dcCore::app()->auth->getInfo('user_cn'),
+ (string) $user_cn,
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
];
- dcCore::app()->activityReport->addLog('user', 'create', $logs);
+ ActivityReport::instance()->addLog('user', 'create', $logs);
}
- public static function usertUpdate($cur, $user_id)
+ public static function userUpdate(cursor $cur, string $user_id): void
{
$user_cn = dcUtils::getUserCN(
- $cur->user_id,
- $cur->user_name,
- $cur->user_firstname,
- $cur->user_displayname
+ $cur->getField('user_id'),
+ $cur->getField('user_name'),
+ $cur->getField('user_firstname'),
+ $cur->getField('user_displayname')
);
$logs = [
- $user_cn,
- dcCore::app()->auth->getInfo('user_cn'),
+ (string) $user_cn,
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
];
- dcCore::app()->activityReport->addLog('user', 'update', $logs);
+ ActivityReport::instance()->addLog('user', 'update', $logs);
}
- public static function userDelete($user_id)
+ public static function userPreference(cursor $cur, string $user_id): void
+ {
+ $user_cn = dcUtils::getUserCN(
+ $cur->getField('user_id'),
+ $cur->getField('user_name'),
+ $cur->getField('user_firstname'),
+ $cur->getField('user_displayname')
+ );
+ $logs = [
+ (string) $user_cn,
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
+ ];
+ ActivityReport::instance()->addLog('user', 'preference', $logs);
+ }
+
+ public static function userDelete(string $user_id): void
{
$users = dcCore::app()->getUser($user_id);
$user_cn = dcUtils::getUserCN(
- $users->user_id,
- $users->user_name,
- $users->user_firstname,
- $users->user_displayname
+ $users->f('user_id'),
+ $users->f('user_name'),
+ $users->f('user_firstname'),
+ $users->f('user_displayname')
);
$logs = [
- $user_cn,
- dcCore::app()->auth->getInfo('user_cn'),
+ (string) $user_cn,
+ (string) dcCore::app()->auth?->getInfo('user_cn'),
];
- dcCore::app()->activityReport->addLog('user', 'delete', $logs);
+ ActivityReport::instance()->addLog('user', 'delete', $logs);
}
}
diff --git a/src/ActivityReport.php b/src/ActivityReport.php
index 005cf55..030d062 100644
--- a/src/ActivityReport.php
+++ b/src/ActivityReport.php
@@ -10,287 +10,257 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_RC_PATH')) {
- return;
-}
+declare(strict_types=1);
-class activityReport
+namespace Dotclear\Plugin\activityReport;
+
+use ArrayObject;
+use dcAuth;
+use dcBlog;
+use dcCore;
+use dcRecord;
+use Dotclear\Database\Statement\{
+ DeleteStatement,
+ JoinStatement,
+ SelectStatement,
+ UpdateStatement
+};
+use Dotclear\Helper\Crypt;
+use Dotclear\Helper\Date;
+use Dotclear\Helper\File\{
+ Files,
+ Path
+};
+use Dotclear\Helper\Network\Mail\Mail;
+use Dotclear\Helper\Text;
+use Exception;
+
+/**
+ * Activity report main class.
+ */
+class ActivityReport
{
- public $con;
+ /** @var int activity marked as pending mail report */
+ public const STATUS_PENDING = 0;
- private $ns = null;
- private $_global = 0;
- private $blog = null;
- private $groups = [];
- private $settings = [];
- private $lock_blog = null;
- private $lock_global = null;
+ /** @var int activity marked as reported by mail */
+ public const STATUS_REPORTED = 1;
- public function __construct($ns = null)
+ /** @var string $type Activity report type (by default activityReport) */
+ public readonly string $type;
+
+ /** @var Settings $settings Activity report settings for current blog */
+ public readonly Settings $settings;
+
+ /** @var Groups $groups Groups of actions */
+ public readonly Groups $groups;
+
+ /** @var Formats $formats Export available formats */
+ public readonly Formats $formats;
+
+ /** @var ActivityReport $instance ActivityReport instance */
+ private static $instance;
+
+ private $lock = null;
+
+ /**
+ * Constructor sets activity main type.
+ *
+ * @param string $type The activity report type
+ */
+ public function __construct(string $type = null)
{
- $this->con = dcCore::app()->con;
- $this->blog = dcCore::app()->con->escape(dcCore::app()->blog->id);
- $this->ns = dcCore::app()->con->escape($ns ?? basename(dirname(__DIR__)));
-
- $this->getSettings();
+ $this->type = $type ?? My::id();
+ $this->settings = new Settings();
+ $this->groups = new Groups();
+ $this->formats = new Formats();
# Check if some logs are too olds
$this->obsoleteLogs();
}
- public function setGlobal()
+ /**
+ * Get singleton instance.
+ *
+ * @return ActivityReport ActivityReport instance
+ */
+ public static function instance(): ActivityReport
{
- $this->_global = 1;
- }
-
- public function unsetGlobal()
- {
- $this->_global = 0;
- }
-
- public function getGroups($group = null, $action = null)
- {
- if ($action !== null) {
- return $this->groups[$group]['actions'][$action] ?? null;
- } elseif ($group !== null) {
- return $this->groups[$group] ?? null;
+ if (!is_a(self::$instance, ActivityReport::class)) {
+ self::$instance = new ActivityReport();
}
- return $this->groups;
+ return self::$instance;
}
- public function addGroup($group, $title)
+ /**
+ * Get logs record.
+ *
+ * @param null|ArrayObject $params The query params
+ * @param bool $count_only Count only
+ * @param null|SelectStatement $ext_sql The sql select statement
+ *
+ * @return null|dcRecord The logs record
+ */
+ public function getLogs(ArrayObject $params = null, bool $count_only = false, ?SelectStatement $ext_sql = null): ?dcRecord
{
- $this->groups[$group] = [
- 'title' => $title,
- 'actions' => [],
- ];
-
- return true;
- }
-
- public function addAction($group, $action, $title, $msg, $behavior, $function)
- {
- if (!isset($this->groups[$group])) {
- return false;
+ if (null === $params) {
+ $params = new ArrayObject();
}
- $this->groups[$group]['actions'][$action] = [
- 'title' => $title,
- 'msg' => $msg,
- ];
- dcCore::app()->addBehavior($behavior, $function);
+ $sql = $ext_sql ? clone $ext_sql : new SelectStatement();
- return true;
- }
-
- private function getSettings()
- {
- $settings = [
- 'active' => false,
- 'obsolete' => 2419200,
- 'interval' => 86400,
- 'lastreport' => 0,
- 'mailinglist' => [],
- 'mailformat' => 'plain',
- 'dateformat' => '%Y-%m-%d %H:%M:%S',
- 'requests' => [],
- 'blogs' => [],
- ];
-
- $this->settings[0] = $this->settings[1] = $settings;
-
- $rs = $this->con->select(
- 'SELECT setting_id, setting_value, blog_id ' .
- 'FROM ' . dcCore::app()->prefix . initActivityReport::SETTING_TABLE_NAME . ' ' .
- "WHERE setting_type='" . $this->ns . "' " .
- "AND (blog_id='" . $this->blog . "' OR blog_id IS NULL) " .
- 'ORDER BY setting_id DESC '
- );
-
- while ($rs->fetch()) {
- $k = $rs->f('setting_id');
- $v = $rs->f('setting_value');
- $b = $rs->f('blog_id');
- $g = $b === null ? 1 : 0;
-
- if (isset($settings[$k])) {
- $this->settings[$g][$k] = self::decode($v);
- }
- }
- # Force blog
- $this->settings[0]['blogs'] = [0 => $this->blog];
- }
-
- public function getSetting($n)
- {
- return $this->settings[$this->_global][$n] ?? null;
- }
-
- public function setSetting($n, $v)
- {
- if (!isset($this->settings[$this->_global][$n])) {
- return null;
- }
-
- $c = $this->delSetting($n);
-
- $cur = $this->con->openCursor(dcCore::app()->prefix . initActivityReport::SETTING_TABLE_NAME);
- $this->con->writeLock(dcCore::app()->prefix . initActivityReport::SETTING_TABLE_NAME);
-
- $cur->blog_id = $this->_global ? null : $this->blog;
- $cur->setting_id = $this->con->escape($n);
- $cur->setting_type = $this->ns;
- $cur->setting_value = (string) self::encode($v);
-
- $cur->insert();
- $this->con->unlock();
-
- $this->settings[$this->_global][$n] = $v;
-
- return true;
- }
-
- private function delSetting($n)
- {
- return $this->con->execute(
- 'DELETE FROM ' . dcCore::app()->prefix . initActivityReport::SETTING_TABLE_NAME . ' ' .
- 'WHERE blog_id' . ($this->_global ? ' IS NULL' : "='" . $this->blog . "'") . ' ' .
- "AND setting_id='" . $this->con->escape($n) . "' " .
- "AND setting_type='" . $this->ns . "' "
- );
- }
-
- // Action params to put in params['sql']
- public static function requests2params($requests)
- {
- $r = [];
- foreach ($requests as $group => $actions) {
- foreach ($actions as $action => $is) {
- $r[] = "activity_group='" . $group . "' AND activity_action='" . $action . "' ";
- }
- }
-
- return empty($r) ? '' : 'AND (' . implode('OR ', $r) . ') ';
- }
-
- public function getLogs($p, $count_only = false)
- {
if ($count_only) {
- $r = 'SELECT count(E.activity_id) ';
+ $sql->column($sql->count($sql->unique('E.activity_id')));
} else {
- $content_r = empty($p['no_content']) ? 'activity_logs, ' : '';
-
- if (!empty($p['columns']) && is_array($p['columns'])) {
- $content_r .= implode(', ', $p['columns']) . ', ';
+ if (empty($params['no_content'])) {
+ $sql->columns([
+ 'activity_logs',
+ ]);
}
-
- $r = 'SELECT E.activity_id, E.blog_id, B.blog_url, B.blog_name, ' . $content_r .
- 'E.activity_group, E.activity_action, E.activity_dt, ' .
- 'E.activity_blog_status, E.activity_super_status ';
- }
-
- $r .= 'FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' E ' .
- 'LEFT JOIN ' . dcCore::app()->prefix . dcBlog::BLOG_TABLE_NAME . ' B on E.blog_id=B.blog_id ';
-
- if (!empty($p['from'])) {
- $r .= $p['from'] . ' ';
- }
-
- if ($this->_global) {
- $r .= 'WHERE E.activity_super_status = 0 ';
- } else {
- $r .= 'WHERE E.activity_blog_status = 0 ';
- }
-
- if (!empty($p['activity_type'])) {
- $r .= "AND E.activity_type = '" . $this->con->escape($p['activity_type']) . "' ";
- } else {
- $r .= "AND E.activity_type = '" . $this->ns . "' ";
- }
-
- if (!empty($p['blog_id'])) {
- if (is_array($p['blog_id'])) {
- $r .= 'AND E.blog_id' . $this->con->in($p['blog_id']);
- } else {
- $r .= "AND E.blog_id = '" . $this->con->escape($p['blog_id']) . "' ";
+ if (!empty($params['columns']) && is_array($params['columns'])) {
+ $sql->columns($params['columns']);
}
- } elseif ($this->_global) {
- $r .= 'AND E.blog_id IS NOT NULL ';
- } else {
- $r .= "AND E.blog_id='" . $this->blog . "' ";
+ $sql->columns([
+ 'E.activity_id',
+ 'E.blog_id',
+ 'B.blog_url',
+ 'B.blog_name',
+ 'E.activity_group',
+ 'E.activity_action',
+ 'E.activity_dt',
+ 'E.activity_status',
+ ]);
+ }
+ $sql
+ ->from($sql->as(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME, 'E'), false, true)
+ ->join(
+ (new JoinStatement())
+ ->left()
+ ->from($sql->as(dcCore::app()->prefix . dcBlog::BLOG_TABLE_NAME, 'B'))
+ ->on('E.blog_id = B.blog_id')
+ ->statement()
+ );
+
+ if (!empty($params['join'])) {
+ $sql->join($params['join']);
}
- if (isset($p['activity_group'])) {
- if (is_array($p['activity_group']) && !empty($p['activity_group'])) {
- $r .= 'AND E.activity_group ' . $this->con->in($p['activity_group']);
- } elseif ($p['activity_group'] != '') {
- $r .= "AND E.activity_group = '" . $this->con->escape($p['activity_group']) . "' ";
+ if (!empty($params['from'])) {
+ $sql->from($params['from']);
+ }
+
+ if (!empty($params['where'])) {
+ //nope
+ }
+
+ if (!empty($params['activity_type'])) {
+ $sql->where('E.activity_type = ' . $sql->quote($params['activity_type']));
+ } else {
+ $sql->where('E.activity_type = ' . $sql->quote($this->type));
+ }
+
+ if (!empty($params['blog_id'])) {
+ if (!is_array($params['blog_id'])) {
+ $params['blog_id'] = [$params['blog_id']];
+ }
+ $sql->and('E.blog_id' . $sql->in($params['blog_id']));
+ } elseif (is_null($params['blog_id'])) {
+ $sql->and('E.blog_id IS NOT NULL');
+ } else {
+ $sql->and('E.blog_id = ' . $sql->quote((string) dcCore::app()->blog?->id));
+ }
+
+ if (isset($params['activity_status'])) {
+ $sql->and('E.activity_status = ' . ((int) $params['activity_tatus']) . ' ');
+ }
+ //$sql->and('E.activity_status = ' . self::STATUS_PENDING);
+
+ if (isset($params['activity_group'])) {
+ if (!is_array($params['activity_group'])) {
+ $params['activity_group'] = [$params['activity_group']];
+ }
+ $sql->and('E.activity_group' . $sql->in($params['activity_group']));
+ }
+
+ if (isset($params['activity_action'])) {
+ if (!is_array($params['activity_action'])) {
+ $params['activity_action'] = [$params['activity_action']];
+ }
+ $sql->and('E.activity_action' . $sql->in($params['activity_action']));
+ }
+
+ if (isset($params['from_date_ts'])) {
+ $sql->and("E.activity_dt >= TIMESTAMP '" . date('Y-m-d H:i:s', $params['from_date_ts']) . "' ");
+ }
+ if (isset($params['to_date_ts'])) {
+ $sql->and("E.activity_dt < TIMESTAMP '" . date('Y-m-d H:i:s', $params['to_date_ts']) . "' ");
+ }
+
+ if (!empty($params['requests'])) {
+ $or = [];
+ foreach ($this->settings->requests as $group => $actions) {
+ if (empty($actions)) {
+ continue;
+ }
+ foreach ($actions as $action => $is) {
+ $or[] = $sql->andGroup(['activity_group = ' . $sql->quote($group), 'activity_action = ' . $sql->quote($action)]);
+ }
+ }
+ if (empty($or)) {
+ $sql->and($sql->orGroup($or));
}
}
- if (isset($p['activity_action'])) {
- if (is_array($p['activity_action']) && !empty($p['activity_action'])) {
- $r .= 'AND E.activity_action ' . $this->con->in($p['activity_action']);
- } elseif ($p['activity_action'] != '') {
- $r .= "AND E.activity_action = '" . $this->con->escape($p['activity_action']) . "' ";
- }
- }
-
- if (isset($p['activity_blog_status'])) {
- $r .= 'AND E.activity_blog_status = ' . ((int) $p['activity_blog_status']) . ' ';
- }
-
- if (isset($p['activity_super_status'])) {
- $r .= 'AND E.activity_super_status = ' . ((int) $p['activity_super_status']) . ' ';
- }
-
- if (isset($p['from_date_ts'])) {
- $dt = date('Y-m-d H:i:s', $p['from_date_ts']);
- $r .= "AND E.activity_dt >= TIMESTAMP '" . $dt . "' ";
- }
- if (isset($p['to_date_ts'])) {
- $dt = date('Y-m-d H:i:s', $p['to_date_ts']);
- $r .= "AND E.activity_dt < TIMESTAMP '" . $dt . "' ";
- }
-
- if (!empty($p['sql'])) {
- $r .= $p['sql'] . ' ';
+ if (!empty($params['sql'])) {
+ $sql->sql($params['sql']);
}
if (!$count_only) {
- if (!empty($p['order'])) {
- $r .= 'ORDER BY ' . $this->con->escape($p['order']) . ' ';
+ if (!empty($params['order'])) {
+ $sql->order($sql->escape($params['order']));
} else {
- $r .= 'ORDER BY E.activity_dt DESC ';
+ $sql->order('E.activity_dt DESC');
}
}
- if (!$count_only && !empty($p['limit'])) {
- $r .= $this->con->limit($p['limit']);
+ if (!$count_only && !empty($params['limit'])) {
+ $sql->limit($params['limit']);
}
+ $rs = $sql->select();
- return $this->con->select($r);
+ return $sql->select();
}
- public function addLog($group, $action, $logs)
+ /**
+ * Add a log.
+ *
+ * @param string $group The group
+ * @param string $action The action
+ * @param array $logs The logs values
+ */
+ public function addLog(string $group, string $action, array $logs): void
{
try {
- $cur = $this->con->openCursor(dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME);
- $this->con->writeLock(dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME);
+ $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME);
+ dcCore::app()->con->writeLock(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME);
- $cur->activity_id = $this->getNextId();
- $cur->activity_type = $this->ns;
- $cur->blog_id = $this->blog;
- $cur->activity_group = $this->con->escape((string) $group);
- $cur->activity_action = $this->con->escape((string) $action);
- $cur->activity_logs = self::encode($logs);
- $cur->activity_dt = date('Y-m-d H:i:s');
+ $cur->setField('activity_id', $this->getNextId());
+ $cur->setField('activity_type', $this->type);
+ $cur->setField('blog_id', (string) dcCore::app()->blog?->id);
+ $cur->setField('activity_group', $group);
+ $cur->setField('activity_action', $action);
+ $cur->setField('activity_logs', json_encode($logs));
+ $cur->setField('activity_dt', date('Y-m-d H:i:s'));
+ $cur->setField('activity_status', self::STATUS_PENDING);
$cur->insert();
- $this->con->unlock();
+ dcCore::app()->con->unlock();
+
+ # --BEHAVIOR-- coreAfterCategoryCreate -- ActivityReport, cursor
+ dcCore::app()->callBehavior('activityReportAfteAddLog', $this, $cur);
} catch (Exception $e) {
- $this->con->unlock();
+ dcCore::app()->con->unlock();
dcCore::app()->error->add($e->getMessage());
}
@@ -298,77 +268,50 @@ class activityReport
$this->needReport();
}
- private function parseLogs($rs)
+ /**
+ * Parse logs using a format.
+ *
+ * @param dcRecord $rs The logs record
+ *
+ * @return string The parsed logs
+ */
+ private function parseLogs(dcRecord $rs): string
{
- if ($rs->isEmpty()) {
- return '';
- }
-
- // @todo move this in function
- include __DIR__ . '/lib.parselogs.config.php';
-
- $from = time();
- $to = 0;
- $res = $blog = $group = '';
- $tz = $this->_global ? 'UTC' : dcCore::app()->blog->settings->system->blog_timezone;
-
- $dt = $this->settings[$this->_global]['dateformat'];
- $dt = empty($dt) ? '%Y-%m-%d %H:%M:%S' : $dt;
-
- $tpl = $this->settings[$this->_global]['mailformat'];
- $tpl = $tpl == 'html' ? $format['html'] : $format['plain'];
-
- $blog_open = $group_open = false;
+ $from = time();
+ $to = 0;
+ $res = $blog = $group = '';
+ $tz = dcCore::app()->blog?->settings->get('system')->get('blog_timezone');
+ $dt = empty($this->settings->dateformat) ? '%Y-%m-%d %H:%M:%S' : $this->settings->dateformat;
+ $format = $this->formats->get($this->formats->has($this->settings->mailformat) ? $this->settings->mailformat : 'plain');
+ $group_open = false;
while ($rs->fetch()) {
- // blog
- if ($rs->blog_id != $blog && $this->_global) {
- if ($group_open) {
- $res .= $tpl['group_close'];
- $group_open = false;
- }
- if ($blog_open) {
- $res .= $tpl['blog_close'];
- }
-
- $blog = $rs->blog_id;
- $group = '';
-
- $res .= str_replace(
- ['%TEXT%', '%URL%'],
- [$rs->blog_name . ' (' . $rs->blog_id . ')', $rs->blog_url],
- $tpl['blog_title']
- ) . $tpl['blog_open'];
-
- $blog_open = true;
- }
-
- if (isset($this->groups[$rs->activity_group])) {
+ if ($this->groups->has($rs->f('activity_group')) && $this->groups->get($rs->f('activity_group'))->has($rs->f('activity_action'))) {
// Type
- if ($rs->activity_group != $group) {
+ if ($rs->f('activity_group') != $group) {
if ($group_open) {
- $res .= $tpl['group_close'];
+ $res .= $format->group_close;
}
- $group = $rs->activity_group;
+ $group = $rs->f('activity_group');
$res .= str_replace(
'%TEXT%',
- __($this->groups[$group]['title']),
- $tpl['group_title']
- ) . $tpl['group_open'];
+ __($this->groups->get($group)->title),
+ $format->group_title
+ ) . $format->group_open;
$group_open = true;
}
// Action
- $time = strtotime($rs->activity_dt);
- $data = self::decode($rs->activity_logs);
+ $time = strtotime($rs->f('activity_dt'));
+ $data = json_decode($rs->f('activity_logs'), true);
$res .= str_replace(
['%TIME%', '%TEXT%'],
- [dt::str($dt, $time, $tz), vsprintf(__($this->groups[$group]['actions'][$rs->activity_action]['msg']), $data)],
- $tpl['action']
+ [Date::str($dt, (int) $time, $tz), vsprintf(__($this->groups->get($group)->get($rs->f('activity_action'))->message), $data)],
+ $format->action
);
# Period
@@ -382,13 +325,10 @@ class activityReport
}
if ($group_open) {
- $res .= $tpl['group_close'];
- }
- if ($blog_open) {
- $res .= $tpl['blog_close'];
+ $res .= $format->group_close;
}
if ($to == 0) {
- $res .= str_replace('%TEXT%', __('An error occured when parsing report.'), $tpl['error']);
+ $res .= str_replace('%TEXT%', __('An error occured when parsing report.'), $format->error);
}
// Top of msg
@@ -399,127 +339,143 @@ class activityReport
$period = str_replace(
'%TEXT%',
__('Activity report'),
- $tpl['period_title']
- ) . $tpl['period_open'];
+ $format->period_title
+ ) . $format->period_open;
$period .= str_replace(
'%TEXT%',
__("You received a message from your blog's activity report module."),
- $tpl['info']
+ $format->info
);
- if (!$this->_global) {
- $period .= str_replace('%TEXT%', $rs->blog_name, $tpl['info']);
- $period .= str_replace('%TEXT%', $rs->blog_url, $tpl['info']);
- }
+
+ $period .= str_replace('%TEXT%', $rs->f('blog_name'), $format->info);
+ $period .= str_replace('%TEXT%', $rs->f('blog_url'), $format->info);
+
$period .= str_replace(
'%TEXT%',
- sprintf(__('Period from %s to %s'), dt::str($dt, $from, $tz), dt::str($dt, $to, $tz)),
- $tpl['info']
+ sprintf(__('Period from %s to %s'), Date::str($dt, (int) $from, $tz), Date::str($dt, (int) $to, $tz)),
+ $format->info
);
- $period .= $tpl['period_close'];
+ $period .= $format->period_close;
- $res = str_replace(['%PERIOD%', '%TEXT%'], [$period, $res], $tpl['page']);
+ $res = str_replace(['%PERIOD%', '%TEXT%'], [$period, $res], $format->page);
return $res;
}
- private function obsoleteLogs()
+ /**
+ * Delete obsolete logs.
+ */
+ private function obsoleteLogs(): void
{
// Get blogs and logs count
- $rs = $this->con->select(
- 'SELECT blog_id ' .
- 'FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ' .
- "WHERE activity_type='" . $this->ns . "' " .
- 'GROUP BY blog_id '
- );
+ $sql = new SelectStatement();
+ $sql->from(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME)
+ ->where('activity_type =' . $sql->quote($this->type))
+ ->group('blog_id');
- if ($rs->isEmpty()) {
- return null;
+ $rs = $sql->select();
+
+ if (!$rs || $rs->isEmpty()) {
+ return;
}
while ($rs->fetch()) {
- $ts = time();
- $obs_blog = dt::str('%Y-%m-%d %H:%M:%S', $ts - (int) $this->settings[0]['obsolete']);
- $obs_global = dt::str('%Y-%m-%d %H:%M:%S', $ts - (int) $this->settings[1]['obsolete']);
+ $ts = time();
+ $obs = Date::str('%Y-%m-%d %H:%M:%S', $ts - (int) $this->settings->obsolete);
- $this->con->execute(
- 'DELETE FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ' .
- "WHERE activity_type='" . $this->ns . "' " .
- "AND (activity_dt < TIMESTAMP '" . $obs_blog . "' " .
- "OR activity_dt < TIMESTAMP '" . $obs_global . "') " .
- "AND blog_id = '" . $this->con->escape($rs->blog_id) . "' "
- );
+ $sql = new DeleteStatement();
+ $sql->from(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME)
+ ->where('activity_type =' . $sql->quote($this->type))
+ ->and('activity_dt < TIMESTAMP ' . $sql->quote($obs))
+ ->and('blog_id = ' . $sql->quote($rs->f('blog_id')))
+ ->delete();
- if ($this->con->changes()) {
+ if (dcCore::app()->con->changes()) {
try {
- $cur = $this->con->openCursor(dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME);
- $this->con->writeLock(dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME);
+ $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME);
+ dcCore::app()->con->writeLock(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME);
- $cur->activity_id = $this->getNextId();
- $cur->activity_type = $this->ns;
- $cur->blog_id = $rs->blog_id;
- $cur->activity_group = 'activityReport';
- $cur->activity_action = 'message';
- $cur->activity_logs = self::encode(__('Activity report deletes some old logs.'));
- $cur->activity_dt = date('Y-m-d H:i:s');
+ $cur->setField('activity_id', $this->getNextId());
+ $cur->setField('activity_type', $this->type);
+ $cur->setField('blog_id', $rs->f('blog_id'));
+ $cur->setField('activity_group', My::id());
+ $cur->setField('activity_action', 'message');
+ $cur->setField('activity_logs', json_encode([__('Activity report deletes some old logs.')]));
+ $cur->setField('activity_dt', date('Y-m-d H:i:s'));
+ $cur->setField('activity_status', self::STATUS_PENDING);
$cur->insert();
- $this->con->unlock();
+ dcCore::app()->con->unlock();
} catch (Exception $e) {
- $this->con->unlock();
+ dcCore::app()->con->unlock();
dcCore::app()->error->add($e->getMessage());
}
}
}
}
- private function cleanLogs()
+ /**
+ * Delete logs.
+ *
+ * @param bool $only_reported Delete only allready reported logs
+ *
+ * @return bool Action done
+ */
+ public function deleteLogs(bool $only_reported = false): bool
{
- $this->con->execute(
- 'DELETE FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ' .
- "WHERE activity_type='" . $this->ns . "' " .
- 'AND activity_blog_status = 1 ' .
- 'AND activity_super_status = 1 '
- );
- }
+ $sql = new DeleteStatement();
- public function deleteLogs()
- {
- if (!dcCore::app()->auth->isSuperAdmin()) {
- return null;
+ if ($only_reported) {
+ $sql->and('activity_status = ' . self::STATUS_REPORTED);
}
- return $this->con->execute(
- 'DELETE FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ' .
- "WHERE activity_type='" . $this->ns . "' "
- );
+ return $sql->from(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME)
+ ->where('activity_type = ' . $sql->quote($this->type))
+ ->delete();
}
- private function updateStatus($from_date_ts, $to_date_ts)
+ /**
+ * Update logs status according to time interval.
+ *
+ * @param int $from_date_ts The start time
+ * @param int $to_date_ts The end time
+ */
+ private function updateStatus(int $from_date_ts, int $to_date_ts): void
{
- $r = 'UPDATE ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME . ' ';
-
- if ($this->_global) {
- $r .= 'SET activity_super_status = 1 WHERE blog_id IS NOT NULL ';
- } else {
- $r .= "SET activity_blog_status = 1 WHERE blog_id = '" . $this->blog . "' ";
- }
- $r .= "AND activity_type = '" . $this->ns . "' " .
- "AND activity_dt >= TIMESTAMP '" . date('Y-m-d H:i:s', $from_date_ts) . "' " .
- "AND activity_dt < TIMESTAMP '" . date('Y-m-d H:i:s', $to_date_ts) . "' ";
-
- $this->con->execute($r);
+ $sql = new UpdateStatement();
+ $sql->from(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME)
+ ->column('activity_status')
+ ->set((string) self::STATUS_REPORTED)
+ ->where('blog_id = ' . $sql->quote((string) dcCore::app()->blog?->id))
+ ->and('activity_type =' . $sql->quote($this->type))
+ ->and('activity_dt >= TIMESTAMP ' . $sql->quote(date('Y-m-d H:i:s', $from_date_ts)))
+ ->and('activity_dt < TIMESTAMP ' . $sql->quote(date('Y-m-d H:i:s', $to_date_ts)))
+ ->update();
}
- public function getNextId()
+ /**
+ * Get next activity ID.
+ *
+ * @return int The next id
+ */
+ public function getNextId(): int
{
- return $this->con->select(
- 'SELECT MAX(activity_id) FROM ' . dcCore::app()->prefix . initActivityReport::ACTIVITY_TABLE_NAME
- )->f(0) + 1;
+ $sql = new SelectStatement();
+ $sql->from(dcCore::app()->prefix . My::ACTIVITY_TABLE_NAME)
+ ->column($sql->max('activity_id'));
+
+ return (int) $sql->select()?->f(0) + 1;
}
- # Lock a file to see if an update is ongoing
- public function lockUpdate()
+ /**
+ * Lock update.
+ *
+ * Lock a file to see if an update is ongoing.
+ *
+ * @return bool The lock success
+ */
+ public function lockUpdate(): bool
{
try {
# Need flock function
@@ -531,20 +487,20 @@ class activityReport
throw new Exception("Can't write in cache fodler");
}
# Set file path
- $f_md5 = $this->_global ? md5(DC_MASTER_KEY) : md5($this->blog);
+ $f_md5 = md5((string) dcCore::app()->blog?->id);
$cached_file = sprintf(
'%s/%s/%s/%s/%s.txt',
DC_TPL_CACHE,
- initActivityReport::CACHE_DIR_NAME,
+ My::CACHE_DIR_NAME,
substr($f_md5, 0, 2),
substr($f_md5, 2, 2),
$f_md5
);
# Real path
- $cached_file = path::real($cached_file, false);
+ $cached_file = (string) Path::real($cached_file, false);
// make dir
if (!is_dir(dirname($cached_file))) {
- files::makeDir(dirname($cached_file), true);
+ Files::makeDir(dirname($cached_file), true);
}
//ake file
if (!file_exists($cached_file)) {
@@ -564,38 +520,45 @@ class activityReport
//throw new Exception("Can't lock file");
return false;
}
- if ($this->_global) {
- $this->lock_global = $fp;
- } else {
- $this->lock_blog = $fp;
- }
+
+ $this->lock = $fp;
return true;
} catch (Exception $e) {
// what ?
throw $e;
}
-
- return false;
}
- public function unlockUpdate()
+ /**
+ * Unlock update.
+ */
+ public function unlockUpdate(): void
{
- if ($this->_global) {
- @fclose($this->lock_global);
- $this->lock_global = null;
- } elseif ($this->lock_blog) {
- @fclose($this->lock_blog);
- $this->lock_blog = null;
+ if ($this->lock) {
+ @fclose($this->lock);
+ $this->lock = null;
}
}
- public static function hasMailer()
+ /**
+ * Check if doctclear has maisl fonction.
+ *
+ * @return bool has mailer
+ */
+ public static function hasMailer(): bool
{
return function_exists('mail') || function_exists('_mail');
}
- public function needReport($force = false)
+ /**
+ * Check if blog need report to be sent and send it.
+ *
+ * @param bool $force Force to send report
+ *
+ * @return bool The success
+ */
+ public function needReport(bool $force = false): bool
{
try {
// Check if server has mail function
@@ -609,33 +572,33 @@ class activityReport
$send = false;
$now = time();
- $active = (bool) $this->settings[$this->_global]['active'];
- $mailinglist = $this->settings[$this->_global]['mailinglist'];
- $mailformat = $this->settings[$this->_global]['mailformat'];
- $requests = $this->settings[$this->_global]['requests'];
- $lastreport = (int) $this->settings[$this->_global]['lastreport'];
- $interval = (int) $this->settings[$this->_global]['interval'];
- $blogs = $this->settings[$this->_global]['blogs'];
+ $mailinglist = $this->settings->mailinglist;
+ $mailformat = $this->settings->mailformat;
+ $requests = $this->settings->requests;
+ $lastreport = $this->settings->lastreport;
+ $interval = $this->settings->interval;
if ($force) {
$lastreport = 0;
}
// Check if report is needed
- if ($active && !empty($mailinglist) && !empty($requests) && !empty($blogs)
- && ($lastreport + $interval) < $now
+ if (!empty($mailinglist)
+ && !empty($requests)
+ && ($lastreport + $interval) < $now
) {
// Get datas
- $params = [
- 'from_date_ts' => $lastreport,
- 'to_date_ts' => $now,
- 'blog_id' => $blogs,
- 'sql' => self::requests2params($requests),
- 'order' => 'blog_id ASC, activity_group ASC, activity_action ASC, activity_dt ASC ',
- ];
+ $params = new ArrayObject([
+ 'from_date_ts' => $lastreport,
+ 'to_date_ts' => $now,
+ 'blog_id' => dcCore::app()->blog?->id,
+ 'activity_status' => self::STATUS_PENDING,
+ 'requests' => true,
+ 'order' => 'activity_group ASC, activity_action ASC, activity_dt ASC ',
+ ]);
$logs = $this->getLogs($params);
- if (!$logs->isEmpty()) {
+ if ($logs !== null && !$logs->isEmpty()) {
// Datas to readable text
$content = $this->parseLogs($logs);
if (!empty($content)) {
@@ -645,23 +608,14 @@ class activityReport
}
// Update db
- if ($send || $this->_global) { // if global : delete all blog logs even if not selected
- $this->updateStatus($lastreport, $now);
- $this->cleanLogs();
- $this->setSetting('lastreport', $now);
- }
- }
-
- // If this is on a blog, we need to test superAdmin report
- if (!$this->_global) {
- $this->_global = true;
- $this->needReport();
- $this->_global = false;
-
if ($send) {
+ $this->updateStatus($lastreport, $now);
+ $this->settings->set('lastreport', $now);
+
dcCore::app()->callBehavior('messageActivityReport', 'Activity report has been successfully send by mail.');
}
}
+
$this->unlockUpdate();
} catch (Exception $e) {
$this->unlockUpdate();
@@ -670,7 +624,16 @@ class activityReport
return true;
}
- private function sendReport($recipients, $message, $mailformat = ' ')
+ /**
+ * Send a report.
+ *
+ * @param array $recipients The recipients
+ * @param string $message The message
+ * @param string $mailformat The mail content format
+ *
+ * @return bool The sent success
+ */
+ private function sendReport(array $recipients, string $message, string $mailformat = 'plain'): bool
{
if (!is_array($recipients) || empty($message)) {
return false;
@@ -681,7 +644,7 @@ class activityReport
$rc2 = [];
foreach ($recipients as $v) {
$v = trim($v);
- if (!empty($v) && text::isEmail($v)) {
+ if (!empty($v) && Text::isEmail($v)) {
$rc2[] = $v;
}
}
@@ -695,13 +658,13 @@ class activityReport
# Sending mails
try {
$subject = mb_encode_mimeheader(
- ($this->_global ? '[' . dcCore::app()->blog->name . '] ' : '') . __('Blog activity report'),
+ sprintf(__('Blog "%s" activity report'), dcCore::app()->blog?->name),
'UTF-8',
'B'
);
$headers = [];
- $headers[] = 'From: ' . (defined('DC_ADMIN_MAILFROM') && DC_ADMIN_MAILFROM ? DC_ADMIN_MAILFROM : 'dotclear@local');
+ $headers[] = 'From: ' . (defined('DC_ADMIN_MAILFROM') && str_contains(DC_ADMIN_MAILFROM, '@') ? DC_ADMIN_MAILFROM : 'dotclear@local');
$headers[] = 'Content-Type: text/' . $mailformat . '; charset=UTF-8;';
//$headers[] = 'MIME-Version: 1.0';
//$headers[] = 'X-Originating-IP: ' . mb_encode_mimeheader(http::realIP(), 'UTF-8', 'B');
@@ -712,7 +675,7 @@ class activityReport
$done = true;
foreach ($recipients as $email) {
- if (true !== mail::sendMail($email, $subject, $message, $headers)) {
+ if (true !== Mail::sendMail($email, $subject, $message, $headers)) {
$done = false;
}
}
@@ -723,51 +686,54 @@ class activityReport
return $done;
}
- public function getUserCode()
+ /**
+ * Generate current user code for public feed.
+ *
+ * @return string The code
+ */
+ public function getUserCode(): string
{
- $code = pack('a32', dcCore::app()->auth->userID()) .
- pack('H*', crypt::hmac(DC_MASTER_KEY, dcCore::app()->auth->getInfo('user_pwd')));
+ $code = pack('a32', (string) dcCore::app()->auth?->userID()) .
+ pack('H*', Crypt::hmac(DC_MASTER_KEY, (string) dcCore::app()->auth?->getInfo('user_pwd')));
return bin2hex($code);
}
- public function checkUserCode($code)
+ /**
+ * Check user code from URL.
+ *
+ * @param string $code The code
+ *
+ * @return string|false The user ID or false
+ */
+ public function checkUserCode(string $code): string|false
{
$code = pack('H*', $code);
$user_id = trim(@pack('a32', substr($code, 0, 32)));
$pwd = @unpack('H40hex', substr($code, 32, 40));
- if ($user_id === false || $pwd === false) {
+ if (empty($user_id) || $pwd === false) {
return false;
}
$pwd = $pwd['hex'];
- $strReq = 'SELECT user_id, user_pwd ' .
- 'FROM ' . dcCore::app()->prefix . dcAuth::USER_TABLE_NAME . ' ' .
- "WHERE user_id = '" . dcCore::app()->con->escape($user_id) . "' ";
+ $sql = new SelectStatement();
+ $sql->from(dcCore::app()->prefix . dcAuth::USER_TABLE_NAME)
+ ->columns(['user_id', 'user_pwd'])
+ ->where('user_id =' . $sql->quote($user_id));
- $rs = dcCore::app()->con->select($strReq);
+ $rs = $sql->select();
- if ($rs->isEmpty()) {
+ if (!$rs || $rs->isEmpty()) {
return false;
}
- if (crypt::hmac(DC_MASTER_KEY, $rs->user_pwd) != $pwd) {
+ if (Crypt::hmac(DC_MASTER_KEY, $rs->f('user_pwd')) != $pwd) {
return false;
}
- return $rs->user_id;
- }
-
- public static function encode($a)
- {
- return @base64_encode(@serialize($a));
- }
-
- public static function decode($a)
- {
- return @unserialize(@base64_decode($a));
+ return $rs->f('user_id');
}
}
diff --git a/src/Backend.php b/src/Backend.php
index 5432734..579b037 100644
--- a/src/Backend.php
+++ b/src/Backend.php
@@ -10,140 +10,187 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_CONTEXT_ADMIN')) {
- return null;
-}
-if (!defined('ACTIVITY_REPORT_V2')) {
- return null;
-}
+declare(strict_types=1);
-dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem(
- __('Activity report'),
- dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)),
- dcPage::getPF(basename(__DIR__) . '/icon.png'),
- preg_match(
- '/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__))) . '(&.*)?$/',
- $_SERVER['REQUEST_URI']
- ),
- dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
- dcAuth::PERMISSION_ADMIN,
- ]), dcCore::app()->blog->id)
-);
+namespace Dotclear\Plugin\activityReport;
-if (dcCore::app()->activityReport->getSetting('active')) {
- dcCore::app()->addBehavior('adminDashboardContentsV2', ['activityReportAdmin', 'adminDashboardContentsV2']);
- dcCore::app()->addBehavior('adminDashboardOptionsFormV2', ['activityReportAdmin', 'adminDashboardOptionsFormV2']);
- dcCore::app()->addBehavior('adminAfterDashboardOptionsUpdate', ['activityReportAdmin', 'adminAfterDashboardOptionsUpdate']);
-}
+use ArrayObject;
+use dcAdmin;
+use dcAuth;
+use dcCore;
+use dcFavorites;
+use dcNsProcess;
+use dcPage;
+use Dotclear\Helper\Date;
+use Dotclear\Helper\Html\Form\{
+ Div,
+ Label,
+ Para,
+ Select,
+ Text
+};
-class activityReportAdmin
+/**
+ * Backend process
+ */
+class Backend extends dcNsProcess
{
- public static function adminDashboardContentsV2($items)
+ public static function init(): bool
{
- dcCore::app()->auth->user_prefs->addWorkspace(basename(__DIR__));
- $limit = abs((int) dcCore::app()->auth->user_prefs->__get(basename(__DIR__))->dashboard_item);
- if (!$limit) {
- return null;
- }
- $p = [
- 'limit' => $limit,
- 'order' => 'activity_dt DESC',
- 'sql' => dcCore::app()->activityReport->requests2params(dcCore::app()->activityReport->getSetting('requests')),
- ];
- $lines = [];
- $rs = dcCore::app()->activityReport->getLogs($p);
- if ($rs->isEmpty()) {
- return null;
- }
- $groups = dcCore::app()->activityReport->getGroups();
- while ($rs->fetch()) {
- $group = $rs->activity_group;
+ static::$init = defined('DC_CONTEXT_ADMIN')
+ && defined('ACTIVITY_REPORT')
+ && My::phpCompliant()
+ && My::isInstalled();
- if (!isset($groups[$group])) {
- continue;
- }
- $lines[] = '' .
- '' . __($groups[$group]['actions'][$rs->activity_action]['title']) . ' ' .
- ' ' . dt::str(
- dcCore::app()->blog->settings->system->date_format . ', ' . dcCore::app()->blog->settings->system->time_format,
- strtotime($rs->activity_dt),
- dcCore::app()->auth->getInfo('user_tz')
- ) . '' .
- ' ' .
- '' . vsprintf(
- __($groups[$group]['actions'][$rs->activity_action]['msg']),
- dcCore::app()->activityReport->decode($rs->activity_logs)
- ) . '
';
- }
- if (empty($lines)) {
- return null;
- }
- $items[] = new ArrayObject([
- '',
- ]);
+ return static::$init;
}
- public static function adminDashboardOptionsFormV2()
+ public static function process(): bool
{
- dcCore::app()->auth->user_prefs->addWorkspace(basename(__DIR__));
-
- echo
- '' .
- '
' . __('Activity report') . ' ' .
- '
' .
- __('Number of activities to show on dashboard:') . ' ' .
- form::combo(
- 'activityReport_dashboard_item',
- self::comboList(),
- self::comboList(dcCore::app()->auth->user_prefs->__get(basename(__DIR__))->dashboard_item)
- ) . '
' .
- '
';
- }
-
- public static function adminAfterDashboardOptionsUpdate($user_id = null)
- {
- if (is_null($user_id)) {
- return;
+ if (!static::$init) {
+ return false;
}
- dcCore::app()->auth->user_prefs->addWorkspace(basename(__DIR__));
- dcCore::app()->auth->user_prefs->__get(basename(__DIR__))->put(
- 'dashboard_item',
- self::comboList(@$_POST['activityReport_dashboard_item']),
- 'integer'
+ dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem(
+ My::name(),
+ dcCore::app()->adminurl?->get('admin.plugin.' . My::id()),
+ dcPage::getPF(My::id() . '/icon.svg'),
+ preg_match(
+ '/' . preg_quote((string) dcCore::app()->adminurl?->get('admin.plugin.' . My::id())) . '(&.*)?$/',
+ $_SERVER['REQUEST_URI']
+ ),
+ dcCore::app()->auth?->check(dcCore::app()->auth->makePermissions([
+ dcAuth::PERMISSION_ADMIN,
+ ]), dcCore::app()->blog?->id)
);
- }
- private static function comboList($q = true)
- {
- $l = [
- __('Do not show activity report') => 0,
- 5 => 5,
- 10 => 10,
- 15 => 15,
- 20 => 20,
- 50 => 50,
- 100 => 100,
- ];
- if (true === $q) {
- return $l;
- }
- if (!$q) {
- $q = -1;
- }
+ dcCore::app()->addBehaviors([
+ // dashboard favorites icon
+ 'adminDashboardFavoritesV2' => function (dcFavorites $favs): void {
+ $favs->register(My::id(), [
+ 'title' => My::name(),
+ 'url' => dcCore::app()->adminurl?->get('admin.plugin.' . My::id()),
+ 'small-icon' => dcPage::getPF(My::id() . '/icon.svg'),
+ 'large-icon' => dcPage::getPF(My::id() . '/icon.svg'),
+ 'permissions' => dcCore::app()->auth?->makePermissions([
+ dcAuth::PERMISSION_ADMIN,
+ ]),
+ ]);
+ },
+ // dashboard content display
+ 'adminDashboardContentsV2' => function (ArrayObject $items): void {
+ $limit = abs((int) dcCore::app()->auth?->user_prefs?->get(My::id())->get('dashboard_item'));
+ if (!$limit) {
+ return ;
+ }
- return in_array($q, $l) ? $l[$q] : 0;
+ $params = new ArrayObject([
+ 'limit' => $limit,
+ 'requests' => true,
+ ]);
+ $rs = ActivityReport::instance()->getLogs($params);
+ if (!$rs || $rs->isEmpty()) {
+ return;
+ }
+
+ $lines = [];
+ $groups = ActivityReport::instance()->groups;
+ while ($rs->fetch()) {
+ if (!$groups->has($rs->f('activity_group'))) {
+ continue;
+ }
+ $group = $groups->get($rs->f('activity_group'));
+ $lines[] = '' .
+ '' . __($group->get($rs->f('activity_action'))->title) . ' ' .
+ ' ' . Date::str(
+ dcCore::app()->blog?->settings->get('system')->get('date_format') . ', ' . dcCore::app()->blog?->settings->get('system')->get('time_format'),
+ (int) strtotime($rs->f('activity_dt')),
+ dcCore::app()->auth?->getInfo('user_tz')
+ ) . '' .
+ ' ' .
+ '' . vsprintf(
+ __($group->get($rs->f('activity_action'))->message),
+ json_decode($rs->f('activity_logs'), true)
+ ) . '
';
+ }
+ if (empty($lines)) {
+ return ;
+ }
+
+ $items[] = new ArrayObject([
+ '',
+ ]);
+ },
+ // dashboard content user preference form
+ 'adminDashboardOptionsFormV2' => function (): void {
+ echo
+ (new Div())->class('fieldset')->items([
+ (new Text('h4', My::name())),
+ (new Para())->items([
+ (new Label(__('Number of activities to show on dashboard:'), Label::OUTSIDE_LABEL_BEFORE))->for(My::id() . '_dashboard_item'),
+ (new Select(My::id() . '_dashboard_item'))->default((string) dcCore::app()->auth?->user_prefs?->get(My::id())->get('dashboard_item'))->items([
+ __('Do not show activity report') => 0,
+ 5 => 5,
+ 10 => 10,
+ 15 => 15,
+ 20 => 20,
+ 50 => 50,
+ 100 => 100,
+ ]),
+ ]),
+ ])->render();
+ },
+ // save dashboard content user preference
+ 'adminAfterDashboardOptionsUpdate' => function (?string $user_id = null): void {
+ if (!is_null($user_id)) {
+ dcCore::app()->auth?->user_prefs?->get(My::id())->put(
+ 'dashboard_item',
+ (int) $_POST[My::id() . '_dashboard_item'],
+ 'integer'
+ );
+ }
+ },
+ // list filters
+ 'adminFiltersListsV2' => function (ArrayObject $sorts): void {
+ $sorts[My::id()] = [
+ My::name(),
+ [
+ __('Group') => 'activity_group',
+ __('Action') => 'activity_action',
+ __('Date') => 'activity_dt',
+ __('Status') => 'activity_status',
+ ],
+ 'activity_dt',
+ 'desc',
+ [__('logs per page'), 30],
+ ];
+ },
+ // list columns user preference
+ 'adminColumnsListsV2' => function (ArrayObject $cols): void {
+ $cols[My::id()] = [
+ My::name(),
+ [
+ 'activity_group' => [true, __('Group')],
+ 'activity_action' => [true, __('Action')],
+ 'activity_dt' => [true, __('Date')],
+ 'activity_status' => [false, __('Status')],
+ ],
+ ];
+ },
+ ]);
+
+ return true;
}
}
diff --git a/src/Combo.php b/src/Combo.php
new file mode 100644
index 0000000..2c7da57
--- /dev/null
+++ b/src/Combo.php
@@ -0,0 +1,72 @@
+formats->dump() as $format) {
+ $combo[$format->name] = $format->id;
+ }
+
+ return $combo;
+ }
+
+ /**
+ * Get report intervals.
+ *
+ * @return array The intervals combo
+ */
+ public static function interval(): array
+ {
+ return [
+ __('every hour') => 3600,
+ __('every 2 hours') => 7200,
+ __('2 times by day') => 43200,
+ __('every day') => 86400,
+ __('every 2 days') => 172800,
+ __('every week') => 604800,
+ ];
+ }
+
+ /**
+ * Get obsolete period.
+ *
+ * @return array The obsolete period combo
+ */
+ public static function obselete(): array
+ {
+ return [
+ __('every hour') => 3600,
+ __('every 2 hours') => 7200,
+ __('2 times by day') => 43200,
+ __('every day') => 86400,
+ __('every 2 days') => 172800,
+ __('every week') => 604800,
+ __('every 2 weeks') => 1209600,
+ __('every 4 weeks') => 2419200,
+ ];
+ }
+}
diff --git a/src/Config.php b/src/Config.php
index f5881e2..f4c2f6c 100644
--- a/src/Config.php
+++ b/src/Config.php
@@ -10,232 +10,218 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_CONTEXT_MODULE')) {
- return null;
-}
+declare(strict_types=1);
-$super = dcCore::app()->auth->isSuperAdmin() && !empty($_REQUEST['super']);
-$redir = empty($_REQUEST['redir']) ? dcCore::app()->admin->list->getURL() . '#plugins' : $_REQUEST['redir'];
+namespace Dotclear\Plugin\activityReport;
-if ($super) {
- dcCore::app()->activityReport->setGlobal();
-}
+use dcAuth;
+use dcCore;
+use dcPage;
+use dcNsProcess;
+use Dotclear\Helper\Date;
+use Dotclear\Helper\Html\Form\{
+ Checkbox,
+ Div,
+ Hidden,
+ Input,
+ Label,
+ Note,
+ Para,
+ Select,
+ Text
+};
+use Exception;
-$combo_interval = [
- __('every hour') => 3600,
- __('every 2 hours') => 7200,
- __('2 times by day') => 43200,
- __('every day') => 86400,
- __('every 2 days') => 172800,
- __('every week') => 604800,
-];
+/**
+ * Config process.
+ */
+class Config extends dcNsProcess
+{
+ public static function init(): bool
+ {
+ static::$init == defined('DC_CONTEXT_ADMIN')
+ && defined('ACTIVITY_REPORT')
+ && My::phpCompliant()
+ && dcCore::app()->auth?->check(dcCore::app()->auth->makePermissions([
+ dcAuth::PERMISSION_ADMIN,
+ ]), dcCore::app()->blog?->id);
-$combo_obselete = [
- __('every hour') => 3600,
- __('every 2 hours') => 7200,
- __('2 times by day') => 43200,
- __('every day') => 86400,
- __('every 2 days') => 172800,
- __('every week') => 604800,
- __('every 2 weeks') => 1209600,
- __('every 4 weeks') => 2419200,
-];
+ return static::$init;
+ }
-$combo_format = [
- __('Plain text') => 'plain',
- __('HTML') => 'html',
-];
-
-if (!empty($_POST['save'])) {
- try {
- dcCore::app()->activityReport->setSetting('active', !empty($_POST['active']));
- if (in_array($_POST['interval'], $combo_interval)) {
- dcCore::app()->activityReport->setSetting('interval', (int) $_POST['interval']);
+ public static function process(): bool
+ {
+ if (!static::$init) {
+ return false;
}
- if (in_array($_POST['obsolete'], $combo_obselete)) {
- dcCore::app()->activityReport->setSetting('obsolete', (int) $_POST['obsolete']);
+
+ if (empty($_POST['save'])) {
+ return true;
}
- dcCore::app()->activityReport->setSetting('mailinglist', explode(';', $_POST['mailinglist']));
- dcCore::app()->activityReport->setSetting('mailformat', isset($_POST['mailformat']) && $_POST['mailformat'] == 'html' ? 'html' : 'plain');
- dcCore::app()->activityReport->setSetting('dateformat', html::escapeHTML($_POST['dateformat']));
- dcCore::app()->activityReport->setSetting('requests', $_POST['requests'] ?? []);
- dcCore::app()->activityReport->setSetting('blogs', $_POST['blogs'] ?? []);
- if (!empty($_POST['send_report_now'])) {
- dcCore::app()->activityReport->needReport(true);
+ try {
+ $s = ActivityReport::instance()->settings;
- dcAdminNotices::addSuccessNotice(
- __('Report successfully sent.')
+ $s->set('feed_active', !empty($_POST['feed_active']));
+ if (in_array($_POST['interval'], Combo::interval())) {
+ $s->set('interval', (int) $_POST['interval']);
+ }
+ if (in_array($_POST['obsolete'], Combo::obselete())) {
+ $s->set('obsolete', (int) $_POST['obsolete']);
+ }
+ $s->set('mailinglist', explode(';', $_POST['mailinglist']));
+ $s->set('mailformat', isset($_POST['mailformat']) && $_POST['mailformat'] == 'html' ? 'html' : 'plain');
+ $s->set('dateformat', $_POST['dateformat']);
+ $s->set('requests', $_POST['requests'] ?? []);
+
+ dcPage::addSuccessNotice(
+ __('Configuration successfully updated.')
);
- }
- if (!empty($_POST['delete_report_now'])) {
- dcCore::app()->activityReport->deleteLogs();
- dcAdminNotices::addSuccessNotice(
- __('Logs successfully deleted.')
+ if (!empty($_POST['send_report_now'])) {
+ ActivityReport::instance()->needReport(true);
+
+ dcPage::addSuccessNotice(
+ __('Report successfully sent.')
+ );
+ }
+ if (!empty($_POST['delete_report_now'])) {
+ ActivityReport::instance()->deleteLogs();
+
+ dcPage::addSuccessNotice(
+ __('Logs successfully deleted.')
+ );
+ }
+
+ dcCore::app()->adminurl?->redirect('admin.plugins', [
+ 'module' => My::id(),
+ 'conf' => 1,
+ ]);
+ } catch (Exception $e) {
+ dcCore::app()->error->add($e->getMessage());
+ }
+
+ return true;
+ }
+
+ public static function render(): void
+ {
+ if (!static::$init) {
+ return;
+ }
+
+ $s = ActivityReport::instance()->settings;
+
+ if (!$s->lastreport) {
+ $last_report = __('never');
+ $next_report = __('on new activity');
+ } else {
+ $last_report = Date::str(
+ dcCore::app()->blog?->settings->get('system')->get('date_format') . ', ' . dcCore::app()->blog?->settings->get('system')->get('time_format'),
+ $s->lastreport,
+ dcCore::app()->auth?->getInfo('user_tz')
+ );
+ $next_report = Date::str(
+ dcCore::app()->blog?->settings->get('system')->get('date_format') . ', ' . dcCore::app()->blog?->settings->get('system')->get('time_format'),
+ $s->interval + $s->lastreport,
+ dcCore::app()->auth?->getInfo('user_tz')
);
}
- dcAdminNotices::addSuccessNotice(
- __('Configuration successfully updated.')
- );
- dcCore::app()->adminurl->redirect('admin.plugins', ['module' => basename(__DIR__), 'conf' => 1, 'super' => $super]);
- } catch (Exception $e) {
- dcCore::app()->error->add($e->getMessage());
+ if (!ActivityReport::hasMailer()) {
+ echo '' .
+ __('This server has no mail function, activityReport does not send email report.') .
+ '
';
+ }
+
+ echo
+ (new Div())->class('two-boxes')->separator('')->items([
+ (new Div())->class('fieldset box odd')->items([
+ (new Text('h4', __('Mail report'))),
+ (new Para())->items([
+ (new Label(__('Send report:'), Label::OUTSIDE_LABEL_BEFORE))->for('interval'),
+ (new Select('interval'))->default((string) $s->interval)->items(Combo::interval()),
+ ]),
+ (new Para())->items([
+ (new Label(__('Recipients:'), Label::OUTSIDE_LABEL_BEFORE))->for('mailinglist'),
+ (new Input('mailinglist'))->size(60)->maxlenght(255)->value(implode(';', $s->mailinglist)),
+ ]),
+ (new Note())->class('form-note')->text(__('Separate multiple email addresses with a semicolon ";"')),
+ (new Note())->class('form-note')->text(__('Leave it empty to disable mail report.')),
+ (new Para())->items([
+ (new Label(__('Date format:'), Label::OUTSIDE_LABEL_BEFORE))->for('dateformat'),
+ (new Input('dateformat'))->size(60)->maxlenght(255)->value($s->dateformat),
+ ]),
+ (new Note())->class('form-note')->text(__('Use Dotclear date formaters. ex: %B %d at %H:%M')),
+ (new Para())->items([
+ (new Label(__('Report format:'), Label::OUTSIDE_LABEL_BEFORE))->for('mailformat'),
+ (new Select('mailformat'))->default($s->mailformat)->items(Combo::mailformat()),
+ ]),
+ (new Text(
+ 'ul',
+ '' . __('Last report by email:') . ' ' . $last_report . ' ' .
+ '' . __('Next report by email:') . ' ' . $next_report . ' '
+ )),
+ ]),
+ (new Div())->class('fieldset box even')->items([
+ (new Text('h4', __('Feeds'))),
+ (new Para())->items([
+ (new Checkbox('feed_active', $s->feed_active))->value(1),
+ (new Label(__('Enable activity feed'), Label::OUTSIDE_LABEL_AFTER))->for('feed_active')->class('classic'),
+ ]),
+ (new Text(
+ 'ul',
+ ' ' .
+ '' .
+ __('Rss2 activities feed') . ' ' .
+ ' ' .
+ '' .
+ __('Atom activities feed') . ' '
+ )),
+ ]),
+ ])->render();
+
+ $i = 0;
+ $g = [
+ (new Text('h4', __('Activities'))),
+ (new Text('p', __('Select actions by activity type to add to report'))),
+ ];
+ foreach (ActivityReport::instance()->groups->dump() as $group_id => $group) {
+ $a = [];
+ $a[] = (new Text('h5', __($group->title)));
+ foreach ($group->dump() as $action_id => $action) {
+ $a[] = (new Para())->items([
+ (new Checkbox(
+ ['requests[' . $group_id . '][' . $action_id . ']', 'requests_' . $group_id . '_' . $action_id . '_'],
+ isset($s->requests[$group_id][$action_id])
+ ))->value(1),
+ (new Label(__($action->title), Label::OUTSIDE_LABEL_AFTER))->for(
+ 'requests_' . $group_id . '_' . $action_id . '_'
+ )->class('classic'),
+ ]);
+ }
+ $g[] = (new Div())->class('fieldset box')->items($a);
+ }
+ echo
+ (new Div('setting_report'))->class('fieldset one-box')->items($g)->render();
+
+ echo
+ (new Div('settings'))->class('fieldset')->items([
+ (new Text('h4', __('Maintenance'))),
+ (new Para())->items([
+ (new Label(__('Automatic cleaning of old logs:'), Label::OUTSIDE_LABEL_BEFORE))->for('obselete'),
+ (new Select('obselete'))->default((string) $s->obsolete)->items(Combo::obselete()),
+ ]),
+ (new Para())->items([
+ (new Checkbox('send_report_now'))->value(1),
+ (new Label(__('Send report now'), Label::OUTSIDE_LABEL_AFTER))->for('send_report_now')->class('classic'),
+ ]),
+ (new Para())->items([
+ (new Checkbox('delete_report_now'))->value(1),
+ (new Label(__('Delete all logs now'), Label::OUTSIDE_LABEL_AFTER))->for('delete_report_now')->class('classic'),
+ ]),
+ ])->render();
}
}
-
-$last_report_ts = dcCore::app()->activityReport->getSetting('lastreport');
-if (!$last_report_ts) {
- $last_report = __('never');
- $next_report = __('on new activity');
-} else {
- $last_report = dt::str(
- dcCore::app()->blog->settings->system->date_format . ', ' . dcCore::app()->blog->settings->system->time_format,
- $last_report_ts,
- dcCore::app()->auth->getInfo('user_tz')
- );
- $next_report = dt::str(
- dcCore::app()->blog->settings->system->date_format . ', ' . dcCore::app()->blog->settings->system->time_format,
- (int) dcCore::app()->activityReport->getSetting('interval') + $last_report_ts,
- dcCore::app()->auth->getInfo('user_tz')
- );
-}
-$emails = implode(';', dcCore::app()->activityReport->getSetting('mailinglist'));
-
-echo '' . ($super ? __('All blogs') : __('Current blog')) . '
';
-
-if (dcCore::app()->auth->isSuperAdmin()) {
- echo sprintf(
- '%s
',
- dcCore::app()->adminurl->get('admin.plugins', ['module' => basename(__DIR__), 'conf' => 1, 'super' => !$super]),
- sprintf(__('Configure activity report for %s'), $super ? __('current blog') : __('all blogs'))
- );
-}
-if (!activityReport::hasMailer()) {
- echo '' .
- __('This server has no mail function, activityReport does not send email report.') .
- '
';
-}
-
-echo '
-' . __('Settings') . '
-
-
-
' .
-form::checkbox('active', '1', dcCore::app()->activityReport->getSetting('active')) . ' ' .
-(
- $super ?
- __('Enable super administrator report') :
- __('Enable report on this blog')
-) . '
-
-
' . __('Automatic cleaning of old logs:') . ' ' .
-form::combo('obsolete', $combo_obselete, dcCore::app()->activityReport->getSetting('obsolete')) . '
-
-
' . __('Date format:') . ' ' .
-form::field('dateformat', 60, 255, dcCore::app()->activityReport->getSetting('dateformat')) . '
-
' . __('Use Dotclear date formaters. ex: %B %d at %H:%M') . '
' .
-
-form::hidden(['super'], $super);
-
-if (!$super) {
- echo
- '
' .
- '' .
- __('Rss2 feed for activity on this blog') . ' ' .
- ' ' .
- '' .
- __('Atom feed for activity on this blog') . '
';
-}
-echo '
-
-
-
' . __('Send report:') . ' ' .
-form::combo('interval', $combo_interval, dcCore::app()->activityReport->getSetting('interval')) . '
-
-
' . __('Recipients:') . ' ' .
-form::field('mailinglist', 60, 255, $emails) . '
-
' . __('Separate multiple email addresses with a semicolon ";"') . '
-
-
' . __('Report format:') . ' ' .
-form::combo('mailformat', $combo_format, dcCore::app()->activityReport->getSetting('mailformat')) . '
-
-
-' . __('Last report by email:') . ' ' . $last_report . '
-' . __('Next report by email:') . ' ' . $next_report . '
-
-
-
';
-
-if ($super) {
- echo '
- ' . __('Blogs') . '
-
' . __('Select blogs to add to report') . '
';
-
- $i = $j = 0;
- $selected_blogs = dcCore::app()->activityReport->getSetting('blogs');
- $blogs = dcCore::app()->getBlogs();
- $num_blogs = $blogs->count();
- while ($blogs->fetch()) {
- $blog_id = dcCore::app()->con->escape($blogs->blog_id);
-
- echo '
-
-
' .
- form::checkbox(
- ['blogs[' . $i . ']', 'blogs_' . $i . '_'],
- $blog_id,
- in_array($blog_id, $selected_blogs)
- ) . ' ' .
- $blogs->blog_name . ' (' . $blog_id . ')
-
';
-
- $i++;
- }
- echo '
';
-} else {
- echo form::hidden('blogs[0]', dcCore::app()->blog->id);
-}
-echo '
-' . __('Report') . '
-
' . __('Select actions by activity type to add to report') . '
';
-
-$groups = dcCore::app()->activityReport->getGroups();
-$blog_request = dcCore::app()->activityReport->getSetting('requests');
-
-$i = 0;
-foreach ($groups as $group_id => $group) {
- echo '
' . __($group['title']) . ' ';
-
- foreach ($group['actions'] as $action_id => $action) {
- echo '
-
' .
- form::checkbox(
- ['requests[' . $group_id . '][' . $action_id . ']', 'requests_' . $group_id . '_' . $action_id . '_'],
- 1,
- isset($blog_request[$group_id][$action_id])
- ) . ' ' . __($action['title']) . '
';
- }
- echo '
';
-}
-echo '
';
-
-if (1) {
- echo '
- ' . __('Special') . '
-
-
' .
- form::checkbox('send_report_now', '1', false) . ' ' .
- __('Send report now') . '
-
-
' .
- form::checkbox('delete_report_now', '1', false) . ' ' .
- __('Delete all logs now') . '
-
-
';
-}
-
-dcCore::app()->activityReport->unsetGlobal();
diff --git a/src/Context.php b/src/Context.php
new file mode 100644
index 0000000..6878204
--- /dev/null
+++ b/src/Context.php
@@ -0,0 +1,71 @@
+ctx || !dcCore::app()->ctx->exists('activityreports')) {
+ return '';
+ }
+
+ $group = dcCore::app()->ctx->__get('activityreports')->activity_group;
+ $action = dcCore::app()->ctx->__get('activityreports')->activity_action;
+
+ if (!ActivityReport::instance()->groups->get($group)->has($action)) {
+ return '';
+ }
+
+ return __(ActivityReport::instance()->groups->get($group)->get($action)->title);
+ }
+
+ /**
+ * Parse content.
+ *
+ * @return string The parsed content
+ */
+ public static function parseContent(): string
+ {
+ if (!dcCore::app()->ctx || !dcCore::app()->ctx->exists('activityreports')) {
+ return '';
+ }
+
+ $group = dcCore::app()->ctx->__get('activityreports')->activity_group;
+ $action = dcCore::app()->ctx->__get('activityreports')->activity_action;
+ $logs = json_decode((string) dcCore::app()->ctx->__get('activityreports')->activity_logs, true);
+
+ if (!is_array($logs) || !ActivityReport::instance()->groups->get($group)->has($action)) {
+ return '';
+ }
+
+ dcCore::app()->initWikiComment();
+
+ return dcCore::app()->wikiTransform(vsprintf(
+ __(ActivityReport::instance()->groups->get($group)->get($action)->message),
+ $logs
+ ));
+ }
+}
diff --git a/src/Format.php b/src/Format.php
new file mode 100644
index 0000000..02ee987
--- /dev/null
+++ b/src/Format.php
@@ -0,0 +1,81 @@
+name = $format['name'] ?? __('Plain text');
+ $this->blog_title = $format['blog_title'] ?? "\n--- %TEXT% ---\n";
+ $this->group_title = $format['group_title'] ?? "\n-- %TEXT% --\n\n";
+ $this->group_open = $format['group_open'] ?? '';
+ $this->group_close = $format['group_close'] ?? '';
+ $this->action = $format['action'] ?? "- %TIME% : %TEXT%\n";
+ $this->error = $format['error'] ?? '%TEXT%';
+ $this->period_title = $format['period_title'] ?? "%TEXT%\n";
+ $this->period_open = $format['period_open'] ?? '';
+ $this->period_close = $format['period_close'] ?? '';
+ $this->info = $format['info'] ?? "%TEXT%\n";
+ $this->page = $format['page'] ?? "%PERIOD%\n-----------------------------------------------------------\n%TEXT%";
+ }
+}
diff --git a/src/Formats.php b/src/Formats.php
index 94ed062..9ab2007 100644
--- a/src/Formats.php
+++ b/src/Formats.php
@@ -10,52 +10,63 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-$format = [
- 'html' => [
- 'blog_title' => '',
- 'blog_open' => '',
- 'blog_close' => '',
- 'group_title' => '%TEXT% ',
- 'group_open' => '',
- 'action' => '%TIME% %TEXT% ',
- 'error' => '%TEXT%
',
- 'period_title' => '%TEXT% ',
- 'period_open' => '',
- 'info' => '%TEXT% ',
- 'page' => '' . "\n" .
- '' . "\n" .
- '' . __('Activity report') . ' ' .
- '' .
- '' .
- '%PERIOD%
%TEXT%
' .
- '' .
- '',
- ],
- 'plain' => [
- 'blog_title' => "\n--- %TEXT% ---\n",
- 'blog_open' => '',
- 'blog_close' => '',
- 'group_title' => "\n-- %TEXT% --\n\n",
- 'group_open' => '',
- 'group_close' => '',
- 'action' => "- %TIME% : %TEXT%\n",
- 'error' => '%TEXT%',
- 'period_title' => "%TEXT%\n",
- 'period_open' => '',
- 'period_close' => '',
- 'info' => "%TEXT%\n",
- 'page' => "%PERIOD%\n-----------------------------------------------------------\n%TEXT%",
- ],
-];
+declare(strict_types=1);
+
+namespace Dotclear\Plugin\activityReport;
+
+/**
+ * Email report formats stack.
+ */
+class Formats
+{
+ /** @var array $stack The formats stack */
+ private array $stack = [];
+
+ /**
+ * Chek if a format exists.
+ *
+ * @param string $id The format ID
+ *
+ * @return bool True if it exists
+ */
+ public function has(string $id): bool
+ {
+ return isset($this->stack[$id]);
+ }
+
+ /**
+ * Add a format.
+ *
+ * @param Format $format The format object
+ *
+ * @return Formats The formats instance
+ */
+ public function add(Format $format): Formats
+ {
+ $this->stack[$format->id] = $format;
+
+ return $this;
+ }
+
+ /**
+ * Get a format.
+ *
+ * @param string $id The format ID
+ *
+ * @return Format The format descriptor
+ */
+ public function get(string $id): Format
+ {
+ return $this->stack[$id] ?? new Format('plain', []);
+ }
+
+ /**
+ * Get all formats.
+ *
+ * @return array The formats stack
+ */
+ public function dump(): array
+ {
+ return $this->stack;
+ }
+}
diff --git a/src/Frontend.php b/src/Frontend.php
index 4f1b726..9597759 100644
--- a/src/Frontend.php
+++ b/src/Frontend.php
@@ -10,165 +10,41 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_RC_PATH')) {
- return null;
-}
-if (!defined('ACTIVITY_REPORT_V2')) {
- return null;
-}
+declare(strict_types=1);
-dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), __DIR__ . '/default-templates/tpl');
-dcCore::app()->tpl->addBlock('activityReports', ['activityReportPublicTpl','activityReports']);
-dcCore::app()->tpl->addValue('activityReportFeedID', ['activityReportPublicTpl','activityReportFeedID']);
-dcCore::app()->tpl->addValue('activityReportTitle', ['activityReportPublicTpl','activityReportTitle']);
-dcCore::app()->tpl->addValue('activityReportDate', ['activityReportPublicTpl','activityReportDate']);
-dcCore::app()->tpl->addValue('activityReportContent', ['activityReportPublicTpl','activityReportContent']);
+namespace Dotclear\Plugin\activityReport;
-class activityReportPublicUrl extends dcUrlHandlers
+use dcCore;
+use dcNsProcess;
+
+/**
+ * Front end process.
+ */
+class Frontend extends dcNsProcess
{
- public static function feed(?string $args): void
+ public static function init(): bool
{
- if (!preg_match('/^(atom|rss2)\/(.+)$/', $args, $m)) {
- self::p404();
+ static::$init = defined('ACTIVITY_REPORT')
+ && My::phpCompliant()
+ && My::isInstalled();
- return;
- }
- if (!defined('ACTIVITY_REPORT_V2')) {
- self::p404();
+ return static::$init;
+ }
- return;
- }
- if (!dcCore::app()->activityReport->getSetting('active')) {
- self::p404();
-
- return;
- }
- $mime = $m[1] == 'atom' ? 'application/atom+xml' : 'application/xml';
-
- if (false === dcCore::app()->activityReport->checkUserCode($m[2])) {
- self::p404();
-
- return;
+ public static function process(): bool
+ {
+ if (!static::$init) {
+ return false;
}
- dcCore::app()->ctx->nb_entry_per_page = (int) dcCore::app()->blog->settings->system->nb_post_per_feed;
- dcCore::app()->ctx->short_feed_items = (int) dcCore::app()->blog->settings->system->short_feed_items;
+ dcCore::app()->tpl->setPath(dcCore::app()->tpl->getPath(), implode(DIRECTORY_SEPARATOR, [My::root(), 'default-templates', 'tpl']));
- header('X-Robots-Tag: ' . context::robotsPolicy(dcCore::app()->blog->settings->system->robots_policy, ''));
- self::serveDocument('activityreport-' . $m[1] . '.xml', $mime);
- }
-}
-
-class activityReportPublicTpl
-{
- public static function activityReports($attr, $content)
- {
- $lastn = 0;
- if (isset($attr['lastn'])) {
- $lastn = abs((int) $attr['lastn']) + 0;
- }
-
- $p = '$_page_number = dcCore::app()->public->getPageNumber(); if ($_page_number < 1) { $_page_number = 1; }' . "\n\$params = array();\n";
-
- if ($lastn > 0) {
- $p .= "\$params['limit'] = " . $lastn . ";\n";
- } else {
- $p .= "\$params['limit'] = dcCore::app()->ctx->nb_entry_per_page;\n";
- }
-
- if (!isset($attr['ignore_pagination']) || $attr['ignore_pagination'] == '0') {
- $p .= "\$params['limit'] = array(((\$_page_number-1)*\$params['limit']),\$params['limit']);\n";
- } else {
- $p .= "\$params['limit'] = array(0, \$params['limit']);\n";
- }
-
- return
- "ctx->activityreport_params = $params; ' . "\n" .
- 'dcCore::app()->ctx->activityreports = dcCore::app()->activityReport->getLogs($params); unset($params); ' . "\n" .
- 'while (dcCore::app()->ctx->activityreports->fetch()) : ?>' . $content . 'ctx->pop("activityreports"); dcCore::app()->ctx->pop("activityreport_params"); ' . "\n" .
- '?>';
- }
-
- public static function activityReportFeedID($attr)
- {
- return
- 'urn:md5:ctx->activityreports->blog_id.' .
- 'dcCore::app()->ctx->activityreports->activity_id.dcCore::app()->ctx->activityreports->activity_dt); ' .
- '?>';
- }
-
- public static function activityReportTitle($attr)
- {
- $f = dcCore::app()->tpl->getFilters($attr);
-
- return '';
- }
-
- public static function activityReportContent($attr)
- {
- $f = dcCore::app()->tpl->getFilters($attr);
-
- return '';
- }
-
- public static function activityReportDate($attr)
- {
- $format = '';
- if (!empty($attr['format'])) {
- $format = addslashes($attr['format']);
- }
-
- $iso8601 = !empty($attr['iso8601']);
- $rfc822 = !empty($attr['rfc822']);
-
- $f = dcCore::app()->tpl->getFilters($attr);
-
- if ($rfc822) {
- return 'ctx->activityreports->activity_dt),dcCore::app()->blog->settings->system->blog_timezone)') . '; ?>';
- } elseif ($iso8601) {
- return 'ctx->activityreports->activity_dt),dcCore::app()->blog->settings->system->blog_timezone)') . '; ?>';
- } elseif (!empty($format)) {
- return 'ctx->activityreports->activity_dt)") . '; ?>';
- }
-
- return 'blog->settings->system->date_format,dcCore::app()->ctx->activityreports->activity_dt)') . '; ?>';
- }
-}
-
-class activityReportContext
-{
- public static function parseTitle()
- {
- $groups = dcCore::app()->activityReport->getGroups();
-
- $group = dcCore::app()->ctx->activityreports->activity_group;
- $action = dcCore::app()->ctx->activityreports->activity_action;
-
- if (!empty($groups[$group]['actions'][$action]['title'])) {
- return __($groups[$group]['actions'][$action]['title']);
- }
-
- return '';
- }
-
- public static function parseContent()
- {
- $groups = dcCore::app()->activityReport->getGroups();
-
- $group = dcCore::app()->ctx->activityreports->activity_group;
- $action = dcCore::app()->ctx->activityreports->activity_action;
- $logs = dcCore::app()->ctx->activityreports->activity_logs;
- $logs = dcCore::app()->activityReport->decode($logs);
-
- if (!empty($groups[$group]['actions'][$action]['msg'])) {
- dcCore::app()->initWikiComment();
-
- return dcCore::app()->wikiTransform(vsprintf(__($groups[$group]['actions'][$action]['msg']), $logs));
- }
-
- return '';
+ dcCore::app()->tpl->addBlock('activityReports', [Template::class, 'activityReports']);
+ dcCore::app()->tpl->addValue('activityReportFeedID', [Template::class, 'activityReportFeedID']);
+ dcCore::app()->tpl->addValue('activityReportTitle', [Template::class, 'activityReportTitle']);
+ dcCore::app()->tpl->addValue('activityReportDate', [Template::class, 'activityReportDate']);
+ dcCore::app()->tpl->addValue('activityReportContent', [Template::class, 'activityReportContent']);
+
+ return true;
}
}
diff --git a/src/Group.php b/src/Group.php
new file mode 100644
index 0000000..61f3617
--- /dev/null
+++ b/src/Group.php
@@ -0,0 +1,82 @@
+ $stack The actions stack */
+ private array $stack = [];
+
+ /**
+ * Constructor sets group description.
+ *
+ * @param string $id The group ID
+ * @param string $title The group title
+ */
+ public function __construct(public readonly string $id, public readonly string $title)
+ {
+ }
+
+ /**
+ * Chek if a action exists.
+ *
+ * @param string $id The action ID
+ *
+ * @return bool True if it exists
+ */
+ public function has(string $id): bool
+ {
+ return isset($this->stack[$id]);
+ }
+
+ /**
+ * Add an action.
+ *
+ * @param Action $action The action object
+ *
+ * @return Group The group instance
+ */
+ public function add(Action $action): Group
+ {
+ $this->stack[$action->id] = $action;
+
+ return $this;
+ }
+
+ /**
+ * Get an action.
+ *
+ * @param string $id The action ID
+ *
+ * @return Action The action descriptor
+ */
+ public function get(string $id): Action
+ {
+ return $this->stack[$id] ?? new Action($id, 'undefined', 'undefined', 'undefined', null);
+ }
+
+ /**
+ * Get all actions.
+ *
+ * @return array The actions stack
+ */
+ public function dump(): array
+ {
+ return $this->stack;
+ }
+}
diff --git a/src/Groups.php b/src/Groups.php
new file mode 100644
index 0000000..742838e
--- /dev/null
+++ b/src/Groups.php
@@ -0,0 +1,72 @@
+ $stack The actions groups stack */
+ private array $stack = [];
+
+ /**
+ * Chek if a group exists.
+ *
+ * @param string $id The group ID
+ *
+ * @return bool True if it exists
+ */
+ public function has(string $id): bool
+ {
+ return isset($this->stack[$id]);
+ }
+
+ /**
+ * Add a group.
+ *
+ * @param Group $group The group object
+ *
+ * @return Groups The groups instance
+ */
+ public function add(Group $group): Groups
+ {
+ $this->stack[$group->id] = $group;
+
+ return $this;
+ }
+
+ /**
+ * Get a group.
+ *
+ * @param string $id The group ID
+ *
+ * @return Group The group descriptor
+ */
+ public function get(string $id): Group
+ {
+ return $this->stack[$id] ?? new Group($id, 'undefined');
+ }
+
+ /**
+ * Get all groups.
+ *
+ * @return array The groups stack
+ */
+ public function dump(): array
+ {
+ return $this->stack;
+ }
+}
diff --git a/src/Install.php b/src/Install.php
index 4c94e7c..e4f0efd 100644
--- a/src/Install.php
+++ b/src/Install.php
@@ -10,53 +10,87 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_CONTEXT_ADMIN')) {
- return null;
+declare(strict_types=1);
+
+namespace Dotclear\Plugin\activityReport;
+
+use dbStruct;
+use dcCore;
+use dcNsProcess;
+use Dotclear\Database\Statement\{
+ DropStatement,
+ TruncateStatement
+};
+use Exception;
+
+/**
+ * Install process.
+ */
+class Install extends dcNsProcess
+{
+ public static function init(): bool
+ {
+ static::$init = defined('DC_CONTEXT_ADMIN')
+ && My::phpCompliant()
+ && dcCore::app()->newVersion(My::id(), dcCore::app()->plugins->moduleInfo(My::id(), 'version'));
+
+ return static::$init;
+ }
+
+ public static function process(): bool
+ {
+ if (!static::$init) {
+ return false;
+ }
+
+ try {
+ self::beforeGrowUp();
+
+ $s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix);
+ $s->{My::ACTIVITY_TABLE_NAME}
+ ->activity_id('bigint', 0, false)
+ ->activity_type('varchar', 32, false, "'" . My::id() . "'")
+ ->blog_id('varchar', 32, true)
+ ->activity_group('varchar', 32, false)
+ ->activity_action('varchar', 32, false)
+ ->activity_logs('text', 0, false)
+ ->activity_dt('timestamp', 0, false, 'now()')
+ ->activity_status('smallint', 0, false, 0)
+
+ ->primary('pk_activity', 'activity_id')
+ ->index('idx_activity_type', 'btree', 'activity_type')
+ ->index('idx_activity_blog_id', 'btree', 'blog_id')
+ ->index('idx_activity_action', 'btree', 'activity_group', 'activity_action')
+ ->index('idx_activity_status', 'btree', 'activity_status');
+
+ (new dbStruct(dcCore::app()->con, dcCore::app()->prefix))->synchronize($s);
+
+ return true;
+ } catch (Exception $e) {
+ dcCore::app()->error->add($e->getMessage());
+
+ return false;
+ }
+ }
+
+ /**
+ * Do some action on previous version before install.
+ */
+ private static function beforeGrowUp(): void
+ {
+ $current = dcCore::app()->getVersion('activityReport');
+
+ // sorry not sorry we restart from scratch
+ if ($current && version_compare($current, '3.0', '<')) {
+ $struct = new dbStruct(dcCore::app()->con, dcCore::app()->prefix);
+
+ if ($struct->tableExists('activity')) {
+ (new TruncateStatement())->from(dcCore::app()->prefix . 'activity')->truncate();
+ }
+ if ($struct->tableExists('activity_settings')) {
+ (new TruncateStatement())->from(dcCore::app()->prefix . 'activity_settings')->truncate();
+ (new DropStatement())->from(dcCore::app()->prefix . 'activity_settings')->drop();
+ }
+ }
+ }
}
-
-if (!dcCore::app()->newVersion(
- basename(__DIR__),
- dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version')
-)) {
- return null;
-}
-
-try {
- $s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix);
- $s->{initActivityReport::ACTIVITY_TABLE_NAME}
- ->activity_id('bigint', 0, false)
- ->activity_type('varchar', 32, false, "'" . basename(__DIR__) . "'")
- ->blog_id('varchar', 32, true)
- ->activity_group('varchar', 32, false)
- ->activity_action('varchar', 32, false)
- ->activity_logs('text', 0, false)
- ->activity_dt('timestamp', 0, false, 'now()')
- ->activity_blog_status('smallint', 0, false, 0)
- ->activity_super_status('smallint', 0, false, 0)
-
- ->primary('pk_activity', 'activity_id')
- ->index('idx_activity_type', 'btree', 'activity_type')
- ->index('idx_activity_blog_id', 'btree', 'blog_id')
- ->index('idx_activity_action', 'btree', 'activity_group', 'activity_action')
- ->index('idx_activity_blog_status', 'btree', 'activity_blog_status')
- ->index('idx_activity_super_status', 'btree', 'activity_super_status');
-
- $s->{initActivityReport::SETTING_TABLE_NAME}
- ->setting_id('varchar', 64, false)
- ->blog_id('varchar', 32, true)
- ->setting_type('varchar', 32, false)
- ->setting_value('text', 0, false)
-
- ->unique('uk_activity_setting', 'setting_id', 'blog_id', 'setting_type')
- ->index('idx_activity_setting_blog_id', 'btree', 'blog_id')
- ->index('idx_activity_setting_type', 'btree', 'setting_type');
-
- $si = new dbStruct(dcCore::app()->con, dcCore::app()->prefix);
- $changes = $si->synchronize($s);
-
- return true;
-} catch (Exception $e) {
- dcCore::app()->error->add($e->getMessage());
-}
-
-return false;
diff --git a/src/Manage.php b/src/Manage.php
index 1db35ec..c6e3693 100644
--- a/src/Manage.php
+++ b/src/Manage.php
@@ -10,83 +10,114 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_CONTEXT_ADMIN')) {
- return null;
-}
+declare(strict_types=1);
-if (!defined('ACTIVITY_REPORT_V2')) {
- return null;
-}
+namespace Dotclear\Plugin\activityReport;
-dcPage::check(dcCore::app()->auth->makePermissions([
- dcAuth::PERMISSION_ADMIN,
-]));
+use ArrayObject;
+use adminGenericFilter;
+use dcAuth;
+use dcCore;
+use dcNsProcess;
+use dcPage;
+use Dotclear\Helper\Html\Form\{
+ Form,
+ Hidden,
+ Para,
+ Submit,
+ Text
+};
+use Exception;
-$super = dcCore::app()->auth->isSuperAdmin() && !empty($_REQUEST['super']);
+/**
+ * Manage process (admin logs list).
+ */
+class Manage extends dcNsProcess
+{
+ public static function init(): bool
+ {
+ static::$init = defined('DC_CONTEXT_ADMIN')
+ && defined('ACTIVITY_REPORT')
+ && My::phpCompliant()
+ && dcCore::app()->auth?->check(dcCore::app()->auth->makePermissions([
+ dcAuth::PERMISSION_ADMIN,
+ ]), dcCore::app()->blog?->id);
-if ($super) {
- dcCore::app()->activityReport->setGlobal();
-}
-
-$logs = dcCore::app()->activityReport->getLogs([]);
-
-if ($super) {
- $breadcrumb = [
- __('Current blog') => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['super' => 0]),
- '' . __('All blogs') . ' ' => '',
- ];
-} else {
- $breadcrumb = ['' . __('Current blog') . ' ' => ''];
- if (dcCore::app()->auth->isSuperAdmin()) {
- $breadcrumb[__('All blogs')] = dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__), ['super' => 1]);
+ return static::$init;
}
-}
-echo '' . __('Activity report') . ' ' .
-dcPage::breadcrumb(array_merge([__('Activity report') => '', __('Logs') => ''], $breadcrumb), ['hl' => false]) .
-dcPage::notices();
-
-if ($logs->isEmpty()) {
- echo '' . __('No log') . '
';
-} else {
- echo '
-
-
- ' . __('Action') . '
- ' . __('Message') . '
- ' . __('Date') . ' ';
- if ($super) {
- echo '' . __('Blog') . ' ';
- }
- echo ' ';
-
- while ($logs->fetch()) {
- $action = dcCore::app()->activityReport->getGroups($logs->activity_group, $logs->activity_action);
-
- if (empty($action)) {
- continue;
+ public static function process(): bool
+ {
+ if (!static::$init) {
+ return false;
}
- $off = $super && $logs->activity_blog_status == 1 ? ' offline' : '';
- $date = dt::str(
- dcCore::app()->blog->settings->system->date_format . ', ' . dcCore::app()->blog->settings->system->time_format,
- strtotime($logs->activity_dt),
- dcCore::app()->auth->getInfo('user_tz')
+ if (!empty($_POST['delete_all_logs']) || !empty($_POST['delete_reported_logs'])) {
+ try {
+ ActivityReport::instance()->deleteLogs(!empty($_POST['delete_reported_logs']));
+ dcPage::addSuccessNotice(__('Logs successfully deleted'));
+ dcCore::app()->adminurl?->redirect('admin.plugin.' . My::id());
+ } catch (Exception $e) {
+ dcCore::app()->error->add($e->getMessage());
+ }
+ }
+
+ return true;
+ }
+
+ public static function render(): void
+ {
+ if (!static::$init) {
+ return;
+ }
+
+ $logs = $counter = $list = null;
+ $filter = new adminGenericFilter(dcCore::app(), My::id());
+ $params = new ArrayObject($filter->params());
+
+ try {
+ $logs = ActivityReport::instance()->getLogs($params);
+ $counter = ActivityReport::instance()->getLogs($params, true);
+ if (!is_null($logs) && !is_null($counter)) {
+ $list = new ManageList(dcCore::app(), $logs, $counter->f(0));
+ }
+ } catch (Exception $e) {
+ dcCore::app()->error->add($e->getMessage());
+ }
+
+ dcPage::openModule(
+ My::name(),
+ $filter->js((string) dcCore::app()->adminurl?->get('admin.plugin.' . My::id())) .
+ dcPage::jsJson(My::id(), ['confirm_delete' => __('Are you sure you want to delete logs?')]) .
+ dcPage::jsModuleLoad(My::id() . '/js/backend.js') .
+
+ # --BEHAVIOR-- activityReportListHeader --
+ dcCore::app()->callBehavior('activityReportListHeader')
);
- $msg = vsprintf(__($action['msg']), dcCore::app()->activityReport->decode($logs->activity_logs));
- echo '
-
- ' . __($action['title']) . '
- ' . $msg . '
- ' . $date . ' ';
- if ($super) {
- echo '' . $logs->blog_id . ' ';
+ echo
+ dcPage::breadcrumb([
+ __('Plugins') => '',
+ My::name() => '',
+ ]) .
+ dcPage::notices();
+
+ if (!is_null($list)) {
+ $filter->display('admin.plugin.' . My::id(), (new Hidden('p', My::id()))->render());
+ $list->logsDisplay($filter, '%s');
}
- echo ' ';
- }
- echo '
';
-}
-dcCore::app()->activityReport->unsetGlobal();
-echo '';
+ if (!is_null($logs) && !$logs->isEmpty()) {
+ echo
+ (new Form('form-logs'))->method('post')->action(dcCore::app()->admin->getPageURL())->fields([
+ (new Para())->class('right')->separator(' ')->items([
+ (new Submit('delete_all_logs'))->class('delete')->value(__('Delete all aticivity logs')),
+ (new Submit('delete_reported_logs'))->class('delete')->value(__('Delete all allready reported logs')),
+ dcCore::app()->formNonce(false),
+ ]),
+ ])->render();
+ }
+
+ dcPage::closeModule();
+ }
+}
diff --git a/src/ManageList.php b/src/ManageList.php
new file mode 100644
index 0000000..424912c
--- /dev/null
+++ b/src/ManageList.php
@@ -0,0 +1,102 @@
+rs || $this->rs->isEmpty()) {
+ if ($filter->show()) {
+ echo '' . __('No log matches the filter') . '
';
+ } else {
+ echo '' . __('No log') . '
';
+ }
+ } else {
+ $pager = new dcPager((int) $filter->value('page'), (int) $this->rs_count, (int) $filter->value('nb'), 10);
+ $pager->var_page = 'page';
+
+ $html_block = '' . (
+ $filter->show() ?
+ sprintf(__('List of %s logs matching the filter.'), $this->rs_count) :
+ sprintf(__('List of %s logs.'), $this->rs_count)
+ ) . ' ';
+
+ $cols = new ArrayObject([
+ 'activity_group' => '' . __('Group') . ' ',
+ 'activity_action' => '' . __('Action') . ' ',
+ 'activity_logs' => '' . __('Message') . ' ',
+ 'activity_date' => '' . __('Date') . ' ',
+ 'activity_status' => '' . __('Status') . ' ',
+ ]);
+
+ $this->userColumns(My::id(), $cols);
+
+ $html_block .= '' . implode(iterator_to_array($cols)) . ' %s
%s
';
+ if ($enclose_block) {
+ $html_block = sprintf($enclose_block, $html_block);
+ }
+ $blocks = explode('%s', $html_block);
+
+ echo $pager->getLinks() . $blocks[0];
+
+ while ($this->rs->fetch()) {
+ echo $this->logsLine();
+ }
+
+ echo $blocks[1] . $blocks[2] . $pager->getLinks();
+ }
+ }
+
+ private function logsLine(): string
+ {
+ $offline = (int) $this->rs->f('activity_status') == ActivityReport::STATUS_REPORTED ? ' offline' : '';
+ $group = ActivityReport::instance()->groups->get($this->rs->f('activity_group'));
+ $action = $group->get($this->rs->f('activity_action'));
+ $message = json_decode((string) $this->rs->f('activity_logs'), true);
+ $message = $message[0] == 'undefined' ? __('undefined') : vsprintf(__($action->message), $message);
+ $date = Date::str(
+ dcCore::app()->blog?->settings->get('system')->get('date_format') . ', ' . dcCore::app()->blog?->settings->get('system')->get('time_format'),
+ (int) strtotime((string) $this->rs->f('activity_dt')),
+ dcCore::app()->auth?->getInfo('user_tz')
+ );
+ $status = (int) $this->rs->f('activity_status') == ActivityReport::STATUS_PENDING ? __('pending') : __('reported');
+
+ $cols = new ArrayObject([
+ 'activity_group' => '' . __($group->title) . ' ',
+ 'activity_action' => '' . __($action->title) . ' ',
+ 'activity_logs' => '' . $message . ' ',
+ 'activity_date' => '' . $date . ' ',
+ 'activity_status' => '' . $status . ' ',
+ ]);
+
+ $this->userColumns(My::id(), $cols);
+
+ return
+ '' .
+ implode(iterator_to_array($cols)) .
+ ' ';
+ }
+}
diff --git a/src/My.php b/src/My.php
new file mode 100644
index 0000000..fec69aa
--- /dev/null
+++ b/src/My.php
@@ -0,0 +1,77 @@
+plugins->moduleInfo(self::id(), 'name'));
+ }
+
+ /**
+ * This module root.
+ */
+ public static function root(): string
+ {
+ return dirname(__DIR__);
+ }
+
+ /**
+ * Check is module is trully installed.
+ *
+ * Required as table structrue has changed
+ */
+ public static function isInstalled(): bool
+ {
+ return dcCore::app()->getVersion(self::id()) == dcCore::app()->plugins->moduleInfo(self::id(), 'version');
+ }
+
+ /**
+ * Check php version.
+ */
+ public static function phpCompliant(): bool
+ {
+ return version_compare(phpversion(), self::PHP_MIN, '>=');
+ }
+}
diff --git a/src/Prepend.php b/src/Prepend.php
index f38fd80..16fd939 100644
--- a/src/Prepend.php
+++ b/src/Prepend.php
@@ -10,30 +10,58 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_RC_PATH')) {
- return null;
-}
+declare(strict_types=1);
-Clearbricks::lib()->autoload([
- 'activityReport' => __DIR__ . '/inc/class.activity.report.php',
- 'activityReportBehaviors' => __DIR__ . '/inc/class.activity.report.behaviors.php',
-]);
+namespace Dotclear\Plugin\activityReport;
-try {
- if (!defined('ACTIVITY_REPORT_V2')) {
- dcCore::app()->__set('activityReport', new activityReport());
+use dcCore;
+use dcNsProcess;
+use Exception;
- dcCore::app()->url->register(
- basename(__DIR__),
- 'reports',
- '^reports/((atom|rss2)/(.+))$',
- ['activityReportPublicUrl', 'feed']
- );
+/**
+ * Prepend process.
+ */
+class Prepend extends dcNsProcess
+{
+ public static function init(): bool
+ {
+ static::$init = defined('DC_RC_PATH')
+ && My::phpCompliant()
+ && My::isInstalled();
- define('ACTIVITY_REPORT_V2', true);
-
- activityReportBehaviors::registerBehaviors();
+ return static::$init;
+ }
+
+ public static function process(): bool
+ {
+ if (!static::$init) {
+ return false;
+ }
+
+ if (defined('ACTIVITY_REPORT')) {
+ return true;
+ }
+
+ try {
+ // launch once activity report stuff
+ ActivityReport::instance();
+
+ // regirster activity feed URL
+ dcCore::app()->url->register(
+ My::id(),
+ 'reports',
+ '^reports/((atom|rss2)/(.+))$',
+ [UrlHandler::class, 'feed']
+ );
+
+ // declare report open
+ define('ACTIVITY_REPORT', My::COMPATIBILITY_VERSION);
+
+ // register predefined activities scan
+ ActivityBehaviors::register();
+ } catch (Exception $e) {
+ }
+
+ return true;
}
-} catch (Exception $e) {
- //throw new Exception('Failed to launch activityReport');
}
diff --git a/src/Settings.php b/src/Settings.php
new file mode 100644
index 0000000..21136e5
--- /dev/null
+++ b/src/Settings.php
@@ -0,0 +1,113 @@
+blog === null) {
+ throw new Exception('Blog is not set');
+ }
+
+ $this->feed_active = (bool) ($this->get('feed_active') ?? false);
+ $this->obsolete = (int) ($this->get('obsolete') ?? 2419200);
+ $this->interval = (int) ($this->get('interval') ?? 86400);
+ $this->lastreport = (int) ($this->get('lastreport') ?? 0);
+ $this->mailinglist = (array) ($this->get('mailinglist') ?? []);
+ $this->mailformat = (string) ($this->get('mailformat') ?? 'plain');
+ $this->dateformat = (string) ($this->get('dateformat') ?? '%Y-%m-%d %H:%M:%S');
+ $this->requests = (array) ($this->get('requests') ?? []);
+ }
+
+ /**
+ * Dump properties.
+ *
+ * @return array The settings properties
+ */
+ public function dump(): array
+ {
+ $vars = get_class_vars(__CLASS__);
+
+ return $vars ? $vars : [];
+ }
+
+ /**
+ * Set a setting in database.
+ *
+ * Setting is modified in database but not in script !
+ *
+ * @param string $key The setting key
+ * @param mixed $value The setting value
+ */
+ public function set(string $key, mixed $value): void
+ {
+ if (property_exists($this, $key) && gettype($value) == gettype($this->{$key})) {
+ dcCore::app()->blog?->settings->get(My::id())->put(
+ $key,
+ $value,
+ gettype($value),
+ null,
+ true,
+ false
+ );
+ }
+ }
+
+ /**
+ * Get a setting from database.
+ *
+ * @param string $key The setting key
+ *
+ * @return mixed The setting value
+ */
+ private function get(string $key): mixed
+ {
+ return dcCore::app()->blog?->settings->get(My::id())->get($key);
+ }
+}
diff --git a/src/Template.php b/src/Template.php
new file mode 100644
index 0000000..419f771
--- /dev/null
+++ b/src/Template.php
@@ -0,0 +1,161 @@
+public->getPageNumber(); if ($_page_number < 1) { $_page_number = 1; }' . "\n\$params = new ArrayObject();\n";
+
+ if ($lastn > 0) {
+ $p .= "\$params['limit'] = " . $lastn . ";\n";
+ } else {
+ $p .= "\$params['limit'] = dcCore::app()->ctx->nb_entry_per_page;\n";
+ }
+
+ if (!isset($attr['ignore_pagination']) || $attr['ignore_pagination'] == '0') {
+ $p .= "\$params['limit'] = array(((\$_page_number-1)*\$params['limit']),\$params['limit']);\n";
+ } else {
+ $p .= "\$params['limit'] = array(0, \$params['limit']);\n";
+ }
+
+ return
+ "ctx->activityreport_params = $params; ' . "\n" .
+ 'dcCore::app()->ctx->activityreports = ' . ActivityReport::class . '::instance()->getLogs($params); unset($params); ' . "\n" .
+ 'while (dcCore::app()->ctx->activityreports->fetch()) : ?>' . $content . 'ctx->pop("activityreports"); dcCore::app()->ctx->pop("activityreport_params"); ' . "\n" .
+ '?>';
+ }
+
+ /**
+ * tpl:activityReportFeedID [attributes] : Activity report feed ID (tpl value)
+ *
+ * attributes:
+ *
+ * - any filters See self::getFilters()
+ *
+ * @param ArrayObject $attr The attributes
+ *
+ * @return string The code
+ */
+ public static function activityReportFeedID(ArrayObject $attr): string
+ {
+ return
+ 'urn:md5:ctx->activityreports->blog_id.' .
+ 'dcCore::app()->ctx->activityreports->activity_id.dcCore::app()->ctx->activityreports->activity_dt); ' .
+ '?>';
+ }
+
+ /**
+ * tpl:activityReportTitle [attributes] : Activity report log title (tpl value)
+ *
+ * attributes:
+ *
+ * - any filters See self::getFilters()
+ *
+ * @param ArrayObject $attr The attributes
+ *
+ * @return string The code
+ */
+ public static function activityReportTitle(ArrayObject $attr): string
+ {
+ $f = dcCore::app()->tpl->getFilters($attr);
+
+ return '';
+ }
+
+ /**
+ * tpl:activityReportContent [attributes] : Activity report log message (tpl value)
+ *
+ * attributes:
+ *
+ * - any filters See self::getFilters()
+ *
+ * @param ArrayObject $attr The attributes
+ *
+ * @return string The code
+ */
+ public static function activityReportContent(ArrayObject $attr): string
+ {
+ $f = dcCore::app()->tpl->getFilters($attr);
+
+ return '';
+ }
+
+ /**
+ * tpl:activityReportDate [attributes] : Activity report log date (tpl value)
+ *
+ * attributes:
+ *
+ * - format Use Date::str() (if iso8601 nor rfc822 were specified default to %Y-%m-%d %H:%M:%S)
+ * - iso8601 (1|0) Use Date::iso8601()
+ * - rfc822 (1|0) Use Date::rfc822()
+ * - any filters See self::getFilters()
+ *
+ * @param ArrayObject $attr The attributes
+ *
+ * @return string The code
+ */
+ public static function activityReportDate(ArrayObject $attr): string
+ {
+ $format = '';
+ if (!empty($attr['format'])) {
+ $format = addslashes($attr['format']);
+ }
+
+ $iso8601 = !empty($attr['iso8601']);
+ $rfc822 = !empty($attr['rfc822']);
+
+ $f = dcCore::app()->tpl->getFilters($attr);
+
+ if ($rfc822) {
+ return 'ctx->activityreports->activity_dt),dcCore::app()->blog->settings->system->blog_timezone)') . '; ?>';
+ } elseif ($iso8601) {
+ return 'ctx->activityreports->activity_dt),dcCore::app()->blog->settings->system->blog_timezone)') . '; ?>';
+ } elseif (!empty($format)) {
+ return 'ctx->activityreports->activity_dt)") . '; ?>';
+ }
+
+ return 'blog->settings->system->date_format,dcCore::app()->ctx->activityreports->activity_dt)') . '; ?>';
+ }
+}
diff --git a/src/Uninstall.php b/src/Uninstall.php
index def1c60..980420d 100644
--- a/src/Uninstall.php
+++ b/src/Uninstall.php
@@ -10,72 +10,78 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
-if (!defined('DC_CONTEXT_ADMIN')) {
- return null;
+declare(strict_types=1);
+
+namespace Dotclear\Plugin\activityReport;
+
+use dcCore;
+use dcNsProcess;
+use Dotclear\Plugin\Uninstaller\Uninstaller;
+
+/**
+ * Uninstall process.
+ *
+ * Using plugin Uninstaller
+ */
+class Uninstall extends dcNsProcess
+{
+ public static function init(): bool
+ {
+ static::$init = defined('DC_CONTEXT_ADMIN');
+
+ return static::$init;
+ }
+
+ public static function process(): bool
+ {
+ if (!static::$init || !dcCore::app()->plugins->moduleExists('Uninstaller')) {
+ return false;
+ }
+
+ Uninstaller::instance()
+ ->addUserAction(
+ 'tables',
+ 'delete',
+ My::ACTIVITY_TABLE_NAME
+ )
+ ->addUserAction(
+ 'settings',
+ 'delete_all',
+ My::id()
+ )
+ ->addUserAction(
+ 'versions',
+ 'delete',
+ My::id()
+ )
+ ->addUserAction(
+ 'plugins',
+ 'delete',
+ My::id()
+ )
+ ->addDirectAction(
+ 'tables',
+ 'delete',
+ My::ACTIVITY_TABLE_NAME
+ )
+ ->addDirectAction(
+ 'settings',
+ 'delete_all',
+ My::id()
+ )
+ ->addDirectAction(
+ 'versions',
+ 'delete',
+ My::id()
+ )
+ ->addDirectAction(
+ 'plugins',
+ 'delete',
+ My::id()
+ )
+ ;
+
+ // no custom action
+ return false;
+ }
}
-
-$this->addUserAction(
- /* type */
- 'tables',
- /* action */
- 'delete',
- /* ns */
- initActivityReport::ACTIVITY_TABLE_NAME,
- /* description */
- sprintf(__('delete %s table'), '"activity"')
-);
-
-$this->addUserAction(
- /* type */
- 'tables',
- /* action */
- 'delete',
- /* ns */
- initActivityReport::SETTING_TABLE_NAME,
- /* description */
- sprintf(__('delete %s table'), '"activity_setting"')
-);
-
-$this->addUserAction(
- /* type */
- 'plugins',
- /* action */
- 'delete',
- /* ns */
- basename(__DIR__),
- /* description */
- __('delete plugin files')
-);
-
-$this->addUserAction(
- /* type */
- 'versions',
- /* action */
- 'delete',
- /* ns */
- basename(__DIR__),
- /* description */
- __('delete the version number')
-);
-
-$this->addDirectAction(
- /* type */
- 'versions',
- /* action */
- 'delete',
- /* ns */
- basename(__DIR__),
- /* description */
- sprintf(__('delete %s version number'), basename(__DIR__))
-);
-
-$this->addDirectAction(
- /* type */
- 'plugins',
- /* action */
- 'delete',
- /* ns */
- basename(__DIR__),
- /* description */
- sprintf(__('delete %s plugin files'), basename(__DIR__))
-);
diff --git a/src/UrlHandler.php b/src/UrlHandler.php
new file mode 100644
index 0000000..4b8a6cc
--- /dev/null
+++ b/src/UrlHandler.php
@@ -0,0 +1,56 @@
+ctx
+ || !preg_match('/^(atom|rss2)\/(.+)$/', (string) $args, $m)
+ || !defined('ACTIVITY_REPORT')
+ || !ActivityReport::instance()->settings->feed_active
+ ) {
+ self::p404();
+ }
+
+ // get type of feed
+ $mime = $m[1] == 'atom' ? 'application/atom+xml' : 'application/xml';
+ if (false === ActivityReport::instance()->checkUserCode($m[2])) {
+ self::p404();
+ }
+
+ // feed limits
+ dcCore::app()->ctx->__set('nb_entry_per_page', (int) dcCore::app()->blog?->settings->get('system')->get('nb_post_per_feed'));
+ dcCore::app()->ctx->__set('short_feed_items', (int) dcCore::app()->blog?->settings->get('system')->get('short_feed_items'));
+
+ // serve activity feed template
+ header('X-Robots-Tag: ' . context::robotsPolicy(dcCore::app()->blog?->settings->get('system')->get('robots_policy'), ''));
+ self::serveDocument('activityreport-' . $m[1] . '.xml', $mime);
+ }
+}