Changeset 89269 in spip-zone


Ignore:
Timestamp:
May 9, 2015, 9:15:32 PM (4 years ago)
Author:
rastapopoulos@…
Message:

Version 1.0.0 de CVT-Upload ! Ajout à l'API CVT qui permet de savoir gérer les fichiers envoyés même si les formulaires s'arrêtent avec des erreurs. La gestion des fichiers ne se fait plus pareil : on enregistre tout dans un même dossier, mais ensuite ce dossier est vidé régulièrement suivant l'âge des fichiers ainsi que le nombre de fichiers maximum. De plus, les informations de chaque fichier ne sont plus enregistrées dans la session du visiteur. Et aussi le morceau de HTML qui présente le fichier envoyé est maintenant dans un squelette SPIP surchargeable.

Location:
_plugins_/cvt-upload/trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/cvt-upload/trunk/cvtupload_pipelines.php

    r63357 r89269  
    33// Sécurité
    44if (!defined("_ECRIRE_INC_VERSION")) return;
     5
     6/**
     7 * Age maximum des fichiers dans le dossier temporaire
     8 **/
     9if (!defined('_CVTUPLOAD_AGE_MAX')) {
     10        define('_CVTUPLOAD_AGE_MAX', 6*3600);
     11}
     12/**
     13 * Nombre maximum de fichiers dans le dossier temporaire
     14 **/
     15if (!defined('_CVTUPLOAD_MAX_FILES')) {
     16        define('_CVTUPLOAD_MAX_FILES', 2);
     17}
    518
    619function cvtupload_chercher_fichiers($form, $args){
     
    2942        if ($champs_fichiers = cvtupload_chercher_fichiers($flux['args']['form'], $flux['args']['args'])){
    3043                $contexte =& $flux['data'];
    31                 // S'il n'y a pas déjà une action de configurée, on en force une pour avoir un hash unique par visiteur
    32                 if (!$contexte['_action'])
    33                         $contexte['_action'] = array('cvtupload', 'cvtupload');
     44               
     45                // On déclare le champ qui contiendra les infos en hidden
     46                $contexte['cvtupload_fichiers_precedents'] = array();
     47               
     48                // On met dans le contexte le HTML pour les fichiers précédemment postés
     49                if ($html_fichiers = cvtupload_generer_html()) {
     50                        $contexte['_fichiers_precedents_html'] = $html_fichiers;
     51                }
    3452        }
    3553       
     
    4462                include_spip('inc/documents');
    4563                include_spip('inc/getdocument');
    46                 include_spip('inc/charsets');
    47                
    48                 $hash = cvtupload_hash();
     64                include_spip('inc/flock');
    4965               
    5066                //Si le répertoire temporaire n'existe pas encore, il faut le créer.
    5167                $repertoire_tmp = sous_repertoire(_DIR_TMP.'cvtupload/');
    52                 $repertoire_tmp = sous_repertoire($repertoire_tmp, $hash.'/');
     68               
     69                // On récupère les anciens fichiers déjà postés
     70                $infos_fichiers_precedents = _request('cvtupload_fichiers_precedents');
     71                $infos_fichiers = array();
     72               
     73                // Les demandes de suppression
     74                $supprimer_fichier = _request('cvtupload_supprimer_fichier');
    5375               
    5476                // On parcourt les champs déclarés comme étant des fichiers
    55                 $infos_fichiers = session_get($hash.'_fichiers') ? session_get($hash.'_fichiers') : array();
    5677                foreach ($champs_fichiers as $champ){
    57                         if ($_FILES[$champ]){
    58                                 $infos = cvtupload_deplacer_fichier($_FILES[$champ], $repertoire_tmp);
    59                                 if (isset($infos_fichiers[$champ]))
     78                        // On commence par ne récupérer que les anciennes informations
     79                        // Si ce champ de fichier est multiple, on décode chaque champ
     80                        if (is_array($infos_fichiers_precedents[$champ])) {
     81                                foreach ($infos_fichiers_precedents[$champ] as $cle=>$fichier) {
     82                                        if ($infos_decodees = decoder_contexte_ajax($fichier, $flux['args']['form'])) {
     83                                                $infos_fichiers[$champ][$cle] = $infos_decodees;
     84                                                $infos_fichiers[$champ][$cle]['infos_encodees'] = encoder_contexte_ajax($infos_decodees, $flux['args']['form']);
     85                                               
     86                                                // Si suppression
     87                                                if (isset($supprimer_fichier[$champ][$cle])) {
     88                                                        supprimer_fichier($infos_fichiers[$champ][$cle]['tmp_name']);
     89                                                        unset($infos_fichiers[$champ][$cle]);
     90                                                        // On génère une erreur pour réafficher le form de toute façon
     91                                                        $erreurs["rien_$champ_$cle"] = 'rien';
     92                                                }
     93                                        }
     94                                }
     95                        }
     96                        // Si le champ est unique, on décode juste le champ
     97                        elseif ($infos_decodees = decoder_contexte_ajax($infos_fichiers_precedents[$champ], $flux['args']['form'])) {
     98                                $infos_fichiers[$champ] = $infos_decodees;
     99                                $infos_fichiers[$champ]['infos_encodees'] = encoder_contexte_ajax($infos_decodees, $flux['args']['form']);
     100                               
     101                                // Si suppression
     102                                if (isset($supprimer_fichier[$champ])) {
     103                                        supprimer_fichier($infos_fichiers[$champ]['tmp_name']);
     104                                        unset($infos_fichiers[$champ]);
     105                                        // On génère une erreur pour réafficher le form de toute façon
     106                                        $erreurs["rien_$champ"] = 'rien';
     107                                }
     108                        }
     109                       
     110                        // On déplace le fichier dans notre dossier tmp de SPIP
     111                        // Et on met à jour les infos par rapport aux anciennes
     112                        if (
     113                                $_FILES[$champ]
     114                                and $infos = cvtupload_deplacer_fichier($_FILES[$champ], $repertoire_tmp, $flux['args']['form'])
     115                        ){
     116                                if (isset($infos_fichiers[$champ])) {
    60117                                        $infos_fichiers[$champ] = array_merge($infos_fichiers[$champ], $infos);
    61                                 else
     118                                }
     119                                else {
    62120                                        $infos_fichiers[$champ] = $infos;
    63                         }
    64                 }
    65                 set_request('_fichiers', $infos_fichiers);
    66                 session_set($hash.'_fichiers', $infos_fichiers);
     121                                }
     122                        }
     123                }
     124               
     125                // On utilise ces infos pour générer le HTML et le garder pour charger()
     126                cvtupload_generer_html($infos_fichiers);
    67127        }
    68128       
     
    72132function cvtupload_formulaire_fond($flux){
    73133        // Si ça a déjà été posté (après verifier()) et qu'il y a des champs fichiers déclarés
    74         if ($flux['args']['je_suis_poste']
     134        if (
     135                $flux['args']['je_suis_poste']
    75136                and $champs_fichiers = cvtupload_chercher_fichiers($flux['args']['form'], $flux['args']['args'])
    76         ){
    77                 $fichiers = _request('_fichiers');
    78                 foreach ($champs_fichiers as $champ){
     137        ) {
     138                include_spip('inc/filtres');
     139                $fichiers = $flux['args']['contexte']['_fichiers_precedents_html'];
     140               
     141                foreach ($champs_fichiers as $champ) {
    79142                        // Si le visiteur a bien réussi a charger un ou plusieurs fichiers dans ce champ
    80                         if (isset($fichiers[$champ])){
    81                                 include_spip('inc/filtres_images');
     143                        if (isset($fichiers[$champ])) {
    82144                                // Si c'est un champ unique
    83                                 if (isset($fichiers[$champ]['name'])){
     145                                if (!is_array($fichiers[$champ])) {
    84146                                        $flux['data'] = preg_replace(
    85147                                                "#<input[^>]*name=['\"]${champ}[^>]*>#i",
    86                                                 image_reduire($fichiers[$champ]['vignette'],32).' '.$fichiers[$champ]['name'],
     148                                                $fichiers[$champ],
    87149                                                $flux['data']
    88150                                        );
    89151                                }
    90152                                // Sinon c'est un multiple
    91                                 else{
    92                                         foreach($fichiers[$champ] as $cle=>$fichier){
     153                                else {
     154                                        foreach ($fichiers[$champ] as $cle=>$html) {
    93155                                                $flux['data'] = preg_replace(
    94156                                                        "#<input[^>]*name=['\"]${champ}[^>]*>#i",
    95                                                         image_reduire($fichier['vignette'],32).' '.$fichier['name'],
     157                                                        $html,
    96158                                                        $flux['data'],
    97159                                                        1 // seul le premier trouvé est remplacé
     
    102164                }
    103165        }
     166       
    104167        return $flux;
    105168}
     
    118181}
    119182
    120 /*
     183/**
     184 * Génére le HTML de chaque fichier déjà uploadés
     185 *
     186 * @param array $infos_fichiers
     187 *              Talbeau contenant les informations pour chaque champ de fichier
     188 * @return array
     189 *              Retourne un tableau avec pour chaque champ une clé contenant le HTML
     190 **/
     191function cvtupload_generer_html($infos_fichiers=null){
     192        static $html_fichiers = array();
     193       
     194        // Si on a des infos de fichiers, on va re-générer du HTML
     195        if ($infos_fichiers and is_array($infos_fichiers)) {
     196                foreach ($infos_fichiers as $champ=>$fichier) {
     197                        // Si c'est un champ unique
     198                        if (isset($fichier['name'])) {
     199                                $html_fichiers[$champ] = recuperer_fond(
     200                                        'formulaires/inc-cvtupload-fichier',
     201                                        array_merge($fichier, array('crochets'=>"[$champ]"))
     202                                );
     203                        }
     204                        // Sinon c'est un champ multiple
     205                        else {
     206                                foreach ($fichier as $cle=>$infos) {
     207                                        $html_fichiers[$champ][$cle] = recuperer_fond(
     208                                                'formulaires/inc-cvtupload-fichier',
     209                                                array_merge($infos, array('crochets'=>"[$champ][$cle]"))
     210                                        );
     211                                }
     212                        }
     213                }
     214        }
     215       
     216        return $html_fichiers;
     217}
     218
     219/**
    121220 * Déplace un fichier uploadé dans un endroit temporaire et retourne des informations dessus
    122221 *
    123  * @param array $fichier Le morceau de $_FILES concernant le ou les fichiers
    124  * @param string $$repertoire Chemin de destination des fichiers
    125  * @return array Retourne un tableau d'informations sur le fichier ou un tableau de tableaux si plusieurs fichiers. Ce tableau est compatible avec l'action "ajouter_un_fichier" de SPIP.
    126  */
    127 function cvtupload_deplacer_fichier($fichier, $repertoire){
     222 * @param array $fichier
     223 *              Le morceau de $_FILES concernant le ou les fichiers
     224 * @param string $repertoire
     225 *              Chemin de destination des fichiers
     226 * @param string $prefix
     227 *              Formulaire d'où ça vient
     228 * @return array
     229 *              Retourne un tableau d'informations sur le fichier ou un tableau de tableaux si plusieurs fichiers. Ce tableau est compatible avec l'action "ajouter_un_fichier" de SPIP.
     230 **/
     231function cvtupload_deplacer_fichier($fichier, $repertoire, $form){
    128232        $vignette_par_defaut = charger_fonction('vignette', 'inc/');
    129233        $infos = array();
     234       
     235        // On commence par nettoyer le dossier
     236        cvtupload_nettoyer_repertoire($repertoire);
     237       
    130238        if (is_array($fichier['name'])){
    131239                foreach ($fichier['name'] as $cle=>$nom){
    132240                        // On commence par transformer le nom du fichier pour éviter les conflits
    133241                        $nom = trim(preg_replace('/[\s]+/', '_', strtolower(translitteration($nom))));
    134                         // Si le fichier a bien un nom et qu'il n'y a pas d'erreur associé à ce fichier
    135                         if (($nom != null) and ($fichier['error'][$cle] == 0)) {
    136                                 //On vérifie qu'un fichier ne porte pas déjà le même nom, sinon on lui donne un nom aléatoire + nom original
    137                                 if (file_exists($repertoire.$nom))
    138                                         $nom = $nom.'_'.rand();
     242                        if (
     243                                // Si le fichier a bien un nom et qu'il n'y a pas d'erreur associé à ce fichier
     244                                ($nom != null)
     245                                and ($fichier['error'][$cle] == 0)
     246                                // Et qu'on génère bien un nom de fichier aléatoire pour déplacer le fichier
     247                                and $chemin_aleatoire = tempnam($repertoire, $form.'_')
     248                        ) {
    139249                                // Déplacement du fichier vers le dossier de réception temporaire + récupération d'infos
    140                                 if (deplacer_fichier_upload($fichier['tmp_name'][$cle], $repertoire.$nom, true)) {
    141                                         $infos[$cle]['tmp_name'] = $repertoire.$nom;
     250                                if (deplacer_fichier_upload($fichier['tmp_name'][$cle], $chemin_aleatoire, true)) {
     251                                        $infos[$cle]['tmp_name'] = $chemin_aleatoire;
    142252                                        $infos[$cle]['name'] = $nom;
    143253                                        // On en déduit l'extension et du coup la vignette
     
    146256                                        //On récupère le type MIME du fichier aussi
    147257                                        $infos[$cle]['mime'] = $fichier['type'][$cle];
     258                                        $infos[$cle]['form'] = $form;
     259                                        $infos[$cle]['infos_encodees'] = encoder_contexte_ajax($infos[$cle], $form);
    148260                                }
    149261                        }
     
    153265                // On commence par transformer le nom du fichier pour éviter les conflits
    154266                $nom = trim(preg_replace('/[\s]+/', '_', strtolower(translitteration($fichier['name']))));
    155                 // Si le fichier a bien un nom et qu'il n'y a pas d'erreur associé à ce fichier
    156                 if (($nom != null) && ($fichier['error'] == 0)) {
    157                         //On vérifie qu'un fichier ne porte pas déjà le même nom, sinon on lui donne un nom aléatoire + nom original
    158                         if (file_exists($repertoire.$nom))
    159                                 $nom = $nom.'_'.rand();
     267                if (
     268                        // Si le fichier a bien un nom et qu'il n'y a pas d'erreur associé à ce fichier
     269                        ($nom != null)
     270                        and ($fichier['error'] == 0)
     271                        // Et qu'on génère bien un nom de fichier aléatoire pour déplacer le fichier
     272                        and $chemin_aleatoire = tempnam($repertoire, $form.'_')
     273                ) {
    160274                        // Déplacement du fichier vers le dossier de réception temporaire + récupération d'infos
    161                         if (deplacer_fichier_upload($fichier['tmp_name'], $repertoire.$nom, true)) {
    162                                 $infos['tmp_name'] = $repertoire.$nom;
     275                        if (deplacer_fichier_upload($fichier['tmp_name'], $chemin_aleatoire, true)) {
     276                                $infos['tmp_name'] = $chemin_aleatoire;
    163277                                $infos['name'] = $nom;
    164278                                // On en déduit l'extension et du coup la vignette
     
    167281                                //On récupère le type MIME du fichier aussi
    168282                                $infos['mime'] = $fichier['type'];
     283                                $infos['form'] = $form;
     284                                $infos['infos_encodees'] = encoder_contexte_ajax($infos, $form);
    169285                        }
    170286                }
     
    174290}
    175291
    176 ?>
     292/**
     293 * Nettoyer un répertoire suivant l'age et le nombre de ses fichiers
     294 *
     295 * @param string $repertoire
     296 *              Répertoire à nettoyer
     297 * @param int $age_max
     298 *              Age maxium des fichiers en seconde
     299 * @param int $max_files
     300 *              Nombre maximum de fichiers dans le dossier
     301 * @return void
     302 **/
     303function cvtupload_nettoyer_repertoire($repertoire, $age_max=_CVTUPLOAD_AGE_MAX, $max_files=_CVTUPLOAD_MAX_FILES) {
     304        include_spip('inc/flock');
     305       
     306        // Si on entre bien dans le répertoire
     307        if ($ressource_repertoire = opendir($repertoire)) {
     308                $fichiers = array();
     309               
     310                // On commence par supprimer les plus vieux
     311                while ($fichier = readdir($ressource_repertoire)) {
     312                        if (!in_array($fichier, array('.', '..', '.ok'))) {
     313                                $chemin_fichier = $repertoire.$fichier;
     314                               
     315                                if (is_file($fichier) and !jeune_fichier($chemin_fichier, $age_max)) {
     316                                        supprimer_fichier($chemin_fichier);
     317                                }
     318                                else {
     319                                        $fichiers[@filemtime($chemin_fichier).'_'.rand()] = $chemin_fichier;
     320                                }
     321                        }
     322                }
     323               
     324                // On trie les fichiers par ordre de leur date
     325                ksort($fichiers);
     326               
     327                // Puis s'il reste trop de fichiers, on supprime le surplus
     328                $nb_fichiers = count($fichiers);
     329                if ($nb_fichiers > $max_files) {
     330                        $nb_a_supprimer = $nb_fichiers - $max_files - 1;
     331                       
     332                        while ($nb_a_supprimer) {
     333                                $fichier = array_shift($fichiers);
     334                                supprimer_fichier($fichier);
     335                                $nb_a_supprimer--;
     336                        }
     337                }
     338        }
     339}
  • _plugins_/cvt-upload/trunk/formulaires/test_upload.php

    r63357 r89269  
    99                'tromperie' => '',
    1010                'seul' => '',
    11                 'plusieurs' => array()
     11                'plusieurs' => array(),
    1212        );
    1313       
  • _plugins_/cvt-upload/trunk/paquet.xml

    r89143 r89269  
    22        prefix="cvtupload"
    33        categorie="outil"
    4         version="0.2.0"
     4        version="1.0.0"
    55        etat="experimental"
    66        compatibilite="[3.0.0;3.0.*]"
Note: See TracChangeset for help on using the changeset viewer.