Browse Source

Importation du plugin "Notifications avancées".

Le but de ce plugin est de remplacer l'ancien "Notifications", en mieux, plus générique, plus extensible, etc. Pour l'instant il est dans un plugin séparé, car il manque encore des choses pour reproduire ce qui existait (mais ça sait le faire et bien plus encore).

Avec ce plugin, on peut :
- définir des modes d'envois, seul l'email est installé ici
- abonner explicitement des utilisateurs à des notifications (dans une table)
- pour chaque notifications, un utilisateur peut définir quel mode d'envoi il préfère (en tout cas c'est prévu dans la table)
- blacklister explicitement des utilisateurs pour une notifications (dans la même table), ce qui permet de ne pas recevoir de notifications pour une où on serait destinataire par défaut
- faire une notification uniquement avec un squelette notifications/truc.html (mais dans ce cas il n'y a pas de destinataires par défaut, il faut donc y abonner des gens explicitement)
- la forme "notifications/patate_truc.html" est reconnu, donc dans le contexte du squelette on a automatiquement "id_patate=..."
- définir des destinataires par défaut pour une notification avec une fonction "notifications_truc_destinataires($id, options)", doit renvoyer un tableau avec soit des identifiants d'auteurs, soit une info de contact (le mail par ex)
- définir trois formats pour une notification : "truc.html" pour le texte normal, "truc_html.html" pour le format HTML, et "truc_court.html" pour un format court du style SMS ou Microblog.
- définir ces trois contenus aussi dans un fonction PHP si on a besoin d'un truc plus complexe, dans une fonction "notifications_truc_contenu($id, $options, $destinataire)". Cette fonction doit renvoyer soit un tableau contenu avec comme clés possibles "texte", "html" et "court", soit une string, qui sera alors utilisée pour le texte normal
- définir une fonction de "préférences" pour une notification, dans "notifications_truc_preferences($id, $options, $preferences)". Cette fonction reçoit les préférences de l'utilisateur qui sont stockés dans la table des abonnés explicites. Elle doit renvoyer true ou false suivant que les préférences de cet abonné indiquent qu'il doit recevoir la notif ou pas. Dans la table, les préférences sont stockées dans un seul champ dans un tableau sérialisé. Pour l'instant il n'y a pas d'interface automatique pour gérer les préférences, c'est aux devs de faire leurs formulaires. À terme le but est de déclarer les préférences d'une notification dans un fichier YAML, avec des Saisies, donc possibilité de générer automatiquement des formulaires de config.

Et j'oublie sûrement encore des choses !
svn/root/tags/v0.4.4
rastapopoulos@spip.org 11 years ago
commit
86c99904f7
  1. 20
      .gitattributes
  2. 57
      action/abonner_notification.php
  3. 29
      action/supprimer_notifications_abonnement.php
  4. 36
      action/toggle_notifications_abonnement.php
  5. 55
      base/notifavancees_installation.php
  6. 47
      base/notifavancees_tables.php
  7. 24
      formulaires/abonner_notification.html
  8. 46
      formulaires/abonner_notification.php
  9. 72
      formulaires/notifications_auteur.html
  10. 45
      formulaires/notifications_auteur.php
  11. BIN
      images/notifications-128.png
  12. BIN
      images/notifications-24.png
  13. 42
      inc/notifications_autoriser.php
  14. 23
      lang/notifavancees_fr.php
  15. 423
      notifavancees_pipelines.php
  16. 46
      notifications/modes/email.php
  17. 3
      notifications/modes/email.yaml
  18. 42
      plugin.xml
  19. 28
      prive/boite/notifications_auteur.html
  20. 21
      prive/exec/notifications_auteur.html

20
.gitattributes vendored

@ -0,0 +1,20 @@
* text=auto !eol
action/abonner_notification.php -text
action/supprimer_notifications_abonnement.php -text
action/toggle_notifications_abonnement.php -text
base/notifavancees_installation.php -text
base/notifavancees_tables.php -text
formulaires/abonner_notification.html -text
formulaires/abonner_notification.php -text
formulaires/notifications_auteur.html -text
formulaires/notifications_auteur.php -text
images/notifications-128.png -text
images/notifications-24.png -text
inc/notifications_autoriser.php -text
lang/notifavancees_fr.php -text
/notifavancees_pipelines.php -text
notifications/modes/email.php -text
notifications/modes/email.yaml -text
/plugin.xml -text
prive/boite/notifications_auteur.html -text
prive/exec/notifications_auteur.html -text

57
action/abonner_notification.php

@ -0,0 +1,57 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
/**
* Action d'abonnement à une notification
* @param unknown_type $arg
* @return unknown_type
*/
function action_abonner_notification_dist($arg=null, $modes=array(), $preferences=array()) {
if (is_null($arg)){
$securiser_action = charger_fonction('securiser_action', 'inc');
$arg = $securiser_action();
}
include_spip('inc/session');
// Pour faire l'abonnement :
// - $arg doit être de la forme "quoi-id"
// - le visiteur doit être un auteur OU il doit y avoir un _request('contact')
if (list($quoi, $id) = explode('-', $arg)
and $quoi
and (($id_auteur = session_get('id_auteur')) > 0 or $contact = _request('contact'))
){
include_spip('base/abtract_sql');
// On nettoie l'une ou l'autre des informations
if ($id_auteur) $contact = '';
else $id_auteur = 0;
// S'il n'y a pas de mode d'envoi dans l'appel, et pas dans l'environnement
// alors on abonne par email par défaut
if (!$modes and !$modes = _request('modes'))
$modes = array('email');
// S'il n'y a pas de préférences dans l'appel, on regarde dans l'environnement
if (!$preferences and $prefs = _request('preferences') and is_array($prefs)){
$preferences = $prefs;
}
// Enfin on insert l'abonnement
sql_insertq(
'spip_notifications_abonnements',
array(
'id_auteur' => $id_auteur,
'contact' => $contact,
'quoi' => $quoi,
'id' => $id,
'modes' => $modes,
'preferences' => $preferences
)
);
}
}
?>

29
action/supprimer_notifications_abonnement.php

@ -0,0 +1,29 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
/**
* Action d'activation / désactivation d'un abonnement
* @param unknown_type $arg
* @return unknown_type
*/
function action_supprimer_notifications_abonnement_dist($arg=null) {
if (is_null($arg)){
$securiser_action = charger_fonction('securiser_action', 'inc');
$arg = $securiser_action();
}
// On ne fait quelque chose que si l'identifiant est correct
// et que l'abonnement est actif
if ($id_notifications_abonnement = intval($arg)
and $id_notifications_abonnement = intval(sql_getfetsel('id_notifications_abonnement', 'spip_notifications_abonnements', 'id_notifications_abonnement = '.$id_notifications_abonnement))
){
sql_delete(
'spip_notifications_abonnements',
'id_notifications_abonnement = '.$id_notifications_abonnement
);
}
}
?>

36
action/toggle_notifications_abonnement.php

@ -0,0 +1,36 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
/**
* Action d'activation / désactivation d'un abonnement
* @param unknown_type $arg
* @return unknown_type
*/
function action_toggle_notifications_abonnement_dist($arg=null) {
if (is_null($arg)){
$securiser_action = charger_fonction('securiser_action', 'inc');
$arg = $securiser_action();
}
// On ne fait quelque chose que si l'identifiant est correct
// et que l'abonnement est actif
if ($id_notifications_abonnement = intval($arg)
and ($actif = sql_getfetsel('actif', 'spip_notifications_abonnements', 'id_notifications_abonnement = '.$id_notifications_abonnement)) !== false
){
if ($actif) $actif = 0;
else $actif = 1;
sql_updateq(
'spip_notifications_abonnements',
array(
'actif' => $actif
)
,
'id_notifications_abonnement = '.$id_notifications_abonnement
);
}
}
?>

55
base/notifavancees_installation.php

@ -0,0 +1,55 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
include_spip('inc/meta');
// Installation et mise à jour
function notifavancees_upgrade($nom_meta_version_base, $version_cible){
$version_actuelle = '0.0';
if (
(!isset($GLOBALS['meta'][$nom_meta_version_base]))
|| (($version_actuelle = $GLOBALS['meta'][$nom_meta_version_base]) != $version_cible)
){
if (version_compare($version_actuelle,'0.0','=')){
// Création des tables
include_spip('base/create');
include_spip('base/abstract_sql');
creer_base();
ecrire_meta($nom_meta_version_base, $version_actuelle=$version_cible, 'non');
}
/*if (version_compare($version_actuelle,'0.5','<')){
include_spip('base/create');
include_spip('base/abstract_sql');
// Modification de notifavancees
sql_alter('');
// On change la version
echo "Mise à jour du plugin notifavancees en version 0.5<br/>";
ecrire_meta($nom_meta_version_base, $version_actuelle=$version_cible, 'non');
}*/
}
}
// Désinstallation
function notifavancees_vider_tables($nom_meta_version_base){
include_spip('base/abstract_sql');
// On efface les tables du plugin
sql_drop_table('spip_notifications_abonnements');
// On efface la version entregistrée
effacer_meta($nom_meta_version_base);
}
?>

47
base/notifavancees_tables.php

@ -0,0 +1,47 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
function notifavancees_declarer_tables_interfaces($interface){
// 'spip_' dans l'index de $tables_principales
$interface['table_des_tables']['notifications_abonnements'] = 'notifications_abonnements';
// Traitements sur certains champs
// On désarialise d'avance les tableaux
$interface['table_des_traitements']['MODES']['notifications_abonnements'] = 'unserialize(%s)';
$interface['table_des_traitements']['PREFERENCES']['notifications_abonnements'] = 'unserialize(%s)';
return $interface;
}
function notifavancees_declarer_tables_principales($tables_principales){
//-- Table notifications -----------------------------------------------------------
$notifications_abonnements = array(
'id_notifications_abonnement' => 'bigint(21) NOT NULL',
'id_auteur' => 'bigint(21) not null default 0',
'contact' => 'tinytext not null default ""', // pour ceux qui n'ont pas un compte auteur
'quoi' => 'tinytext not null',
'id' => 'bigint(21) not null default 0',
'preferences' => 'text not null default ""', // pour les options *de l'abonnement* et non de la notif
'modes' => 'text not null default ""',
'actif' => 'tinyint(1) not null default 1'
);
$notifications_abonnements_cles = array(
'PRIMARY KEY' => 'id_notifications_abonnement',
'KEY id_auteur' => 'id_auteur'
);
$tables_principales['spip_notifications_abonnements'] = array(
'field' => &$notifications_abonnements,
'key' => &$notifications_abonnements_cles,
'join'=> array(
'id_notification' => 'id_notifications_abonnement'
)
);
return $tables_principales;
}
?>

24
formulaires/abonner_notification.html

@ -0,0 +1,24 @@
<div class="formulaire_spip formulaire_editer formulaire_#ENV{form}[ formulaire_#ENV{form}-(#ENV{id,nouveau})]">
[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</p>]
[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
[(#ENV{editable}|oui)
<form method="post" action="#ENV{action}" enctype="multipart/form-data"><div>
[(#REM) declarer les hidden qui declencheront le service du formulaire
parametre : url d'action ]
#ACTION_FORMULAIRE{#ENV{action}}
<ul>
#GENERER_SAISIES{#ENV{_infos_notification}|table_valeur{preferences}}
</ul>
[(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ]
<!--extra-->
<p class="boutons">
<span class="image_loading"></span>
<input type="submit" class="submit" value="<:bouton_enregistrer:>" />
</p>
</div></form>
]
</div>

46
formulaires/abonner_notification.php

@ -0,0 +1,46 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
function formulaires_abonner_notification_charger($id_notifications_abonnement, $redirect='', $quoi='', $id=0, $option=array()){
$contexte = array();
$id_notifications_abonnement = intval($id_notifications_abonnement);
// S'il n'y a ni identifiant d'abonnement correct, ni les infos requises pour un nouvel abonnement, kaput !
if (
(!$id_notifications_abonnement
or !($abonnement = sql_fetsel('*', 'spip_notifications_abonnements', 'id_notifications_abonnement = '.$id_notifications_abonnement))
)
and !($quoi and $id)
)
return false;
include_spip('notifavancees_pipelines');
// Si c'est un abonnement déjà là, on récupère les infos dont on a besoin
if ($abonnement){
$quoi = $abonnement['quoi'];
$id = $abonnement['id'];
}
// On va chercher les paramètres de ce type de notification
$contexte['_infos_notification'] = notifications_charger_infos($quoi);
return $contexte;
}
function formulaires_abonner_notification_verifier($id_notifications_abonnement, $redirect='', $quoi='', $id=0, $option=array()){
$erreurs = array();
return $erreurs;
}
function formulaires_abonner_notification_traiter($id_notifications_abonnement, $redirect='', $quoi='', $id=0, $option=array()){
$retours = array();
return $retours;
}
?>

72
formulaires/notifications_auteur.html

@ -0,0 +1,72 @@
<div class="formulaire_spip formulaire_editer formulaire_#ENV{form}[ formulaire_#ENV{form}-(#ENV{id,nouveau})]">
[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</p>]
[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
<form method="post" action="#ENV{action}" enctype="multipart/form-data"><div>
[(#REM) declarer les hidden qui declencheront le service du formulaire
parametre : url d'action ]
#ACTION_FORMULAIRE{#ENV{action}}
<table>
<thead>
<tr>
<th class="selection"></th>
<th class="type">Type</th>
<th class="objet">Objet</th>
<th class="modes">Modes d'envoi</th>
<th class="statut">Statut</th>
<th class="actions">Actions</th>
</tr>
</thead>
<tbody>
<BOUCLE_notifications(NOTIFICATIONS_ABONNEMENTS){id_auteur=#ENV{_id_auteur}}>
[(#SET{objet,[(#QUOI|explode{_}|table_valeur{0})]})]
<tr>
<td class="selection">
<input type="checkbox" name="notifications[]" value="#ID_NOTIFICATIONS_ABONNEMENT" />
</td>
<td class="type">
[(#ENV{_notifications_disponibles}|table_valeur{#QUOI}|table_valeur{titre}|sinon{#QUOI})]
</td>
<td class="objet">#INFO_TITRE{#GET{objet}, #ID}</td>
<td class="modes">
<BOUCLE_modes(POUR){tableau #MODES}{", "}>
[(#ENV{_modes_disponibles}|table_valeur{#VALEUR}|table_valeur{titre}|sinon{#VALEUR})]
</BOUCLE_modes>
<em><:notifavancees:modes_refus:></em>
<//B_modes>
</td>
<td class="statut">[(#ACTIF|?{Activé, Désactivé})]</td>
<td class="actions">
[(#REM) Pour l'instant on édite rien
[(#AUTORISER{modifier,notifications_abonnement,#ID_NOTIFICATIONS_ABONNEMENT}|oui)
<:notifavancees:abonnement_action_editer:>
]
]
[(#AUTORISER{toggle,notifications_abonnement,#ID_NOTIFICATIONS_ABONNEMENT}|oui)
<a href="#URL_ACTION_AUTEUR{toggle_notifications_abonnement,#ID_NOTIFICATIONS_ABONNEMENT,#SELF}">
[(#ACTIF|?{<:notifavancees:abonnement_action_desactiver:>,<:notifavancees:abonnement_action_activer:>})]
</a>
]
[(#AUTORISER{supprimer,notifications_abonnement,#ID_NOTIFICATIONS_ABONNEMENT}|oui)
<a href="#URL_ACTION_AUTEUR{supprimer_notifications_abonnement,#ID_NOTIFICATIONS_ABONNEMENT,#SELF}"
onclick="return confirm('<:notifavancees:confirmer_supprimer:>')"
>
<:notifavancees:abonnement_action_supprimer:>
</a>
]
</td>
</tr>
</BOUCLE_notifications>
</tbody>
</table>
[(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ]
<!--extra-->
<p class="boutons">
<span class="image_loading"></span>
<input type="submit" class="submit" value="<:bouton_enregistrer:>" />
</p>
</div></form>
</div>

45
formulaires/notifications_auteur.php

@ -0,0 +1,45 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
include_spip('notifavancees_pipelines');
function formulaires_notifications_auteur_charger($id_auteur){
$contexte = array();
// Attention à l'id_auteur
if (!($id_auteur = intval($id_auteur) and $id_auteur > 0))
return false;
$contexte['_id_auteur'] = $id_auteur;
// On va chercher tous les abonnements de cet auteur et on pré-transforme
/*$notifications = sql_allfetsel(
'*',
'spip_notifications_abonnements',
'id_auteur = '.$id_auteur
);*/
// On va chercher les informations sur toutes les notifications disponibles
$contexte['_notifications_disponibles'] = notifications_lister_disponibles();
// On va chercher les informations sur tous les modes d'envoi disponibles
$contexte['_modes_disponibles'] = notifications_modes_lister_disponibles();
return $contexte;
}
function formulaires_notifications_auteur_verifier($id_auteur){
$erreurs = array();
return $erreurs;
}
function formulaires_notifications_auteur_traiter($id_auteur){
$retours = array();
return $retours;
}
?>

BIN
images/notifications-128.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
images/notifications-24.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

42
inc/notifications_autoriser.php

@ -0,0 +1,42 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
function notifavancees_autoriser(){
}
// Configurer les notifications d'un auteur : soit l'auteur soit un admin
function autoriser_auteur_configurer_notifications_dist($faire, $type, $id, $qui, $options){
if (($qui['statut'] <= '0minirezo' and !$qui['restreint'])
or ($id>0 and $qui['id_auteur'] == $id)
)
return true;
else
return false;
}
// Modifier un abonnement : soit l'abonné, soit un admin
function autoriser_notifications_abonnement_modifier_dist($faire, $type, $id, $qui, $options){
if (($qui['statut'] <= '0minirezo' and !$qui['restreint'])
or (
$id_auteur = intval(sql_getfetsel('id_auteur', 'spip_notifications_abonnements', 'id_notifications_abonnement = '.intval($id)))
and $qui['id_auteur'] == $id_auteur
)
)
return true;
else
return false;
}
// Désactiver un abonnement : pouvoir modifier
function autoriser_notifications_abonnement_toggle_dist($faire, $type, $id, $qui, $options){
return autoriser('modifier', 'notifications_abonnement', $id, $qui, $options);
}
// Supprimer un abonnement : pouvoir modifier
function autoriser_notifications_abonnement_supprimer_dist($faire, $type, $id, $qui, $options){
return autoriser('modifier', 'notifications_abonnement', $id, $qui, $options);
}
?>

23
lang/notifavancees_fr.php

@ -0,0 +1,23 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
$GLOBALS[$GLOBALS['idx_lang']] = array(
'abonnement_action_activer' => 'Activer',
'abonnement_action_desactiver' => 'D&eacute;sactiver',
'abonnement_action_editer' => '&Eacute;diter',
'abonnement_action_supprimer' => 'Supprimer',
'config_modifier_notifications_auteur' => 'Modifier les abonnements',
'confirmer_supprimer' => '&Ecirc;tes-vous s&ucirc;r de vouloir supprimer cette notification ?',
'infos_mes_notifications' => 'Mes notifications',
'infos_notifications' => 'Notifications',
'infos_nb_abonnements' => 'Abonn&eacute; &agrave; @nb@ notification(s)',
'infos_nb_refus' => '@nb@ notification(s) refusées',
'modes_email_choix' => 'Me pr&eacute;venir par e-mail &agrave; l\'adresse :',
'modes_email_description' => 'Envoie une notification sur votre adresse e-mail.',
'modes_email_titre' => 'Courriel',
'modes_refus' => 'Ne rien envoyer',
);
?>

423
notifavancees_pipelines.php

@ -0,0 +1,423 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
function notifavancees_notifications($flux){
// On récupère les infos
$quoi = $flux['args']['quoi'];
$id = intval($flux['args']['id']);
$options = $flux['args']['options'];
// On cherche d'abord les destinataires vu que s'il n'y en a pas, on ne fait rien :)
$destinataires = notifications_destinataires($quoi, $id, $options);
// Youpiiii la liste des destinataires est terminée
// On ne continue que s'il en reste
if ($destinataires){
include_spip('inc/filtres');
// On récupère les abonnés explicites pour connaître les éventuelles préférences d'envoi
$preferences = notifications_abonnes($quoi, $id);
// On programme les envois pour chaque destinataire un par un
foreach ($destinataires as $cle=>$destinataire){
// Si c'est un tableau avec déjà toutes les infos
if (is_array($destinataire)){
foreach ($destinataire as $mode=>$contact){
job_queue_add('notifications_envoyer', "Notification ($quoi, $id) par le mode $mode pour <$contact>", array($contact, $mode, $quoi, $id, $options), 'notifavancees_pipelines');
}
}
// Sinon c'est soit un id_auteur soit un mail
// Si on le trouve dans les préférences, on les suit
elseif ($modes = $preferences[$destinataire]['modes']){
foreach ($modes as $mode){
job_queue_add('notifications_envoyer', "Notification ($quoi, $id) par le mode $mode pour <$destinataire>", array($destinataire, $mode, $quoi, $id, $options), 'notifavancees_pipelines');
}
}
// Si c'est pas dans les préférences
// et que $destinataire est SOIT un mail SOIT un id_auteur
// (on vérifie quand même et on ne traite pas les autres cas qui à priori sont pathologiques)
// alors on envoie uniquement par courriel par défaut
elseif ((intval($destinataire) == $destinataire and $destinataire > 0) or email_valide($destinataire)){
$mode = 'email';
job_queue_add('notifications_envoyer', "Notification ($quoi, $id) par le mode $mode pour <$destinataire>", array($destinataire, $mode, $quoi, $id, $options), 'notifavancees_pipelines');
}
}
}
}
/*
* Retourne la liste des destinataires pour une notification précise.
*
* La liste est un tableau pouvant être composé de trois choses :
* - Un identifiant d'auteur
* - Une adresse de courriel
* - Un tableau associatif mode=>information définissant directement les modes de contact, par exemple 'email'=>'truc@machin.com'
*
* Les destinataires peuvent provenir de trois sources différentes :
* - La notification "truc" peut définir une fonction notifications_truc_destinataires()
* - La table "spip_notifications_abonnements" qui défini les abonnés explicites
* - Le pipeline "notifications_destinataires"
*
* @param string $quoi Le nom de la notification
* @param int $id Un éventuel identifiant d'objet lié à la notification
* @param array $options Des options supplémentaires
* @return array Retourne un tableau de destinataires sous la forme décrite ci-dessus
*/
function notifications_destinataires($quoi, $id=0, $options=array()){
// On retourne toujours un tableau
$destinataires = array();
// En premier les destinataires choisis par la notification
if ($fonction_destinataires = charger_fonction('destinataires', "notifications/$quoi", true))
$destinataires = $fonction_destinataires($id, $options);
// Ensuite, ceux qui sont abonnés explicitement
// Pour les préférences, la notification peut définir une fonction notifications_truc_preferences()
$abonnes = notifications_abonnes($quoi, $id);
if (is_array($abonnes) and $abonnes){
// On cherche l'éventuelle fonction qui sait gérer les préférences
$fonction_preferences = charger_fonction('preferences', "notifications/$quoi", true);
// On teste tous les abonnés un par un
foreach ($abonnes as $dest=>$infos){
// S'il n'y pas de préférences, on ajoute directement
if (!$infos['preferences']){
$destinataires[] = $dest;
}
// Sinon on applique le test de la fonction dédiée pour savoir si on ajoute
elseif ($fonction_preferences and $fonction_preferences($id, $options, $infos['preferences'])){
$destinataires[] = $dest;
}
}
}
// Ensuite on passe dans le pipeline
$destinataires = pipeline(
'notifications_destinataires',
array(
'args' => array('quoi'=>$quoi, 'id'=>$id, 'options'=>$options),
'data' => $destinataires
)
);
// On supprime les doublons
$destinataires = array_unique($destinataires);
// Enfin on retire ceux qui se sont blacklistés explicitement
if ($blacklist = notifications_abonnes($quoi, $id, true))
$destinataires = notifications_exclure_destinataires($destinataires, $blacklist);
return $destinataires;
}
/*
* Exclure une liste de destinataires d'une autre liste
*
* @param array $destinataires La liste initiale de destinataires
* @param array @blacklist La liste qu'on veut exclure
* @return array Retourne la première liste moins la seconde
*/
function notifications_exclure_destinataires($destinataires, $blacklist){
foreach ($blacklist as $exclu){
// Si on le trouve direct, soit l'auteur, soit le contact, on le vire
if ($cles = array_keys($destinataires, $exclu)){
foreach ($cles as $cle)
unset($destinataires[$cle]);
}
// Sinon on essaye de le trouver dans les tableaux éventuels
else{
$destinataires_tableau = array_filter($destinataires, 'is_array');
foreach ($destinataires_tableau as $cle => $tableau){
if (in_array($exclu, $tableau))
unset($destinataires[$cle]);
}
}
}
return $destinataires;
}
/*
* Retourne la liste des abonnés explicites à une notification.
* Cette fonction est à utiliser pour ne pas refaire plusieurs appels à la base de données dans un même hit PHP.
*
* Si on demande les abonnés le tableau est de la forme id=>modes.
* Si on demande les blacklistés le tableau contient la liste directement, soit l'id_auteur soit le contact.
*
* @param string $quoi Le nom de la notification
* @param int $id Un éventuel identifiant d'objet lié à la notification
* @param bool $blacklist Indique si l'on retourne ceux qui ne veulent PAS être notifiés
* @return array Retourne un tableau des abonnés ou des blacklistés
*/
function notifications_abonnes($quoi, $id=0, $blacklist=false){
static $abonnes = array();
static $blacklistes = array();
// On normalise l'id
if (!($id = intval($id)) or !($id > 0))
$id = 0;
// On ne fait la requête que si on a pas déjà les valeurs
if (
(!$blacklist and !isset($abonnes[$quoi][$id]))
or ($blacklist and !isset($blacklistes[$quoi][$id]))
){
include_spip('base/abtract_sql');
$where = array(
'quoi = '.sql_quote($quoi)
);
// S'il y a un id pertinent on le rajoute à la requête
if ($id > 0)
$where[] = 'id = '.$id;
// On va chercher tous les gens liés à cette notification
$requete = sql_allfetsel(
'id_auteur, contact, preferences, modes, actif',
'spip_notifications_abonnements',
$where
);
$abonnes[$quoi][$id] = $blacklistes[$quoi][$id] = array();
foreach ($requete as $ligne){
// On ne fait quelque chose que si l'abonnement est actif !
if ($ligne['actif']){
// S'il y a des préférences de modes d'envoi, c'est un abonné
if ($modes = trim($ligne['modes']) and $modes = unserialize($modes) and is_array($modes)){
$infos = array('modes'=>$modes, 'preferences'=>unserialize($ligne['preferences']));
// Si c'est un auteur on met ça comme clé
if ($ligne['id_auteur'] > 0)
$abonnes[$quoi][$id][$ligne['id_auteur']] = $infos;
// Sinon on met l'information de contact
else
$abonnes[$quoi][$id][$ligne['contact']] = $infos;
}
// Sinon c'est un blacklisté
else{
// Si c'est un auteur on met l'id
if ($ligne['id_auteur'] > 0)
$blacklistes[$quoi][$id][] = $ligne['id_auteur'];
// Sinon on met l'information de contact
else
$blacklistes[$quoi][$id][] = $ligne['contact'];
}
}
}
}
// On retourne
if (!$blacklist)
return $abonnes[$quoi][$id];
else
return $blacklist[$quoi][$id];
}
/*
* Liste toutes les notifications installées
*
* @return array Un tableau listant les notifications et leurs informations
*/
function notifications_lister_disponibles(){
static $notifications = null;
if (is_null($notifications)){
$notifications = array();
$liste = find_all_in_path('notifications/', '.+[.]yaml$');
if (count($liste)){
foreach ($liste as $fichier=>$chemin){
$type_notification = preg_replace(',[.]yaml$,i', '', $fichier);
$dossier = str_replace($fichier, '', $chemin);
if (is_array($notification = notifications_charger_infos($type_notification))){
$notifications[$type_notification] = $notification;
}
}
}
}
return $notifications;
}
/*
* Charger les informations contenues dans le yaml d'une notification
*
* @param string $type_notification Le type de la notification
* @return array Un tableau contenant le YAML décodé
*/
function notifications_charger_infos($type_notification){
include_spip('inc/yaml');
$fichier = find_in_path("notifications/$type_notification.yaml");
$notification = yaml_decode_file($fichier);
if (is_array($notification)){
$notification['titre'] = $notification['titre'] ? _T_ou_typo($notification['titre']) : $type_notification;
$notification['description'] = $notification['description'] ? _T_ou_typo($notification['description']) : '';
$notification['icone'] = $notification['icone'] ? find_in_path($notification['icone']) : '';
}
return $notification;
}
/*
* Liste tous les modes d'envoi installés.
*
* @return array Un tableau listant les modes et leurs informations
*/
function notifications_modes_lister_disponibles(){
static $modes = null;
if (is_null($modes)){
$modes = array();
$liste = find_all_in_path('notifications/modes/', '.+[.]yaml$');
if (count($liste)){
foreach ($liste as $fichier=>$chemin){
$type_mode = preg_replace(',[.]yaml$,i', '', $fichier);
$dossier = str_replace($fichier, '', $chemin);
// On ne garde que les modes qui ont bien la fonction d'envoi
if (charger_fonction('envoyer', "notifications/modes/$type_mode/", true)
and (
is_array($mode = notifications_modes_charger_infos($type_mode))
)
){
$modes[$type_mode] = $mode;
}
}
}
}
return $modes;
}
/*
* Charger les informations contenues dans le yaml d'un mode d'envoi
*
* @param string $type_mode Le type du mode d'envoi
* @return array Un tableau contenant le YAML décodé
*/
function notifications_modes_charger_infos($type_mode){
include_spip('inc/yaml');
$fichier = find_in_path("notifications/modes/$type_mode.yaml");
$mode = yaml_decode_file($fichier);
if (is_array($mode)){
$mode['titre'] = $mode['titre'] ? _T_ou_typo($mode['titre']) : $type_mode;
$mode['description'] = $mode['description'] ? _T_ou_typo($mode['description']) : '';
$mode['choix'] = $mode['choix'] ? _T_ou_typo($mode['choix']) : '';
$mode['icone'] = $mode['icone'] ? find_in_path($mode['icone']) : '';
}
return $mode;
}
/*
* Fonction centrale d'envoi d'UNE notification.
* C'est elle qui fait la jonction entre un destinataire, un mode d'envoi, et le bon contenu approprié au mode.
*
* @param mixed $contact Le destinataire à qui envoyer, cela peut-être un id_auteur, ou une information de contact (mail, téléphone, etc)
* @param string $mode Le mode d'envoi à utiliser
* @param string $quoi La nom de la notification
* @param int $id Un éventuel identifiant d'objet lié à la notification
* @param array $options Des options supplémentaires
* @return bool Retourne false si une erreur se produit
*/
function notifications_envoyer($destinataire, $mode, $quoi, $id=0, $options=array()){
// On commence par aller chercher la bonne information de contact adapté au mode
// Car si on ne la trouve pas... on envoie rien
if (
$mode_envoyer = charger_fonction('envoyer', "notifications/modes/$mode/", true)
and $mode_contact = charger_fonction('contact', "notifications/modes/$mode/", true)
and $contact = $mode_contact($destinataire)
){
// On cherche maintenant le contenu
$contenu = array();
// Si la notification a une fonction dédiée au contenu, c'est ça qu'on prend
if ($notification_contenu = charger_fonction('contenu', "notifications/$quoi/", true)){
$contenu_tmp = $notification_contenu($id, $options, $destinataire);
if (is_array($contenu_tmp))
$contenu = $contenu_tmp;
elseif (is_string($contenu_tmp))
$contenu['texte'] = $contenu_tmp;
}
// On construit le contexte utile
$contexte = array(
'quoi' => $quoi,
'id' => $id,
'options' => $options,
'destinataire' => $destinataire,
'contact' => $contact
);
// Pour ajouter des informations utiles, on utilise le même principe que les modèles : le premier mot est le type
include_spip('base/abstract_sql');
$type_objet = explode('_', $quoi);
$type_objet = $type_objet[0];
$cle_objet = id_table_objet($type_objet);
$contexte['objet'] = $type_objet;
$contexte['id_objet'] = $id;
$contexte[$cle_objet] = $id;
// Le contenu de base est le contenu texte
// S'il n'existe pas on cherche le squelette directement
if (!$contenu['texte'] and find_in_path("notifications/${quoi}.html")){
$contenu['texte'] = trim(recuperer_fond(
"notifications/$quoi",
$contexte
));
}
// On ne continue que si on a bien un texte de base
if ($contenu['texte']){
// Existe-t-il une version HTML ? Sinon le squelette
if (!$contenu['html'] and find_in_path("notifications/${quoi}_html.html")){
$contenu['html'] = trim(recuperer_fond(
"notifications/${quoi}_html",
$contexte
));
}
// Existe-t-il une version courte ?
if (!$contenu['court']){
// Sinon le squelette
if (find_in_path("notifications/${quoi}_court.html")){
$contenu['court'] = trim(recuperer_fond(
"notifications/${quoi}_court",
$contexte
));
}
// Sinon on la construit à partir de la première ligne
else{
include_spip('inc/texte');
// Nettoyer un peu les retours chariots
$contenu['court'] = str_replace("\r\n", "\r", $contenu['texte']);
$contenu['court'] = str_replace("\r", "\n", $contenu['court']);
// Découper
$contenu['court'] = explode("\n",trim($contenu['court']));
// Extraire la premiere ligne
$contenu['court'] = array_shift($contenu['court']);
// La couper si besoin
$contenu['court'] = couper($contenu['court'], 130);
}
}
// Maintenant qu'on a tout on appelle le mode d'envoi
return $mode_envoyer($contact, $contenu);
}
}
return false;
}
function notifavancees_affiche_droite($flux){
if (in_array($flux['args']['exec'], array('auteur_infos', 'infos_perso'))){
$boite = recuperer_fond(
'prive/boite/notifications_auteur',
array(
'id_auteur' => $flux['args']['id_auteur']
)
);
$flux['data'] .= $boite;
}
return $flux;
}
?>

46
notifications/modes/email.php

@ -0,0 +1,46 @@
<?php
// Sécurité
if (!defined('_ECRIRE_INC_VERSION')) return;
// Envoi le contenu par email
function notifications_modes_email_envoyer_dist($contact, $contenu){
// S'il y a le plugin Facteur, on peut faire un truc plus propre
if (defined('_DIR_PLUGIN_FACTEUR')){
$corps = array(
'texte' => $contenu['texte'],
);
// Si on a une version HTML
if ($contenu['html'])
$corps['html'] = $contenu['html'];
}
// Sinon c'est juste le texte
else{
$corps = $contenu['texte'];
}
$envoyer_mail = charger_fonction('envoyer_mail', 'inc/');
return $envoyer_mail($contact, $contenu['court'], $corps);
}
// Renvoie une adresse e-mail ou rien
function notifications_modes_email_contact_dist($destinataire){
include_spip('inc/filtres');
// Si c'est déjà un mail
if (email_valide($destinataire))
return $destinataire;
// Si c'est un id_auteur
elseif (
intval($destinataire) == $destinataire
and $destinataire > 0
and $email = sql_getfetsel('email', 'spip_auteurs', 'id_auteur = '.$destinataire)
){
return $email;
}
// Sinon rien
else
return null;
}
?>

3
notifications/modes/email.yaml

@ -0,0 +1,3 @@
titre: '<:notifavancees:modes_email_titre:>'
description: '<:notifavancees:modes_email_description:>'
choix: '<:notifavancees:modes_email_choix:>'

42
plugin.xml

@ -0,0 +1,42 @@
<plugin>
<nom>Notifications avancées</nom>
<auteur>[Les Développements Durables->http://www.ldd.fr]</auteur>
<licence>GPL v3</licence>
<version>0.2.0</version>
<version_base>0.1.0</version_base>
<etat>test</etat>
<description>Permet une gestion fine des notifications à envoyer avec possibilité de s'inscrire/se désinscrire et de choisir les modes d'envois.</description>
<icon>images/notifications-128.png</icon>
<categorie>outil</categorie>
<prefix>notifavancees</prefix>
<install>base/notifavancees_installation.php</install>
<pipeline>
<nom>declarer_tables_principales</nom>
<inclure>base/notifavancees_tables.php</inclure>
</pipeline>
<pipeline>
<nom>declarer_tables_interfaces</nom>
<inclure>base/notifavancees_tables.php</inclure>
</pipeline>
<pipeline>
<nom>notifications</nom>
<inclure>notifavancees_pipelines.php</inclure>
</pipeline>
<pipeline>
<nom>affiche_droite</nom>
<inclure>notifavancees_pipelines.php</inclure>
</pipeline>
<pipeline>
<nom>autoriser</nom>
<inclure>inc/notifications_autoriser.php</inclure>
</pipeline>
<necessite id="SPIP" version="[2.1.0;2.1.99]" />
<necessite id="spip_bonux" version="[2.2.10;]" />
<necessite id="queue" version="[0.6.2;]" />
<necessite id="saisies" version="[1.8.5;]" />
<necessite id="yaml" version="[1.4.1;]" />
</plugin>

28
prive/boite/notifications_auteur.html

@ -0,0 +1,28 @@
#SET{abonnements,0}
#SET{refus,0}
<BOUCLE_notifications(NOTIFICATIONS_ABONNEMENTS){id_auteur}>
[(#MODES|oui)
[(#SET{abonnements,[(#GET{abonnements}|plus{1})]})]
]
[(#MODES|non)
[(#SET{refus,[(#GET{refus}|plus{1})]})]
]
</BOUCLE_notifications>
<div style="" class="cadre cadre-r">
[<img width="24" height="24" class="cadre-icone" alt="" src="(#CHEMIN{images/notifications-24.png})">]
<h3 class="titrem">[(#SESSION{id_auteur}|=={#ENV{id_auteur}}|?{<:notifavancees:infos_mes_notifications:>,<:notifavancees:infos_notifications:>})]</h3>
<div class="cadre_padding">
[(#GET{abonnements}|oui)
<p><:notifavancees:infos_nb_abonnements{nb=#GET{abonnements}}:></p>
]
[(#GET{refus}|oui)
<p><:notifavancees:infos_nb_refus{nb=#GET{refus}}:></p>
]
[(#AUTORISER{configurer_notifications, auteur, #ENV{id_auteur}}|oui)
<p class="boutons">
<a href="[(#URL_ECRIRE{notifications_auteur}|parametre_url{id_auteur,#ENV{id_auteur}})]"><:notifavancees:config_modifier_notifications_auteur:></a>
</p>
]
</div>
</div>
</B_notifications>

21
prive/exec/notifications_auteur.html

@ -0,0 +1,21 @@
[(#AUTORISER{configurer_notifications, auteur, #ENV{id_auteur}}|oui)
<!--#hierarchie-->
<ul id="chemin">
<li>
<a href="#URL_ECRIRE{auteurs}"><:icone_auteurs:></a>
</li>
<li>
<em> > </em>
<a href="[(#URL_ECRIRE{auteur_infos}|parametre_url{id_auteur, #ENV{id_auteur}})]">#INFO_TITRE{auteur,#ENV{id_auteur}}</a>
</li>
<li>
<em> > </em>
[<span class="on">(#SESSION{id_auteur}|=={#ENV{id_auteur}}|?{<:notifavancees:infos_mes_notifications:>,<:notifavancees:infos_notifications:>})</span>]
</li>
</ul>
<!--/#hierarchie-->
<h1>[(#SESSION{id_auteur}|=={#ENV{id_auteur}}|?{<:notifavancees:infos_mes_notifications:>,<:notifavancees:infos_notifications:>})]</h1>
#FORMULAIRE_NOTIFICATIONS_AUTEUR{#ENV{id_auteur}}
]
Loading…
Cancel
Save