diff --git a/ezcache/territoires_stats.php b/ezcache/territoires_stats.php new file mode 100644 index 0000000000000000000000000000000000000000..34dddeea2806de8e81d320470863bf8a37a3c73f --- /dev/null +++ b/ezcache/territoires_stats.php @@ -0,0 +1,54 @@ +<?php +/** + * Ce fichier contient les fonctions de service nécessitées par le plugin Cache Factory. + */ +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} + +/** + * Renvoie la configuration spécifique des caches gérés par REST Factory si les fonctions de collection des données + * sont directement codés en PHP. + * + * Dans le cas où les données JSON sont créées via des squelettes SPIP, le cache est déjà géré par SPIP. + * + * @param string $plugin Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou + * un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe. + * + * @return array<string, mixed> Tableau de la configuration brute du plugin Taxonomie. + */ +function territoires_stats_cache_configurer(string $plugin) : array { + // Initialisation du tableau de configuration avec les valeurs par défaut du plugin Cache. + $configuration = [ + 'config' => [ + 'racine' => '_DIR_ETC', + 'sous_dossier' => true, + 'nom_prefixe' => 'config', + 'nom_obligatoire' => [], + 'nom_facultatif' => [], + 'extension' => '.yaml', + 'securisation' => false, + 'serialisation' => false, + 'decodage' => true, + 'separateur' => '', + 'conservation' => 0, + 'administration' => false + ], + 'source' => [ + 'racine' => '_DIR_ETC', + 'sous_dossier' => true, + 'nom_prefixe' => 'source_1', + 'nom_obligatoire' => [], + 'nom_facultatif' => [], + 'extension' => '.json', + 'securisation' => false, + 'serialisation' => false, + 'decodage' => true, + 'separateur' => '-', + 'conservation' => 0, + 'administration' => false + ], + ]; + + return $configuration; +} diff --git a/ezmashup/config.template.yaml b/ezmashup/config.template.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5cffe0b0089698776aaab39abd9de8879a9e8489 --- /dev/null +++ b/ezmashup/config.template.yaml @@ -0,0 +1,81 @@ +# Ce template permet au plugin d'initialiser les YAML utilisateur. +# Il contient tous les champs possibles. +# --------------------------------------------------------------- + +# L'identifiant du feed est le nom du dossier contenant le fichier YAML +title: '' +description: '' + +# Catégorisation du feed +# -- Pour le plugin, la catégorie des feeds est toujours la même, `territory_data` +category: 'territory_data' +# -- Le plugin utilise les tags pour définir le type de territoire, le pays et le code territoire utilisé dans le jeu de données +tags: + type_id: '' + type: '' + pays: '' + +# Configuration du stockage de destination : c'est la table `spip_territoires_extras` +target: + format: 'sql_table' + id: 'territoires_extras' + # Options de paramétrage de la cible : + # - le plugin définit une limite à 5000 enregistrements par insertion (protection pour timeout) + options: + max_chunk: 5000 + +# Configuration du mapping et du processus de mashup +mapping: + # Données de base : ces données sont issues du jeu de données + # - `code_feed` contient le code utilisé par jeu si celui-ci n'est pas le code primaire du territoire. Sinon ce champ + # est absent et on remplir directement le champ `iso_territoire` + basic_fields: + iso_territoire: 'iso_feed' + code_feed: '' + valeur: '' + + # Liste des champs de base étendus : ces données sont calculées à partir des champs de base et inclus dans le stockage + # - aucun nécessaire + + # Données statiques : à ajouter à la target mais ne provient pas d'un dataset source + # Le plugin définit les champs qui seront inclus dans la table spip hors le code de territoire et la valeur : + # - l'identifiant de la données (extra), le type d'extra à savoir toujours `stat` pour le plugin, l'id du feed, + # le type de territoire et le pays (proviennent des tags) + static_fields: + extra: '' + type_extra: 'stat' + feed_id: '/feed_id' + type: '#type' + iso_pays: '#pays' + + # Liste des champs de la target qui ne seront pas retenus pour le stockage + # - Si `code_feed` est utilisé, sinon vide + unused_fields: ['code_feed'] + +# Le plugin ne peut pas utiliser d'include (aucune fonction particulière par feed n'est possible) + +# Description des datasets source primaires +# - Le plugin ne supporte qu'un seul dataset primaire et aucun addon. +sources_basic: + source_1: + # Complément pour la source + source: + # Prend les valeurs file ou api + type: '' + # Définit le format du fichier (json, xml ou csv) ou du contenu retourné par l'api : json uniquement. + format: '' + # Nom du fichier avec extension ou URL HTTP + uri: '' + last_update: '' + version: '' + license: '' + # Informations optionnelles permettant de décoder le contenu de la source + decoding: + # - root_node : sommet de l'arborescence à extraire (sous la forme a/b/c) si la source n'est pas un fichier CSV (vide par défaut) + root_node: '' + # - delimiter : si la source est un fichier CSV (virgule par défaut) + delimiter: '' + # Description du provider pour les crédits + provider: + name: '' + url: '' diff --git a/ezmashup/territoires_stats.php b/ezmashup/territoires_stats.php index 3d014b9677fc0e97a1ba3db768d25498a190c733..c2260a4e6c3cb82d2e2cd751f1bccebcf562b40a 100644 --- a/ezmashup/territoires_stats.php +++ b/ezmashup/territoires_stats.php @@ -17,12 +17,10 @@ if (!defined('_ECRIRE_INC_VERSION')) { * * @pipeline_appel feed_lister_categories * - * @param string $plugin Préfixe du plugin utilisateur. - * * @return array Liste des catégories et de leur description au format [id] = tableau de description avec le nom (label), * la description et l'icone. */ -function territoires_stats_feed_lister_categories(string $plugin) : array { +function territoires_stats_feed_lister_categories() : array { // Initialisation des catégories par défaut return [ 'territory_data' => [ @@ -36,11 +34,9 @@ function territoires_stats_feed_lister_categories(string $plugin) : array { /** * Renvoie la catégorie par défaut dans la liste des catégories supportées par le plugin. * - * @param string $plugin Préfixe du plugin utilisateur. - * * @return string Identifiant de la catégorie par défaut. */ -function territoires_stats_feed_initialiser_categorie_defaut(string $plugin) : string { +function territoires_stats_feed_initialiser_categorie_defaut() : string { // Initialisation des catégories par défaut de Mashup Factory return 'territory_data'; } @@ -49,17 +45,15 @@ function territoires_stats_feed_initialiser_categorie_defaut(string $plugin) : s * Renvoie la configuration par défaut de la racine où trouver les feeds. * Cette information est utilisée a minima au chargement des feeds disponibles. * - * Le plugin crée dynamiquement les feeds. De fait, il les stocke dans le - * dossier des données permanentes inaccessibles, _DIR_ETC. Ce dossier n'étant pas accessible via le path de spip - * il est nécessaire d'indiquer la racine exacte qui fera l'objet d'un traitement particulier. - * - * @param string $plugin Préfixe du plugin utilisateur. + * Le plugin crée dynamiquement les feeds. De fait, il les stocke dans le dossier des données permanentes inaccessibles, + * _DIR_ETC. Ce dossier n'étant pas accessible via le path de spip il est nécessaire d'indiquer la racine exacte qui + * fera l'objet d'un traitement particulier. * * @return string Racine où chercher les feeds. */ -function territoires_stats_feed_initialiser_racine(string $plugin) : string { +function territoires_stats_feed_initialiser_racine() : string { // Le plugin range les feeds créés dynamiquement dans _DIR_ETC. - return _DIR_ETC . $plugin . '/'; + return _DIR_ETC; } /** @@ -67,12 +61,9 @@ function territoires_stats_feed_initialiser_racine(string $plugin) : string { * * Le plugin rajoute la consignation des données statistiques. * - * @package SPIP\MASHUP\SERVICE - * * @uses unite_peuplement_consigne_identifier() - * @uses ezmashup_chercher_service() * - * @param array $feed Configuration du feed + * @param array $feed Configuration du feed * * @return void */ @@ -109,11 +100,9 @@ function territoires_stats_feed_completer_execution(array $feed) : void { * * Le plugin Mashup Factory ne fait rien de particulier actuellement. * - * @package SPIP\MASHUP\SERVICE - * - * @uses ezmashup_chercher_service() + * @uses unite_peuplement_consigne_identifier() * - * @param array $feed Configuration du feed + * @param array $feed Configuration du feed * * @return void */ @@ -160,8 +149,8 @@ function territoires_stats_feed_completer_vidage(array $feed) : void { * Le plugin gère les cas où le code identifiant les territoires ne sont pas les codes ISO comme l'attend la * table spip_territoires_extras (par exemple, le code INSEE en France). * - * @param array $item Item d'un dataset source - * @param array $feed Configuration du feed + * @param array $item Item d'un dataset source + * @param array $feed Configuration du feed * * @return array Item mis à jour */ diff --git a/formulaires/creer_feed_territoires.php b/formulaires/creer_feed_territoires.php index 0d070b9e6c9ce352d46a487f15b117dcc753ddb8..572f3ac07647de4ee96f8fae897346f43b6e27ba 100644 --- a/formulaires/creer_feed_territoires.php +++ b/formulaires/creer_feed_territoires.php @@ -186,7 +186,7 @@ function formulaires_creer_feed_territoires_verifier_1() : array { // Extraire l'extension pour déterminer l'option de décodage à présenter [, $format] = explode('/', $_FILES[$variable_source]['type']); } - set_request('format_source', $format); + set_request('_format_source', $format); if ($format === 'csv') { set_request('_label_decodage', _T('territoires_stats:label_feed_decodage_delimiteur')); set_request('_explication_decodage', _T('territoires_stats:explication_feed_decodage_delimiteur')); @@ -197,12 +197,10 @@ function formulaires_creer_feed_territoires_verifier_1() : array { // -- Identifiant proposé pour le feed include_spip('inc/ezmashup_feed'); - $prefixe = "{$type}_{$pays}_{$extra}"; - foreach (['', '2', '3', '4', '5', '6', '7', '8', '9'] as $_suffixe) { - $id_feed = $prefixe . ($_suffixe ? '_' : '') . $_suffixe; - if (!feed_yaml_existe('territoires_stats', $id_feed)) { - break; - } + $id_feed = "{$type}_" . ($pays ? "{$pays}_" : '') . $extra; + if (feed_ressource_existe('territoires_stats', $id_feed, 'config')) { + // On rajoute un suffixe que l'utilisateur devra modifier + $id_feed .= '_xxx'; } set_request('_feed_id_defaut', strtolower($id_feed)); } @@ -253,7 +251,7 @@ function formulaires_creer_feed_territoires_verifier_2() : array { include_spip('inc/ezmashup_feed'); if (!preg_match('#^[\w]+$#i', $id_feed)) { $erreurs['feed_id'] = _T('territoires_stats:erreur_feed_id'); - } elseif (feed_yaml_existe('territoires_stats', $id_feed)) { + } elseif (feed_ressource_existe('territoires_stats', $id_feed, 'config')) { $erreurs['feed_id'] = _T('territoires_stats:erreur_feed_id_existe'); } @@ -264,13 +262,115 @@ function formulaires_creer_feed_territoires_verifier_2() : array { * Exécution du formulaire : . * * @return array Tableau retourné par le formulaire contenant toujours un message de bonne exécution ou - * d'erreur. L'indicateur editable est toujours à vrai. + * d'erreur. */ function formulaires_creer_feed_territoires_traiter() : array { // Initialisation du retour de la fonction $retour = []; - // Récupération des paramètres de base de la carte et début de consolidation des champs de l'objet carte + // Récupération des variables constitutives du YAML + // -- étape 1 + $type = _request('type'); + $pays = _request('pays_' . $type) ?? ''; + $type_source = _request('type_source'); + $source = $type_source === 'api' + ? _request('url_source') + : basename($_FILES['fichier_source']['name']); + $extra = _request('extra'); +// $titre_extra = _request('titre_extra'); + $format_source = _request('format_source'); + + // -- étape 2 + $type_code = _request('type_code'); + $decodage = trim(_request('decodage')) ?? ''; + $mapping_code = _request('mapping_code'); + $mapping_valeur = _request('mapping_valeur'); + $id_feed = _request('feed_id'); + $titre_feed = _request('titre'); + $description_feed = _request('description') ?? ''; + + // Initialisation du YAML à partir du template + include_spip('inc/yaml'); + $yaml_template = _DIR_PLUGIN_TERRITOIRES_STATS . 'ezmashup/config.template.yaml'; + $description_yaml = yaml_decode_file($yaml_template); + + // Personnalisation du YAML en fonction du contexte des saisies. + // On considère que toutes les vérifications ont été faites et que donc les variables saisies sont cohérentes + // -- identification + $description_yaml['title'] = $titre_feed; + $description_yaml['description'] = $description_feed; + // -- catégorisation : seuls les tags sont à mettre à jour + $description_yaml['tags']['type'] = $type; + $description_yaml['tags']['pays'] = $pays; + $description_yaml['tags']['type_id'] = $type_code; + // -- mapping : basic, static et unused fields + if ($type_code === 'iso_territoire') { + // Le code primaire est utilisé dans jeu de données, il n'est pas utile de passer par un code alternatif + // - le champ `code_feed` est donc inutile + $description_yaml['mapping']['basic_fields']['iso_territoire'] = $mapping_code; + unset($description_yaml['mapping']['basic_fields']['code_feed']); + unset($description_yaml['mapping']['unused_fields']); + } else { + // Le jeu de données utilise un code alternatif au code primaire + // - le champ `code_feed` est donc nécessaire temporairement + $description_yaml['mapping']['basic_fields']['code_feed'] = $mapping_code; + } + $description_yaml['mapping']['basic_fields']['valeur'] = $mapping_valeur; + $description_yaml['mapping']['static_fields']['extra'] = $extra; + // -- la source : pour l'instant les crédits ne sont pas supportés, elle porte toujours l'id `source_1` + $description_yaml['sources_basic']['source_1']['source']['type'] = $type_source; + $description_yaml['sources_basic']['source_1']['source']['format'] = $format_source; + $description_yaml['sources_basic']['source_1']['source']['uri'] = $source; + if ($format_source === 'csv') { + unset($description_yaml['sources_basic']['source_1']['decoding']['root_node']); + $description_yaml['sources_basic']['source_1']['decoding']['delimiter'] = $decodage; + } else { + unset($description_yaml['sources_basic']['source_1']['decoding']['delimiter']); + $description_yaml['sources_basic']['source_1']['decoding']['root_node'] = $decodage; + } + + // Ecriture de la source si elle est au format fichier + if ($type_source === 'file') { + // Récupération du fichier qui est stocké temporairement dans tmp/ en attendant le chargement du feed + // -- Création du répertoire d'upload + $dir = sous_repertoire(_DIR_TMP, 'territoires_stats'); + + // -- Détermination du nom du fichier temporaire de façon à ce qu'il soit unique. + $hash = md5("{$format_source}-" . $GLOBALS['visiteur_session']['id_auteur'] . time()); + $fichier = $dir . $hash . '-' . $_FILES['fichier_source']['name']; + + // -- Déplacement du fichier téléchargé dans la destination choisie. + if (move_uploaded_file($_FILES['fichier_source']['tmp_name'], $fichier)) { + // -- Lecture et suppression du fichier temporaire + include_spip('inc/flock'); + lire_fichier($fichier, $contenu_source); + @unlink($fichier); + + // Stockage de la source dans son emplacement final + if (!feed_ressource_ecrire('territoires_stats', $id_feed, 'source', $contenu_source)) { + $retour['message_erreur'] = _T('territoires_stats:erreur_recupération_source'); + } + } + else { + $retour['message_erreur'] = _T('territoires_stats:erreur_recupération_source'); + } + } + + if (empty($retour['message_erreur'])) { + // Ecriture du YAML + include_spip('inc/ezmashup_feed'); + if (feed_ressource_ecrire('territoires_stats', $id_feed, 'config', $description_yaml)) { + // Insertion du YAML en base de données + feed_charger('territoires_stats'); + } else { + $retour['message_erreur'] = _T('territoires_stats:erreur_ecriture_config'); + } + } + + // Redirection vers la page des jeux de données si tout s'est bien passé + if (empty($retour['message_erreur'])) { + $retour['redirect'] = generer_url_ecrire('peupler_statistiques'); + } return $retour; } diff --git a/formulaires/creer_feed_territoires_2.html b/formulaires/creer_feed_territoires_2.html index 0d40933b67b3cd89b4180f78af8d8d4f0d638abc..801ba1784216f2872d6bf9a0765ab360e26655c4 100644 --- a/formulaires/creer_feed_territoires_2.html +++ b/formulaires/creer_feed_territoires_2.html @@ -59,6 +59,10 @@ })] </fieldset> + [(#SAISIE{hidden, format_source, + defaut=#ENV{_format_source} + })] + <p class="boutons"> #SET{etape_precedente, #ENV{_etape}|moins{1}} <input type="submit" class="submit" name="_retour_etape_1" value="<:territoires:info_etape_precedente:>" /> diff --git a/paquet.xml b/paquet.xml index d19360523f461306119ccfebb44ffdb79144c72f..c507cea2b9a7ebdb9fc26fd1f9cfd716c4277863 100644 --- a/paquet.xml +++ b/paquet.xml @@ -19,4 +19,5 @@ <necessite nom="ezmashup" compatibilite="[1.0.2;]" /> <necessite nom="territoires" compatibilite="[1.5.6;]" /> + <necessite nom="ezcache" compatibilite="[1.3.1;[" /> </paquet>