<?php /** * Fichier gérant l'installation et désinstallation du plugin * * @package SPIP\Formidable\Installation **/ // Sécurité if (!defined('_ECRIRE_INC_VERSION')) { return; } /** * Installation/maj des tables de formidable... * * @param string $nom_meta_base_version * Nom de la meta informant de la version du schéma de données du plugin installé dans SPIP * @param string $version_cible * Version du schéma de données dans ce plugin (déclaré dans paquet.xml) * @return void */ function formidable_upgrade($nom_meta_base_version, $version_cible) { // Création des tables include_spip('base/create'); include_spip('base/abstract_sql'); include_spip('inc/formidable_migrer_depuis_ft'); $maj = []; $maj['create'] = [ ['maj_tables',[ 'spip_formulaires', 'spip_formulaires_reponses', 'spip_formulaires_reponses_champs', 'spip_formulaires_liens']], ['formidable_importer_forms'], ['formidable_importer_forms_donnees'], ['formidable_associer_forms'], ['formidable_creer_secret'] ]; // Ajout du choix de ce qu'on affiche à la fin des traitements $maj['0.4.0'] = [['maj_tables',['spip_formulaires']]]; // Ajout d'une URL de redirection $maj['0.5.0'] = [['maj_tables',['spip_formulaires']]]; // Modif du type du message de retour pour pouvoir mettre plus de chose $maj['0.5.1'] = [['sql_alter','TABLE spip_formulaires CHANGE message_retour message_retour text NOT NULL default ""']]; // Passer le champ saisies en longtext pour permettre d'y stocker des formulaires longs $maj['0.5.2'] = [['sql_alter','TABLE spip_formulaires CHANGE saisies saisies longtext NOT NULL default ""']]; // Ajouter un champ date de création $maj['0.5.3'] = [['sql_alter','TABLE spip_formulaires ADD date_crea datetime NOT NULL DEFAULT "0000-00-00 00:00:00"']]; // Renommer la date de création (pas d'abbréviations dans les noms) $maj['0.5.5'] = [['sql_alter','TABLE spip_formulaires CHANGE date_crea date_creation datetime NOT NULL DEFAULT "0000-00-00 00:00:00"']]; // statut publie sur les formulaires sans statut $maj['0.5.6'] = [ ['sql_updateq', 'spip_formulaires', ['statut' => 'publie'], 'statut=' . sql_quote('')], ]; $maj['0.6.0'] = [ ['sql_alter','TABLE spip_formulaires_reponses_champs RENAME TO spip_formulaires_reponses_champs_bad'], ['maj_tables',['spip_formulaires_reponses_champs']], ['formidable_transferer_reponses_champs'], ['sql_drop_table','spip_formulaires_reponses_champs_bad'], ]; $maj['0.6.1'] = [ ['formidable_unifier_reponses_champs'], ]; $maj['0.6.3'] = [ ['sql_alter','TABLE spip_formulaires_reponses_champs ADD UNIQUE reponse (id_formulaires_reponse,nom)'], ]; $maj['0.6.4'] = [ // champ resume_reponse ['maj_tables',['spip_formulaires']], ]; // Pouvoir rendre un champ unique $maj['0.6.5'] = [ // champ resume_reponse ['maj_tables',['spip_formulaires']], ]; $maj['0.6.6'] = [ ['sql_updateq', 'spip_formulaires_reponses', ['statut' => 'refuse'], 'statut=' . sql_quote('poubelle')], ]; // Ajouter un champ "css" sur les formulaires $maj['0.7.0'] = [ ['maj_tables', ['spip_formulaires']], ]; // Migrer afficher_si_remplissage vers la checkbox $maj['0.8.0'] = [ ['formidable_migrer_formulaires_afficher_si_remplissage'] ]; $maj['0.9.0'] = [ ['formidable_migrer_resume_reponse'] ]; $maj['0.10.0'] = [ ['formidable_migrer_reglage_champ_unique'] ]; $maj['0.11.0'] = [ ['formidable_migrer_anonymisation'] ]; $maj['0.12.0'] = [ ['formidable_migrer_config'] ]; $maj['0.15.0'] = [ ['formidable_effacer_traitement_enregistrer_sans_option'] ]; $maj['0.17.1'] = [ ['sql_alter','TABLE spip_formulaires_reponses CHANGE variable_php variable_php VARCHAR(255) NOT NULL default ""'] ]; $maj['0.20.0'] = [ ['sql_alter','TABLE spip_formulaires_reponses ADD column `date_envoi` datetime NOT NULL default "0000-00-00 00:00:00" AFTER `date`'], ['sql_update', 'spip_formulaires_reponses', ['date_envoi' => 'date']], ]; $maj['0.23.0'] = [ ['formidable_saisies_identifier'] ]; // Ajouter un champ "vu" pour les liaisons $maj['1.0.0'] = [ ['maj_tables', ['spip_formulaires_liens']], ['formidable_verifier_liens_vu'], ]; // Ajouter un champ afficher_message_ok_traitements pour les formulaires $maj['1.3.0'] = [ ['maj_tables', ['spip_formulaires']], ]; // Et le supprimer après car on a trouvé mieux. Cf discussion https://git.spip.net/spip-contrib-extensions/formidable/issues/58 if (lire_config($nom_meta_base_version) == '1.3.0') { $maj['1.4.0'] = [ ['sql_alter', 'TABLE spip_formulaires DROP afficher_message_ok_traitements' ] ]; } $maj['1.4.2'] = [ ['formidable_creer_secret'], ]; include_spip('base/upgrade'); maj_plugin($nom_meta_base_version, $version_cible, $maj); } function formidable_unifier_reponses_champs() { $rows = sql_allfetsel( 'DISTINCT id_formulaires_reponses_champ,id_formulaires_reponse,nom,count(id_formulaires_reponse) AS N', 'spip_formulaires_reponses_champs', 'nom LIKE ' . sql_quote('multiple%') . ' OR nom LIKE ' . sql_quote('mot%'), 'concat( id_formulaires_reponse, nom )', 'id_formulaires_reponse', '0,100', 'N>1' ); do { foreach ($rows as $row) { #var_dump($row); // pour chaque reponse on recupere tous les champs $reponse = sql_allfetsel( '*', 'spip_formulaires_reponses_champs', 'id_formulaires_reponse=' . intval($row['id_formulaires_reponse']) ); spip_log('id_formulaires_reponse ' . $row['id_formulaires_reponse'], 'formidable_unifier_reponses_champs' . _LOG_INFO_IMPORTANTE); // on les reinsere un par un dans la nouvelle table propre $data = []; foreach ($reponse as $champ) { $data[$champ['nom']][] = $champ; } foreach ($data as $nom => $champs) { if (count($champs) > 1) { #var_dump($champs); $keep = $champs[0]['id_formulaires_reponses_champ']; $delete = []; $valeurs = []; foreach ($champs as $champ) { $valeurs[] = $champ['valeur']; if ($champ['id_formulaires_reponses_champ'] !== $keep) { $delete[] = $champ['id_formulaires_reponses_champ']; } } $valeurs = serialize($valeurs); #var_dump($valeurs); #var_dump($keep); #var_dump($delete); sql_updateq('spip_formulaires_reponses_champs', ['valeur' => $valeurs], 'id_formulaires_reponses_champ=' . intval($keep)); sql_delete('spip_formulaires_reponses_champs', sql_in('id_formulaires_reponses_champ', $delete)); //die(); } } #var_dump($data); //die('nothing?'); if (time() > _TIME_OUT) { return; } } if (time() > _TIME_OUT) { return; } } while ($rows = sql_allfetsel('DISTINCT id_formulaires_reponses_champ,id_formulaires_reponse,nom,count( id_formulaires_reponse ) AS N', 'spip_formulaires_reponses_champs', 'nom LIKE ' . sql_quote('multiple%') . ' OR nom LIKE ' . sql_quote('mot%'), 'concat( id_formulaires_reponse, nom )', 'id_formulaires_reponse', '0,100', 'N>1')); //die('fini?'); } function formidable_transferer_reponses_champs() { $rows = sql_allfetsel('DISTINCT id_formulaires_reponse', 'spip_formulaires_reponses_champs_bad', '', 'id_formulaires_reponse', '', '0,100'); do { foreach ($rows as $row) { // pour chaque reponse on recupere tous les champs $reponse = sql_allfetsel('*', 'spip_formulaires_reponses_champs_bad', 'id_formulaires_reponse=' . intval($row['id_formulaires_reponse'])); // on les reinsere un par un dans la nouvelle table propre foreach ($reponse as $champ) { sql_insertq('spip_formulaires_reponses_champs', $champ); } // et on les vire de la mauvaise sql_delete('spip_formulaires_reponses_champs_bad', 'id_formulaires_reponse=' . intval($row['id_formulaires_reponse'])); if (time() > _TIME_OUT) { return; } } if (time() > _TIME_OUT) { return; } } while ($rows = sql_allfetsel('DISTINCT id_formulaires_reponse', 'spip_formulaires_reponses_champs_bad', '', 'id_formulaires_reponse', '', '0,100')); } /** * Déplace les réglages sur les tests d'unicité depuis des colonnes vers des sous options du traitement "enregistrer" * * * @return void */ function formidable_migrer_reglage_champ_unique() { include_spip('inc/sql'); $res = sql_select('id_formulaire,unicite,message_erreur_unicite,traitements', 'spip_formulaires'); while ($row = sql_fetch($res)) { $traitements = unserialize($row['traitements']); if ($row['unicite'] != '') { if (!isset($traitements['enregistrement'])) { $traitements['enregistrement'] = []; } $traitements['enregistrement']['unicite'] = $row['unicite']; } if ($row['message_erreur_unicite'] != '') { if (!isset($traitements['enregistrement'])) { $traitements['enregistrement'] = []; } $traitements['enregistrement']['message_erreur_unicite'] = $row['message_erreur_unicite']; } $traitements = serialize($traitements); sql_updateq('spip_formulaires', ['traitements' => $traitements], 'id_formulaire=' . $row['id_formulaire']); } sql_alter('TABLE spip_formulaires DROP message_erreur_unicite, DROP unicite'); } /** * Cherche tous les formulaires et migre les conditions afficher_si_remplissage * vers le champ afficher_si + afficher_si_remplissage_uniquement coché * * @return void */ function formidable_migrer_formulaires_afficher_si_remplissage() { // selection include_spip('inc/saisies_migrer_afficher_si_remplissage'); if ($res = sql_select(['id_formulaire','saisies'], 'spip_formulaires')) { // boucler sur les resultats while ($row = sql_fetch($res)) { $id_formulaire = $row['id_formulaire']; if ($saisies = unserialize($row['saisies'])) { $saisies = saisies_migrer_afficher_si_remplissage($saisies); $saisies = serialize($saisies); sql_updateq( 'spip_formulaires', ['saisies' => $saisies], 'id_formulaire=' . intval($id_formulaire) ); } } } } /** * Convertit la config d'anonymisation des réponses des formulaires qui l'avaient activés. * Le but étant de séparer l'anonymisation et l'identification par valeur PHP. * C'est à dire, pour ces formulaires: * 1. Change le nom de la variable de config. * 2. Si jamais la identification était par id_auteur, la transforme en par valeur php. * 3. Conserve l'anonymat des réponses * Et aussi * 1. Avant toute chose, crée une colonne variable_php * 2. Migre, pour les formulaires concernées, id_auteur vers variable_php * @return void **/ function formidable_migrer_anonymisation() { sql_alter('TABLE spip_formulaires_reponses ADD column `variable_php` bigint(21) NOT NULL default 0 AFTER `cookie`'); sql_alter('TABLE spip_formulaires_reponses ADD INDEX (variable_php)'); $res = sql_select('id_formulaire, traitements', 'spip_formulaires'); while ($row = sql_fetch($res)) { $id_formulaire = $row['id_formulaire']; $traitements = unserialize($row['traitements']); $enregistrement = isset($traitements['enregistrement']) ? $traitements['enregistrement'] : []; // A-ton l'option d'anonymisation activée? alors on migre, sinon rien à changer if (($enregistrement['anonymiser'] ?? '') == 'on') { $enregistrement['variable_php'] = isset($enregistrement['anonymiser_variable']) ? $enregistrement['anonymiser_variable'] : ''; unset($enregistrement['anonymiser_variable']); if (($enregistrement['identification'] ?? '') === 'id_auteur') { $enregistrement['identification'] = 'variable_php'; } // Mettre à jour le traitement $traitements['enregistrement'] = $enregistrement; $traitements = serialize($traitements); sql_updateq('spip_formulaires', ['traitements' => $traitements], "id_formulaire=$id_formulaire"); // Mettre à jour les réponses $res_reponse = sql_select('id_auteur,id_formulaires_reponse', 'spip_formulaires_reponses', "id_formulaire=$id_formulaire"); while ($raw_reponse = sql_fetch($res_reponse)) { $id_formulaires_reponse = $raw_reponse['id_formulaires_reponse']; sql_updateq('spip_formulaires_reponses', ['variable_php' => $raw_reponse['id_auteur'], 'id_auteur' => 0], "id_formulaires_reponse=$id_formulaires_reponse"); } } } } /** * Cherche tous les formulaires et migre le champ resume_reponse vers une option du traitement "enregistrer" * * Supprime ensuite ce champ de la structure de table * @return void */ function formidable_migrer_resume_reponse() { if ($res = sql_select(['id_formulaire','traitements','resume_reponse'], 'spip_formulaires')) { while ($row = sql_fetch($res)) { $id_formulaire = $row['id_formulaire']; $traitements = unserialize($row['traitements']); $resume_reponse = $row['resume_reponse']; if ($resume_reponse) { if (isset($traitements['enregistrement'])) { $traitements['enregistrement']['resume_reponse'] = $resume_reponse; } else { $traitements['enregistrement'] = ['resume_reponse' => $resume_reponse]; } sql_updateq( 'spip_formulaires', ['traitements' => serialize($traitements)], "id_formulaire=$id_formulaire" ); } } } // suppression du champ sql_alter('TABLE spip_formulaires DROP COLUMN resume_reponse'); } /** * https://zone.spip.net/trac/spip-zone/changeset/111847/ avait créer des traitements enregistrer sans options * C'était un bug * Cela ne devrait pas exister * En outre, cela créait des enregistrements indus * On annule ces traitements enregistrer vide **/ function formidable_effacer_traitement_enregistrer_sans_option() { include_spip('inc/sql'); $res = sql_select('id_formulaire,traitements', 'spip_formulaires'); while ($row = sql_fetch($res)) { $traitements = unserialize($row['traitements']); if ($traitements['enregistrement'] === []) { unset($traitements['enregistrement']); } $traitements = serialize($traitements); sql_updateq('spip_formulaires', ['traitements' => $traitements], 'id_formulaire=' . $row['id_formulaire']); } } /** * Migre la config depuis formidable/analyse vers formidable **/ function formidable_migrer_config() { include_spip('inc/config'); $config = lire_config('formidable/analyse'); effacer_config('formidable/analyse'); ecrire_config('formidable', $config); } /** * Tester les liens existants et pour chacun voir si on doit mettre vu=oui */ function formidable_verifier_liens_vu() { include_spip('action/editer_liens'); include_spip('formidable_pipelines'); // Chercher tous les liens de form pas marqué comme vu if ($liens = objet_trouver_liens(['formulaire' => '*'], ['*' => '*'], ['vu="non"'])) { foreach ($liens as $lien) { $table = table_objet_sql($lien['objet']); $cle = id_table_objet($lien['objet']); if ($contenu = sql_fetsel('*', $table, "$cle=" . intval($lien['id_objet']))) { $contenu = implode(' ', $contenu); // On cherche les modèles insérés dans les textes du contenu $formulaires = formidable_trouve_liens($contenu); // Est-ce qu'on trouve le form de ce lien dans les modèles trouvés if (isset($formulaires[$lien['id_formulaire']])) { // On lui ajoute vu=oui objet_qualifier_liens(['formulaire' => $lien['id_formulaire']], [$lien['objet'] => $lien['id_objet']], ['vu' => 'oui']); } } } } } /** * Désinstallation/suppression des tables de formidable * * @param string $nom_meta_base_version * Nom de la meta informant de la version du schéma de données du plugin installé dans SPIP * @return void */ function formidable_vider_tables($nom_meta_base_version) { include_spip('inc/meta'); include_spip('inc/config'); include_spip('base/abstract_sql'); // On efface les tables du plugin sql_drop_table('spip_formulaires'); sql_drop_table('spip_formulaires_reponses'); sql_drop_table('spip_formulaires_reponses_champs'); sql_drop_table('spip_formulaires_liens'); // on efface les champs d'import de f&t si il y a lieu $trouver_table = charger_fonction('trouver_table', 'base'); if ($trouver_table('spip_forms')) { sql_alter('TABLE spip_forms DROP id_formulaire'); } if ($trouver_table('spip_forms_donnees')) { sql_alter('TABLE spip_forms_donnees DROP id_formulaires_reponse'); } // Effacer les PJ include_spip('inc/formidable_fichiers'); supprimer_repertoire(_DIR_FICHIERS_FORMIDABLE); // On efface la version enregistrée effacer_config('formidable'); effacer_meta($nom_meta_base_version); } /** * Identifier toutes les saisies en base **/ function formidable_saisies_identifier() { include_spip('inc/saisies'); $res = sql_select('id_formulaire, saisies', 'spip_formulaires'); while ($row = sql_fetch($res)) { $saisies = unserialize($row['saisies']); $saisies = saisies_identifier($saisies); $saisies = serialize($saisies); sql_updateq('spip_formulaires', ['saisies' => $saisies], 'id_formulaire=' . $row['id_formulaire']); } } /** * Créer une clé hashée secret_de_formidable qui ne sera plus modifiée par la suite * * @return void */ function formidable_creer_secret() { if (lire_config('secret_de_formidable')) { return; } include_spip('inc/acces'); include_spip('auth/sha256.inc'); ecrire_config( 'secret_de_formidable', spip_sha256( $_SERVER['DOCUMENT_ROOT'] . (isset($_SERVER['SERVER_SIGNATURE']) ? $_SERVER['SERVER_SIGNATURE'] : '') . creer_uniqid() ) ); }