Browse Source

Normalement fin de la gestion des inscriptions + de la récup des infos d'un flux précis quand on décide qu'il peut fournir des pushs automatiquement. Ce qui permet de récupérer le titre général du flux et les pushs qu'il contient à un instant T. Reste à scanner régulièrement les flux automatiques pour générer des vrais pushs à envoyer suivant ce qu'on trouve dedans (et ça en détectant ce qui est déjà inséré à envoyer, pas générer deux fois les mêmes).

pull/1/head
RastaPopoulos 3 months ago
parent
commit
4038c5b1e3
  1. 22
      action/api_pushsubscription.php
  2. 8
      base/pushsubscribers.php
  3. 71
      inc/pushsubscribers.php
  4. 23
      javascript/pushsubscribers.utils.js
  5. 6
      modeles/push_inscription.html
  6. 1
      paquet.xml
  7. 42
      pushs/articles.php
  8. 45
      pushs/pushlist.php
  9. 29
      pushsubscribers_pipelines.php

22
action/api_pushsubscription.php

@ -9,6 +9,7 @@ include_spip('action/editer_objet');
include_spip('inc/autoriser');
include_spip('inc/config');
include_spip('inc/session');
include_spip('inc/pushsubscribers');
function action_api_pushsubscription_dist() {
// On récupère les infos
@ -17,6 +18,8 @@ function action_api_pushsubscription_dist() {
$keys = _request('keys');
$auth = $keys['auth'];
$p256dh = $keys['p256dh'];
$pushlist = html_entity_decode(_request('pushlist'));
$pushlist_checked = ($pushlist and _request('pushlist_checked'));
$vapid_public = lire_config('pushsubscribers/vapid_public');
if (
@ -48,6 +51,11 @@ function action_api_pushsubscription_dist() {
autoriser_exception('instituer', 'pushsubscriber', $id_pushsubscriber, true);
$reponse = objet_modifier('pushsubscriber', $id_pushsubscriber, $maj);
autoriser_exception('instituer', 'pushsubscriber', $id_pushsubscriber, false);
// Ensuite on met à jour pour la liste précise (ça crée la liste à la volée si elle n'existait pas)
if ($pushlist) {
pushsubscribers_switch_pushlist($id_pushsubscriber, $pushlist, $pushlist_checked);
}
}
// Si c'est pour supprimer
elseif ($action == 'delete' and $id_pushsubscriber) {
@ -62,7 +70,21 @@ function action_api_pushsubscription_dist() {
}
// Si c'est pour chercher la liste des inscriptions
elseif ($action == 'list' and $id_pushsubscriber) {
$liste = array();
// On cherche la liste complète de ses inscriptions
if ($pushsubscriptions = sql_allfetsel('*', 'spip_pushsubscriptions', 'id_pushsubscriber = '.$id_pushsubscriber)) {
foreach ($pushsubscriptions as $pushsubscription) {
// Si on trouve bien la liste avec son contexte
if ($contexte = sql_getfetsel('contexte', 'spip_pushlists', 'id_pushlist = '.intval($pushsubscription['id_pushlist']))) {
$liste[$contexte] = $pushsubscription;
}
}
}
// On renvoie la liste en JSON
header('Content-Type: application/json');
echo json_encode($liste);
}
return array($id_pushsubscriber, $reponse);

8
base/pushsubscribers.php

@ -94,7 +94,7 @@ function pushsubscribers_declarer_tables_objets_sql($tables) {
'titre' => 'text NOT NULL DEFAULT ""',
'auto' => 'tinyint not null default "1"', // par défaut c'est auto, sauf si on édite par le form
'type' => 'varchar(25) NOT NULL DEFAULT ""', // "feed" pour dire que c'est un flux à lire régulièrement
'contexte' => 'varchar(255) NOT NULL DEFAULT ""',
'contexte' => 'varchar(255) NOT NULL DEFAULT ""', // le vrai identifiant de la liste : un mot et une query string éventuelle (articles?id_rubrique=123&id_mot=456)
'maj' => 'TIMESTAMP NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'
),
'key' => array(
@ -171,18 +171,18 @@ function pushsubscribers_declarer_tables_auxiliaires($tables) {
// Les inscriptions c'est-à-dire ce que chaque inscrit a vraiment accepté de recevoir comme liste
$tables['spip_pushsubscriptions'] = array(
'field' => array(
'id_pushsubscription' => 'bigint(21) default"0" NOT NULL',
'id_pushsubscriber' => 'bigint(21) default "0" NOT NULL',
'id_pushlist' => 'bigint(21) default "0" NOT NULL',
'maj' => 'TIMESTAMP NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
),
'key' => array(
"PRIMARY KEY" => "id_pushsubscription",
"PRIMARY KEY" => "id_pushsubscriber,id_pushlist",
"KEY id_pushsubscriber" => "id_pushsubscriber",
"KEY id_pushlist" => "id_pushlist",
)
);
// À qui envoyer tel notif précise
// À qui envoyer telle notif précise
$tables['spip_pushs_destinataires'] = array(
'field' => array(
"id_push" => "bigint(21) DEFAULT '0' NOT NULL",

71
inc/pushsubscribers.php

@ -30,6 +30,73 @@ function pushsubscribers_desinscrire($id_ou_endpoint) {
}
}
/**
* Inscrire ou désinscrire à une liste précise, et la créer dans la base si non existante
*
* @param $id_ou_endpoint
* ID SQL ou endpoint d'un pushsubscribers
* @param string $contexte
* Chaine identifiant un contexte de liste, peut contenir une query string
* @param bool $inscrire
* Booléen indiquant si on doit inscrire ou sinon désinscrire à cette liste
*/
function pushsubscribers_switch_pushlist($id_ou_endpoint, $contexte, $inscrire=true) {
include_spip('action/editer_objet');
// On vérifie que le pushsubscriber existe bien
if (is_string($id_ou_endpoint)) {
$id_pushsubscriber = sql_getfetsel('id_pushsubscriber', 'spip_pushsubscribers', 'endpoint = '.sql_quote($id_ou_endpoint));
}
else {
$id_pushsubscriber = sql_getfetsel('id_pushsubscriber', 'spip_pushsubscribers', 'id_pushsubscriber = '.intval($id_ou_endpoint));
}
// Seulement si on a bien trouvé un inscrit
if ($id_pushsubscriber = intval($id_pushsubscriber)) {
// Cette liste existe-t-elle déjà ?
if (!$id_pushlist = sql_getfetsel('id_pushlist', 'spip_pushlists', 'contexte = '.sql_quote($contexte))) {
// On crée la liste
$id_pushlist = objet_inserer('pushlist');
// Et en modifiant son contexte, c'est censé pré-remplir les autres bonnes infos
objet_modifier('pushlist', $id_pushlist, array('contexte' => $contexte));
}
// Si on a donc bien une liste
if ($id_pushlist) {
// Si on veut inscrire et qu'il n'y a pas déjà l'inscription
if (
$inscrire
and !$pushsubscription = sql_fetsel(
'*',
'spip_pushsubscriptions',
array(
'id_pushsubscriber = ' . $id_pushsubscriber,
'id_pushlist = ' . $id_pushlist,
)
)
) {
$id_pushsubscription = sql_insertq(
'spip_pushsubscriptions',
array(
'id_pushsubscriber' => $id_pushsubscriber,
'id_pushlist' => $id_pushlist,
)
);
}
// Sinon si on veut désinscrire
elseif (!$inscrire) {
sql_delete(
'spip_pushsubscriptions',
array(
'id_pushsubscriber = ' . $id_pushsubscriber,
'id_pushlist = ' . $id_pushlist,
)
);
}
}
}
}
/**
* Lance le chargeur PSR pour les libs embarquées
**/
@ -59,9 +126,9 @@ function pushsubscribers_preparer_payload($id_ou_push) {
// TODO
$payload = array(
'title' => $push['titre'],
'message' => 'Contenu texte de la notif',
'message' => $push['texte'],
'icon' => 'URL image',
'data' => array('url' => 'URL de lien quand on clique',),
'data' => array('url' => 'http://rastapopoulos.artizanal.info',),
'actions' => array(
array('action' => 'close', 'title' => 'Fermer'),
)

23
javascript/pushsubscribers.utils.js

@ -50,17 +50,20 @@ var pushsubscribers = {
data: subscription_json,
type: 'GET',
async: false,
dateType: 'json', // on attend du json pour cette action là
success: function (reponse) {
console.log(reponse);
if (reponse) {
pushsubscriptions = reponse;
}
},
});
}
// Qu'elle ait déjà une inscription ou pas
// On cherche tous les champs pour s'inscrire pas encore activés
$('[data-pushsubscription]:disabled').each(function() {
$('[data-pushlist]:disabled').each(function() {
var me = $(this);
var contexte = me.data('pushsubscription');
var contexte = me.data('pushlist');
// On va chercher si la personne a déjà accepté ce contexte
// = si on trouve ce contexte dans les inscriptions
@ -85,6 +88,10 @@ var pushsubscribers = {
// Inscrire ou désinscrire à une liste précise lors du switch coché/décoché
switch_inscription: function() {
var champ = $(this);
var pushlist = champ.data('pushlist');
var checked = champ.is(':checked') ? 1 : 0;
// À chaque clic, on va retester si on trouve une inscription
navigator.serviceWorker.ready.then(function (registration) {
var applicationServerKey = pushsubscribers.urlBase64ToUint8Array(jQuery.spip.pushsubscribers.vapid_public);
@ -106,7 +113,11 @@ var pushsubscribers = {
.then(function (subscription) {
var subscription_json = subscription.toJSON();
var url_api = pushsubscribers.get_url_api();
console.debug("subscription_json", subscription_json);
//~ console.debug("subscription_json", subscription_json);
// En plus de créer ou mettre à jour l'inscription général, il faut inscrire ou désinscrire à la liste précise
subscription_json.pushlist = pushlist;
subscription_json.pushlist_checked = checked;
$.post(
url_api + 'create',
@ -125,7 +136,7 @@ var pushsubscribers = {
// Quand le DOM est prêt
$(function() {
pushsubscribers.activer_champs_inscription();
// Et dès qu'il y a un chargement ajax
onAjaxLoad(pushsubscribers.activer_champs_inscription);
// Et dès qu'il y a un chargement ajax (pas pour l'instant car boucle infinie)
//~ onAjaxLoad(pushsubscribers.activer_champs_inscription);
});
}(jQuery));

6
modeles/push_inscription.html

@ -13,15 +13,15 @@ Modèle pour permettre à n'importe quelle personne de gérer l'inscription à d
@param label
Label affiché à l'utilisateurice
@param url
Une query string, représentant un identifiant de contexte + des paramètres éventuels à lui passer. Si c'est une liste automatique, ce contexte sera forcément implémenté dans le path `pushlists/` (par ex `pushlists/articles.html`).
@param pushlist
Une query string, représentant un identifiant de contexte + des paramètres éventuels à lui passer. Si c'est une liste automatique, ce contexte sera forcément implémenté dans le path `pushs/` (par ex `pushs/articles.html`).
]
#SET{id, #ENV{url}|md5}
<div class="formulaire_spip">
<div class="pushsubscription choix">
<input type="checkbox" id="#GET{id}" name="#GET{id}" disabled="disabled" data-pushsubscription="#ENV{url}" value="" />
<input type="checkbox" id="#GET{id}" name="#GET{id}" autocomplete="off" disabled="disabled" data-pushlist="[(#ENV{pushlist}|html_entity_decode)]" value="" />
<label for="#GET{id}">#ENV{label, Recevoir des notifications}</label>
</div>
</div>

1
paquet.xml

@ -23,6 +23,7 @@
<pipeline nom="declarer_tables_objets_sql" inclure="base/pushsubscribers.php" />
<pipeline nom="declarer_tables_auxiliaires" inclure="base/pushsubscribers.php" />
<pipeline nom="declarer_tables_interfaces" inclure="base/pushsubscribers.php" />
<pipeline nom="pre_edition" inclure="pushsubscribers_pipelines.php" />
<pipeline nom="optimiser_base_disparus" inclure="pushsubscribers_pipelines.php" />
<pipeline nom="insert_head" inclure="pushsubscribers_pipelines.php" />
<pipeline nom="serviceworker_install_js" inclure="pushsubscribers_pipelines.php" />

42
pushs/articles.php

@ -0,0 +1,42 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function pushs_articles_dist($contexte=array()) {
include_spip('base/abstract_sql');
include_spip('inc/filtres');
$flux = array(
'titre' => _T('info_articles'),
'pushs' => array(),
);
// Si jamais on veut filtrer
$where = array(
'statut = "publie"',
);
if (isset($contexte['id_rubrique'])) {
$id_rubrique = intval($contexte['id_rubrique']);
$flux['titre'] .= ' - ' . _T('rubrique') . ' ' . generer_info_entite($id_rubrique, 'rubrique', 'titre');
$where[] = 'id_rubrique = '.$id_rubrique;
}
if ($articles = sql_allfetsel('id_article, titre, texte, date', 'spip_articles', $where, '', 'date desc', '0,20')) {
foreach ($articles as $article) {
$push = array(
'titre' => $article['titre'],
'texte' => $article['texte'],
'url' => url_absolue(generer_url_entite($article['id_article'], 'article')),
'date' => $article['date'],
);
$flux['pushs'][] = $push;
}
}
return $flux;
}

45
pushs/pushlist.php

@ -0,0 +1,45 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Cherche si un contexte donné à un flux prévu et renvoie son contenu
*
* @param string $contexte
* Un mot et une query string éventuelle (articles?id_rubrique=123&id_mot=456)
* @return array
* Tableau PHP représentant le flux
*/
function pushs_pushlist_dist($contexte) {
// Par défaut, pas de flux du tout
$flux = $chemin = null;
$parse = parse_url($contexte);
if (isset($parse['path'])) {
$chemin = $parse['path'];
}
if (isset($parse['query'])) {
parse_str($parse['query'], $contexte);
}
else {
$contexte = array();
}
// S'il y a une fonction PHP pour ce flux, c'est prioritaire
if ($chemin and $fonction_contexte = charger_fonction($chemin, 'pushs', true)) {
$flux = $fonction_contexte($contexte);
}
// Sinon s'il y a un squelette et que ça retourne un JSON
elseif (
find_in_path("pushs/$chemin")
and $json = recuperer_fond("pushs/$chemin", $contexte)
and $json = json_decode($json, true)
and is_array($json)
) {
$flux = $json;
}
return $flux;
}

29
pushsubscribers_pipelines.php

@ -13,6 +13,35 @@ if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/*
* Des modifs supplémentaires après édition
*/
function pushsubscribers_pre_edition($flux) {
// Si on modifie une liste
if (isset($flux['args']['type']) and $flux['args']['type'] == 'pushlist') {
$id_pushlist = intval($flux['args']['id_objet']);
// L'état actuel
$pushlist = sql_fetsel('*', 'spip_pushlists', 'id_pushlist = ' . $id_pushlist);
// Si le contexte a été modifié
if (isset($flux['data']['contexte']) and $contexte = $flux['data']['contexte']) {
// On cherche si ce nouveau contexte a un flux prévu
$fonction_pushlist = charger_fonction('pushlist', 'pushs');
if ($feed = $fonction_pushlist($contexte)) {
// Dans ce cas c'est forcément un type=feed
$flux['data']['type'] = 'feed';
}
// S'il n'y avait pas de titre avant, on le remplit avec le titre du flux ou le contexte
if (!$pushlist['titre']) {
$flux['data']['titre'] = isset($feed['titre']) ? $feed['titre'] : $contexte;
}
}
}
return $flux;
}
/**
* Optimiser la base de données
*

Loading…
Cancel
Save