Forum CMS Made Simple FR

Version complète : [Résolu] CGSmartImage, udt et cache
Vous consultez actuellement la version basse qualité d’un document. Voir la version complète avec le bon formatage.
Citation :#~~~~~ DEBUT BLOC A NE PAS SUPPRIMER ~~~~~
#~ Version du CMS: #1.10.1
#~ Url du site : www.nextrides.yannlamy.com
#~ Hébergeur / Soft : hébergeur pas cher
#~ Informations Système :
#~ ----------------------------------------------
#~ Cms Version: 1.10.1
#~ Installed Modules:
#~ CMSMailer: 2.0.2
#~ CMSPrinting: 1.0
#~ FileManager: 1.2.0
#~ MenuManager: 1.7.7
#~ MicroTiny: 1.1.1
#~ ModuleManager: 1.5.1
#~ News: 2.12.3
#~ Search: 1.7
#~ ThemeManager: 1.1.4
#~ CGExtensions: 1.27.1
#~ FrontEndUsers: 1.16.4
#~ SelfRegistration: 1.6.13
#~ CustomContent: 1.7.3
#~ CGSmartImage: 1.6.1
#~ CGSimpleSmarty: 1.4.10
#~ Config Information:
#~ php_memory_limit:
#~ process_whole_template: false
#~ output_compression: true
#~ max_upload_size: 6000000
#~ default_upload_permission: 664
#~ url_rewriting: mod_rewrite
#~ page_extension: .html
#~ query_var: page
#~ image_manipulation_prog: GD
#~ auto_alias_content: true
#~ locale:
#~ default_encoding: utf-8
#~ admin_encoding: utf-8
#~ set_names: true
#~ Php Information:
#~ phpversion: 5.3.8
#~ md5_function: On (Vrai)
#~ gd_version: 2
#~ tempnam_function: On (Vrai)
#~ magic_quotes_runtime: Off (Faux)
#~ E_STRICT: 0
#~ E_DEPRECATED: 0
#~ memory_limit: 64M
#~ max_execution_time: 90
#~ output_buffering: On
#~ safe_mode: Off (Faux)
#~ file_uploads: On (Vrai)
#~ post_max_size: 10M
#~ upload_max_filesize: 6M
#~ session_save_path: /tmp (1777)
#~ session_use_cookies: On (Vrai)
#~ xml_function: On (Vrai)
#~ Server Information:
#~ Server Api: cgi-fcgi
#~ Server Db Type: MySQL (mysql)
#~ Server Db Version: 5.1.56
#~ ----------------------------------------------
#~~~~~ FIN BLOC A NE PAS SUPPRIMER ~~~~~



Bonjour à tous,

toujours sur mon site qui me permet de tester plein de trucs, aujourd'hui, c'est une histoire de cache qui me pose problème.

En effet, avec feu les gens peuvent uploader une image qui s'affiche comme avatar lors de leur connection.
cet avatar est généré de 2 façons mais toujours par l'intermédiaire de CGSmartImage.
ces 2 façons sont soit directement cgsi soit par une udt {avatar} qui utilise cgsi.

mon soucis dans le cas présent est que utilisant jquery à outrance ( Sad )... mes changements de paramètres se font par l'intermédiaire du formulaire feu placé dans une fancybox (le formulaire est donc en iframe), ce qui fonctionne mais qui m'ennuit pour la mise a jour des images.
lorsque je recharge mon iframe et mon module de login (tout ça par jquery) les avatars ne se mettent pas à jour. il faut une réactualisation complète de la page pour ça fonctionne et encore, pas sur les iframes qui utilisent l'udt pour l'affichage de l'avatar.
j'ai donc rajouté un script php, appelé en ajax, pour effacer toutes les miniatures de l'image, générées par cgsi pour qu'au prochain affichage elles soient regénérées... mais que dalle! elles sont bien regénérées mais l'explorateur continue d'afficher l'ancienne image...
c'est donc surement un problème de mise en cache par l'explorateur mais j'aimerai bien pouvoir y remédier.

Donc si quelqu'un avait une idée pour régler ce problème....

merci bien.

les différents codes à dispo

udt avatar:

Code :
[== PHP ==]
global $gCms;

$feu =& cms_utils::get_module('FrontEndUsers');
$userloggedin = $feu->LoggedIn();

$width = $params['width'];
$height = $params['height'];

if($userloggedin){

   $userid = $feu->LoggedInId();
   $photo = $feu->GetUserPropertyFull('image',$userid);

   if (file_exists("uploads/feusers/".$photo)){

      $photosrc = 'uploads/feusers/'.$photo;}
  
   else{
        
      $photosrc = 'uploads/Nextrides/avatar.jpg';}
  
      
      $smarty = &cmsms()->GetSmarty();
      $smarty_data = "{CGSmartImage src=$photosrc filter_resizetofit=$width,$height,transparent,0 overwrite='true'} ";
      $smarty->_compile_source('temporary template', $smarty_data, $_compiled );
      @ob_start();
      $smarty->_eval('?>' . $_compiled);
      $_contents = @ob_get_contents();
      @ob_end_clean();
     echo '<div id="avatar">'.$_contents.'</div>';



}

script d'effacement des miniatures générées:

Code :
[== PHP ==]
$img1 = $_POST['img1'];
$img_split = explode("-",$img1);
$regex = $img_split[0];
$chemin = "../_CGSmartImage";
$repertoire = opendir($chemin);
while(false !== ($fichier = readdir($repertoire))){
        if(preg_match('#^'.$regex.'#', $fichier)){
            if($fichier!="." AND $fichier!=".." AND !is_dir($fichier)){
                unlink($chemin.'/'.$fichier);
                echo $fichier;}
        }
}

closedir($repertoire);
Je vions de m'apercevoir un truc aussi concernant FEU, c'est que lorsqu'on vide une image uploadée, ça l'efface bien du dossier feusers mais pas de la base de donnée... c'est pas logique ce truc là, non?
c'est le comportement de ton navigateur qui provoque cela

système interne de cache. il conserve l'url qui ne change pas d'une image et donc ne retélécharge pas l'image

voilà pour la cause... maintenant faut trouver la solution Sad
J'ai trouvé ceci qui pourrait peut-être fonctionner : forcer le rafraichissement d'une image qui a été modifiée
passer par de l'url rewriting me parait un peu extreme mais l'idée de coller un paramètre à l'url de l'image pour forcer son re-téléchargement est effectivement une bonne idée

attention toute fois à ce que ce paramètre variable ne soit pas regénéré à chaque chargement de page ... par ce que sinon bonjour la bande passante !
Merci à vous 2 pour votre contribution.

Je suis une brèle en codage mais j'ai vu que CGSmartImage incluait déjà une variable encodée en md5 dans le nom de l'image par contre je ne sais pas encore ce qui est rajouté.
J'ai vu sur le net que le mieux est de rajouté un time() encodé dan le nom comme ça, on est sûr d'avoir un nom différent à chaque fois et donc plus de soucis de cache puisque rechargement à chaque fois.

je pense donc que c'est au niveau de CGSI qu'il faut que je regarde plus précisemment comment est généré le nom de la miniature et le modifier si besoin est.
donc vérifier le md5 généré dans le nom et vérifier le paramètre overwritte pour voir si il re-écrit sur l'ancien fichier généré ou si il l'efface et en re-crée un avec un md5 différent...


je dis des conneries... c'est le nom enregistré dans la bd de FEU qui doit être modifié pour avoir un nom différenrent et que CGSI recrée une miniature à chaque changement d'image et non pas à chaque regénération de page , comme ça le cache du navigateur sera utilisé à bon escient, me trompe-je???

j'essaye de regarder tout ça et je vous dis.

Par contre pour cette histoire de vidage d'image, j'aimerai bien savoir si chez les autres c'est aussi que le fichier image qui est supprimmé ou si l'entrée dans la base de donnée l'est aussi car pour la vérification avant affichage, ça change un peu la façon de faire.
Bon voilà, c'est réglé en modifiant FEU.

la solution trouvée:

FEU crée une image en la nommant de la sorte: $uid_image.jpg
la chose à faire était qu'à chaque modif elle soit nommé: $uid_image$1.jpg
$1 étant incrémenté de 1 à chaque changement.

si l'image était vidé, on réinitialise le tout et au prochain upload, on recommence à $uid_image.jpg... puis $uid_image1.jpg...$uid_image2.jpg...etc

il fallait aussi que ça fonctionne si l'admin changeait l'image ou l'effacer depuis la partie admin.

donc les changement de script:

3 pages sont concernées:
  1. FrontEndUsers.module.php
  2. action.do_userchangesettings.php
  3. action.do_edituser3.php

FrontEndUsers.module.php
on récupère l'ancien nom de l'image
ligne 1239 (environ)


Code :
// avant changement
function ManageImageUpload($id, $fldprefix, $fldname, $uid)



//après changement
function ManageImageUpload($id, $fldprefix, $fldname, $uid, $oldval)

si ce nom existe on l'incrémente de 1
ligne 1286 (environ)

Code :
[== Indéfini ==]
// avant changement

$ext = strchr($file['name'],'.');
$destname = $uid.'_'.$fldname.$ext;




// après changement

if(isset($oldval)&& !empty($oldval)){
    
          function ajouteun($masque){
             return $masque[1].($masque[2]+1).$masque[3];
          }
      $destname = preg_replace_callback('`([0-9]_image)(\d+)?(\.[a-z])`','ajouteun',$oldval);
}
else{
      $ext = strchr($file['name'],'.');
          $destname = $uid.'_'.$fldname.$ext;
}

on efface l'ancienne image du serveur si elle existe
ligne 11299 (environ)

Code :
[== Indéfini ==]
// avant changement

    // Create the destination directory if necessary
    $destDir = $this->get_upload_dirname($uid);
    @mkdir($destDir);
    if( !is_writable( $destDir ) )
      {
    return array(false,$this->Lang('error_destinationnotwritable'));
      }

    @cms_move_uploaded_file($file['tmp_name'], cms_join_path($destDir,$destname));

    return array(true,$destname);
  }



// après changement

    // Create the destination directory if necessary
    $destDir = $this->get_upload_dirname($uid);
    @mkdir($destDir);
    if( !is_writable( $destDir ) )
      {
    return array(false,$this->Lang('error_destinationnotwritable'));
      }

    @cms_move_uploaded_file($file['tmp_name'], cms_join_path($destDir,$destname));
    
    if(isset($oldval)&& !empty($oldval)){
        @unlink(cms_join_path($destDir,$oldval));
    }

    return array(true,$destname);
  }


action.do_userchangesettings.php
on envoie le nom de l'image précédemment utilisé à la fonction ManageImageUpload()
ligne 289 (environ)

Code :
[== Indéfini ==]
// avant changement

$result = $this->ManageImageUpload($id, 'feu_input_', $propname, $uid);



// après changement

$result = $this->ManageImageUpload($id, 'feu_input_', $propname, $uid, $val );



action.do_edituser3.php
on récupère le nom de l'image précédemment utilisé et on l'envoie à la fonction ManageImageUpload()
ligne 309 (environ)

Code :
[== Indéfini ==]
// avant changement

// it's an uploaded file type

      $result = $this->ManageImageUpload($id,'input_', $k, $user_id);



// après changement

// it's an uploaded file type
      $oldval = trim($params['hidden_'.$k]);
      $result = $this->ManageImageUpload($id,'input_', $k, $user_id, $oldval );


voilà, comme ça à chaque nouvel upload d'image le nom change et s'incrémente de 1 aussi bien coté frontend que coté admin et du coup l'image est bien régénéré à chaque changement.

Pour CGSI l'utilisation du paramètre nobchache=1 marchait aussi mais obligeait à recrée une miniature à chaque affichage dont plus d'utilisation du cache du navigateur.
avec ces changement les images restent en cache tant qu'il n'y a pas de nouvel upload.

si quelqu'un voit des améliorations aux changements que j'ai fait, allez-y, je suis tout ouie!
je ré-ouvre la discussion pour apporter un complément

tu modifie le source de FEU, on sait tous ce que ça signifie pour la prochaine mise à jour.

Une solution un peu plus propre existe et t'évitera de perdre tes modifications durant un update de module

http://calguy1000.com/Blogs/6/60/customi...lates.html
Merci Bess pour cette astuce!

Je viens de faire les changements en créant mon dossier module_custom.
Ca tombe bien, vu que j'ai revu aussi le filtre resizetofit de CGSmartImage dont je ne trouvais pas la logique correcte... j'ai pu faire tous ces changements de manière non destructive.


A noter aussi que mon script php appelé en ajx pour effacer toutes les miniatures générée par CGSI ne marche plus avec les les modifs puisque les noms des images comportent maintenant un numéro donc, je l'ai modifié comme ça:

Code :
[== PHP ==]
$img1 = $_POST['img1'];
preg_match('/(\d+_[a-z]+)/',$img1,$regex);
$regex = $regex[1];
$chemin = "../_CGSmartImage";
$repertoire = opendir($chemin);
while(false !== ($fichier = readdir($repertoire))){
        if(preg_match('#^'.$regex.'#', $fichier)){
            if($fichier!="." AND $fichier!=".." AND !is_dir($fichier)){
                unlink($chemin.'/'.$fichier);
                echo $fichier;}
        }
}

closedir($repertoire);

voilà, c'était histoire de tout mettre à jour!
bess a écrit :je ré-ouvre la discussion pour apporter un complément

tu modifie le source de FEU, on sait tous ce que ça signifie pour la prochaine mise à jour.

Une solution un peu plus propre existe et t'évitera de perdre tes modifications durant un update de module

http://calguy1000.com/Blogs/6/60/customi...lates.html

Alors après test, la solution module_custom ne marche pas pour la simple raison que module_custom ne permet de changer que les fichiers lang et template mais pas le core ecrit en php (cf: IRC)
Ils m'ont aussi demandé de ne pas partager de hack sur le forum pour pas qu'ils soient utilisés incorrectement et que ça crée des problèmes difficilement résolvables par la suite.... je crois que c'est trop tard pour celui-là Sad
haaa bha tu m'apprend un truc

pas de soucis avec le hack sur forum, c'est normal qu'ils t'ont dit cela, c'est également normal de signaler sur ce forum que si tu commence à modifier un module, tu perds la garantie constructeur. Smile

c'est pour cela que je t'avais proposé cette solution (erroné au final) qui évitait au moins de modifier en dur les fichiers des modules
J'ai appris un truc à bess... moi, un nOOb .... coooooool! ;-)
vive la persévérance!!!

pour compléter à nouveau si l'image n'est pas effacée de la bd lors d'une edition coté frontend c'est normal, le module est apparemment prévu comme ça, pt'être parce qu'un user n'efface presque jamais son image, il la remplace et comme le nom reste le même on touche pas à la bd pour ça.
C'est d'ailleurs un peu con car pour la vérif avant de l'afficher, on est obligé de vérifier la présence du fichier dans le dossier et non pas l'existance de l'image ( if(isset($image)) ne fonctionne plus en cas de vidage par l'utilisateur).

voilà, ça c'est fait!