aide prestashop PhenixSuite Help
    • Catégories
    • Récent
    • Mots-clés
    • Populaire
    • Utilisateurs
    • Groupes
    • Recherche
    • S'inscrire
    • Se connecter

    Images produit qui disparaissent

    Planifier Épinglé Verrouillé Déplacé Bugs & Améliorations
    30 Messages 4 Publieurs 1.4k Vues 4 Watching
    Charger plus de messages
    • Du plus ancien au plus récent
    • Du plus récent au plus ancien
    • Les plus votés
    Répondre
    • Répondre à l'aide d'un nouveau sujet
    Se connecter pour répondre
    Ce sujet a été supprimé. Seuls les utilisateurs avec les droits d'administration peuvent le voir.
    • C Hors-ligne
      camille
      dernière édition par

      Ben non, pas d'imports, les produits sont ajoutés manuellement via le BO. Pas de module de nettoyage non plus.
      Je vous joins la liste des modules actifs. Certains sont de mon cru, mais aucun n'agit sur les images produits.
      C'est vraiment curieux car le problème est survenu il n'y a pas longtemps. On est resté longtemps sur le site de dev (bp de modif dans les textes à faire) sans aucun souci. Cela touche des produits sur lesquels on n'est pas intervenus depuis un moment comme des produits mis à jour ou des nouveaux produits. C'est aléatoire. C'est la surprise du matin ...! J'ai vérifié le module créé pour ajouter le webp aux images des catégories, mais il ne cible que celles-ci et il n'y a pas de deleteImage.
      Au début, cela ne semblait concerner que quelques produits. Là (ou est-ce parce cette fois ça touche une page entière) c'est quasi 30 produits.
      liste-modules-actifs.jpg

      1 réponse Dernière réponse Répondre Citer 0
      • C Hors-ligne
        camille
        dernière édition par

        Bonjour, aujourd'hui 30 images ont "disparu".
        Alors je cherche.

        1. J'ai vu que la régénération des images était automatique. Utilise-t-elle la même procédure que celle de Prestashop ? (qui génère des erreurs 500 quand il y a beaucoup d'images).
          Si oui, j'ai peut-être alors une explication sur le nombre de pannes avec erreur 500
        2. Si elle est automatique et que le bouton "Supprimer les anciennes images" est activé, alors à chaque fois ces images sont supprimées pour être régénérées.
          Sauf que, à première vue, si des produits sont désactivés, les déclinaisons d'images sont supprimées et pas régénérées (home, cart, etc). Mais l'image de base est gardée. Ex 160.jpg
          => je n'ai pas encore tout vérifié, mais les images qui disparaissent sont, à priori, toutes dans des sous-dossiers d'images de produits désactivés.
          Ex : le produit 946 a une image id 1608, le 947 image id 1609, etc
          Dans le dossier 1>0>6 j'ai l'image 160.jpg (produit désactivé) mais je n'ai plus aucun sous-dossier

        J'ai désactivé la suppression des images dans la régénération. Il ne m'avait jamais semblé que l'état de ce bouton était pris en compte dans Prestashop.
        Donc, est-il possible que le processus de Phenix fasse comme la régénération manuelle de PS, avec prise en compte de l'état du bouton ? Et en provoquant autant d'erreurs 500 ? (au point qu'en général, sur PS, j'installe un module pour le faire, sans surcharge serveur)

        Merci d'avance

        1 réponse Dernière réponse Répondre Citer 0
        • C Hors-ligne
          camille
          dernière édition par

          Je confirme mon doute. J'ai testé sur le dev, à 2 reprises.
          Dans la bdd j'ai vu des images "soeurs"
          img id = 130 -> prod id = 166
          img id = 1301 - prod id = 840
          img id = 1302 - prod id = 841
          Donc j'ai ajouté une image au prod id 166.
          -> tout est ok
          J'ai alors supprimé l'ancienne image du prod 166 (img id 130)
          -> les produits 840 et 841 ont perdu leurs images, les dossiers 1>3>0>1 et 1>3>0>2 ont été effacés immédiatement.

          Je ne sais pas si il y a un lien mais j'ai testé ceci aussi sur le site de dev :
          img id 120 prod id 100.
          Ajout d'une image que je mets en couv
          -> dans le ftp la 120.jpg a perdu ses vignettes (home, cart, etc).
          Mais les dossiers 120x sont (encore) là.

          Sur le site de prod, hier, il y avait aussi des images "seules", elles semblent avoir toutes disparu aujourd'hui. Et, à priori, personne ne les a supprimées dans les fiches produit. Peut-être un script qui les considérait comme "orphelines" parce que sans vignettes ?

          voilà ...
          peut-être cela peut-il donner une piste ? un script trop gourmand ?
          Et comment savoir à quel moment la régénération automatique se fait ? Pour savoir si cela concorde avec les nombreuses erreurs 500 ?

          Merci d'avance !

          doekiaD 1 réponse Dernière réponse Répondre Citer 0
          • eoliaE Hors-ligne
            eolia
            dernière édition par

            Je vais regarder vos pistes.
            Concernant la regénération:

            • Plus d'erreur 500 car on ne les regénère plus, c'est en direct au 1er appel en FO ou BO.
            • Si vous cochez "Effacer les images précédentes" cela supprime uniquement les miniatures mais jamais l'image d'origine

            Créateur de PhenixSuite. Pour plus d'infos : https://eoliashop.com

            1 réponse Dernière réponse Répondre Citer 0
            • C Hors-ligne
              camille
              dernière édition par

              Merci Eolia. A première vue, avec ChatGpt, nous avons réussi à faire un override de la class Image.php et du controller admin AdminImagesController.php. Testé sur 2 copies du prod, la dernière version semble être ok.
              Voici le code de AdminImagesController.php

              <?php
              /**
               * Override anti-cascade pour la suppression/régénération des vignettes
               * Phenix/PS 1.6.x – DEV
               */
              class AdminImagesController extends AdminImagesControllerCore
              {
                  /**
                   * SAFE: supprime uniquement les tailles explicites, jamais l’original id.jpg,
                   * et n'exécute pas de nettoyage récursif global (pas de "cascade" sur les soeurs).
                   */
                  protected function _deleteOldImages($dir, $type, $product = false)
                  {
                      // TRACE facultative (décommente pour vérifier l’override)
                      // @error_log("[IMG] override _deleteOldImages CALLED in ".__FILE__."\n", 3, _PS_ROOT_DIR_."/var/log/img_trace.log");
              
                      if (!is_dir($dir)) {
                          return true;
                      }
              
                      // OK : purge du /img/tmp uniquement
                      Tools::deleteDirectory(_PS_TMP_IMG_DIR_, false);
              
                      // Liste blanche stricte des tailles
                      if (!is_array($type) || empty($type)) {
                          return true;
                      }
                      $allowed = array();
                      foreach ($type as $t) {
                          if (!empty($t['name'])) {
                              $allowed[] = $t['name'];
                          }
                      }
                      if (empty($allowed)) {
                          return true;
                      }
              
                      $entries = scandir($dir);
                      if (!is_array($entries)) {
                          return true;
                      }
              
                      foreach ($entries as $d) {
                          // Ne JAMAIS toucher à l'original (ex: 130.jpg)
                          if (preg_match('/^[0-9]+\.jpe?g$/i', $d)) {
                              continue;
                          }
              
                          // Supprimer uniquement :
                          //  - id[-id_product]-<type>.jpg|webp
                          //  - <lang>-default-<type>.jpg|webp
                          foreach ($allowed as $name) {
                              $reBase = '/^[0-9]+-'.($product ? '[0-9]+-' : '').preg_quote($name,'/').'\.(?:jpe?g|webp)$/i';
                              $reLang = '/^[a-z]{2}-default-'.preg_quote($name,'/').'\.(?:jpe?g|webp)$/i';
              
                              if (preg_match($reBase, $d) || preg_match($reLang, $d)) {
                                  $full = $dir.$d;
                                  if (file_exists($full)) {
                                      @unlink($full);
                                  }
                                  break;
                              }
                          }
                      }
              
                      // pas de nettoyage récursif global (source de suppression en cascade)
                      // if ($product) { $this->cleanAllImages(_PS_PROD_IMG_DIR_); }
              
                      return true;
                  }
              
                  /**
                   * Par sécurité, si du code legacy appelle encore cleanAllImages(),
                   * on le rend inoffensif (pas de suppression récursive).
                   */
                  public function cleanAllImages($path)
                  {
                      // TRACE facultative
                      // @error_log("[IMG] cleanAllImages bypassed in ".__FILE__."\n", 3, _PS_ROOT_DIR_."/var/log/img_trace.log");
                      return true;
                  }
              }
              

              et de Image.php

              <?php
              /**
               * Override SAFE de la classe Image (suppression non-destructive)
               * - Ne touche jamais à l’original id.jpg
               * - Ne supprime que les tailles de l’image courante
               * - Pas de nettoyage récursif / pas de prune des dossiers parents
               */
              class Image extends ImageCore
              {
                  /**
                   * Journalise l’appel puis délègue au parent.
                   * Le parent appellera $this->deleteImage(), qui est overridée ci-dessous.
                   */
                  public function delete()
                  {
                      @file_put_contents(
                          _PS_ROOT_DIR_.'/var/log/img_trace.log',
                          date('c')." Image::delete id_image={$this->id} id_product={$this->id_product}\n",
                          FILE_APPEND
                      );
                      // On laisse le parent gérer la partie BDD (ps_image*, position, cover…)
                      return parent::delete();
                  }
              
                  /**
                   * Suppression des fichiers sur disque (override SAFE)
                   * $force_delete est ignoré volontairement pour NE PAS supprimer l’original.
                   */
                  public function deleteImage($force_delete = false)
                  {
                      // Chemin de base sans extension, ex: /img/p/1/3/0/0/1300
                      $basePath = $this->getPathForCreation();
                      $dir      = dirname($basePath).'/';
              
                     
              // 1) SUPPRIMER l’original et ses variantes (jpg, png, webp)
              $exts = array('jpg','png','webp');
              foreach ($exts as $ext) {
                  $orig = $basePath.'.'.$ext;
                  if (file_exists($orig)) {
                      @unlink($orig);
                      @file_put_contents(
                          _PS_ROOT_DIR_.'/var/log/img_trace.log',
                          date('c')." unlink original: ".$orig."\n",
                          FILE_APPEND
                      );
                  }
              }
                      // 2) Supprimer UNIQUEMENT les déclinaisons de CETTE image
                      $types = ImageType::getImagesTypes('products', false);
                      $exts  = array('jpg','webp'); // on couvre les 2 familles
                      foreach ($types as $t) {
                          $name = stripslashes($t['name']);
                          foreach ($exts as $ext) {
                              $file = $basePath.'-'.$name.'.'.$ext;
                              if (file_exists($file)) {
                                  @unlink($file);
                                  @file_put_contents(
                                      _PS_ROOT_DIR_.'/var/log/img_trace.log',
                                      date('c')." unlink variant: ".$file."\n",
                                      FILE_APPEND
                                  );
                              }
                              // variante 2x si jamais utilisée
                              $file2x = $basePath.'-'.$name.'2x'.'.'.$ext;
                              if (file_exists($file2x)) {
                                  @unlink($file2x);
                                  @file_put_contents(
                                      _PS_ROOT_DIR_.'/var/log/img_trace.log',
                                      date('c')." unlink variant2x: ".$file2x."\n",
                                      FILE_APPEND
                                  );
                              }
                          }
                      }
              
                      // 3) NE PAS remonter dans l’arbo, NE PAS pruner les dossiers parents
                      //    (donc pas de rmdir(), pas de cleanAllImages())
              
                      // On considère l’opération disque OK même si certaines variantes n’existaient pas.
                      return true;
                  }
              }
              
              

              Je ne suis hélas pas dév PHP, je peux y apporter des changements, mais pour créer des overrides, j'ai préféré me faire aider. Car pour la gestion du site, cela commençait à devenir vraiment compliqué, ces disparitions d'images. Pour les anciennes, je pouvais les récupérer du clone d'origine. Mais pour les nouvelles, on est obligé de les renvoyer. Avec, en plus, un souci au niveau de la bdd vu que les anciennes assos img/prod n'étaient pas supprimées.

              Pour les erreurs 500, si elles ne peuvent être liées à un script auto de régénération, alors d'où peuvent-elles venir ? J'attends un avis de spécialiste demain chez O2Switch car ni eux, ni moi, n'arrivons à trouver une piste 😞

              1 réponse Dernière réponse Répondre Citer 0
              • C Hors-ligne
                camille
                dernière édition par

                Par contre, est-ce normal que, d'office, le bouton "Effacer les anciennes images" reste actif ? J'ai beau le mettre sur non, quand je reviens sur la page il est de nouveau actif.

                1 réponse Dernière réponse Répondre Citer 0
                • eoliaE Hors-ligne
                  eolia
                  dernière édition par

                  Le problème est sur la fonction Tools::cleanDirectory($this->image_dir.$this->getImgFolder()); rien d'autre et c'est en cours de résolution.
                  Pour le bouton "Effacer les images" (actif par défaut) si celui-ci n'est pas actif il ne se passera rien pour les produits lorsque vous cliquerez sur "Regénérer", seules les miniatures manquantes seront générées lorsqu'elles seront appelées.

                  Créateur de PhenixSuite. Pour plus d'infos : https://eoliashop.com

                  1 réponse Dernière réponse Répondre Citer 0
                  • eoliaE Hors-ligne
                    eolia
                    dernière édition par

                    commentez la ligne 665 de Image.php ( //Tools::cleanDirectory($this->image_dir.$this->getImgFolder()); ) en attendant le patch. Les répertoires vides ne seront pas nettoyés mais ce n'est pas grave pour l'instant.

                    Créateur de PhenixSuite. Pour plus d'infos : https://eoliashop.com

                    C 1 réponse Dernière réponse Répondre Citer 0
                    • C Hors-ligne
                      camille
                      dernière édition par

                      Merci Eolia,
                      J'attends donc la résolution 🙂 en attendant l'override évite de nouvelles disparitions.
                      Me trompe-je ou, d'habitude, il n'est pas activé par défaut ? Justement pour éviter de tout régénérer si on oublie de le désactiver pour quelques vignettes manquantes ?
                      Et est-ce que le script automatique prend en compte cela et donc régénèrerait toutes les vignettes quand on ajoute une image ? Car les erreurs 500 ont quand même l'air d'être assez reliées aux moments où on ajoute des images ...

                      1 réponse Dernière réponse Répondre Citer 0
                      • eoliaE Hors-ligne
                        eolia
                        dernière édition par

                        Je me répète mais Phenix ne regénère jamais toutes les miniatures (ce qui provoquait souvent des erreurs 500).
                        Si vous cliquez sur regénérer en ayant coché "supprimer les images" seules les miniatures sont supprimées. L'image de base jpg reste seule.

                        Lorsque vous naviguerez sur le FO les images manquantes seront regénérées à la volée pour le ou les produits en cours de visualisation.

                        Créateur de PhenixSuite. Pour plus d'infos : https://eoliashop.com

                        C 1 réponse Dernière réponse Répondre Citer 0
                        • C Hors-ligne
                          camille @eolia
                          dernière édition par

                          @eolia merci, je vais tester ça sur le dev

                          1 réponse Dernière réponse Répondre Citer 0
                          • C Hors-ligne
                            camille @eolia
                            dernière édition par

                            @eolia ok merci, je voulais juste m'en assurer car je suis toutes les pistes qui pourraient m'expliquer la fréquence des erreurs 500, avec perte de connexion à la bdd. Les logs sont absolument silencieux là-dessus...

                            1 réponse Dernière réponse Répondre Citer 0
                            • eoliaE Hors-ligne
                              eolia
                              dernière édition par

                              Function à remplacer dans Image.php:

                                  public function deleteImage($force_delete = false)
                                  {
                                      if(!$this->id) {
                                          return false;
                                      }
                              
                                      $parent_dir = $this->image_dir.$this->getImgFolder();
                                      if(Configuration::get('PS_LEGACY_IMAGES')) {
                                          $files_to_delete = array();
                                          // Delete base image
                                          if(file_exists($this->image_dir.$this->getExistingImgPath().'.'.$this->image_format)) {
                                              @unlink($this->image_dir.$this->getExistingImgPath().'.'.$this->image_format);
                                          }
                                          // Delete auto-generated images
                                          $image_types = ImageType::getImagesTypes();
                                          foreach($image_types as $image_type) {
                                              $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'.'.$this->image_format;
                                              $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'.webp';
                                              if(Configuration::get('WATERMARK_HASH')) {
                                                  $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'-'.Configuration::get('WATERMARK_HASH').'.'.$this->image_format;
                                                  $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-'.$image_type['name'].'-'.Configuration::get('WATERMARK_HASH').'.webp';
                                              }
                                          }
                                          // Delete watermark image
                                          $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-watermark.'.$this->image_format;
                                          $files_to_delete[] = $this->image_dir.$this->getExistingImgPath().'-watermark.webp';
                                          // Delete index.php
                                          $files_to_delete[] = $parent_dir.'index.php';
                                          foreach ($files_to_delete as $file) {
                                              if (file_exists($file) && !@unlink($file)) {
                                                  return false;
                                              }
                                          }
                                      }
                                      else {
                                          if(is_dir($parent_dir)) {
                                              $files = glob($parent_dir.'*');
                                              foreach($files as $file) {
                                                  if(is_file($file)) {
                                                      unlink($file);
                                                  }
                                              }
                                          }
                                      }
                              
                                      self::deleteTempImages($this->id_product);
                              
                                      // Delete the image folder if empty
                                      if(is_dir($parent_dir)) {
                                          $delete_folder = true;
                                          foreach(scandir($parent_dir) as $file) {
                                              if($file != '.' && $file != '..') {
                                                  $delete_folder = false;
                                                  file_put_contents($parent_dir.'index.php', Tools::getDefaultIndexContent($path));
                                                  break;
                                              }
                                          }
                                      }
                                      if(isset($delete_folder) && $delete_folder) {
                                          @rmdir($this->image_dir.$this->getImgFolder());
                                      }
                              
                                      return true;
                                  }
                              

                              Créateur de PhenixSuite. Pour plus d'infos : https://eoliashop.com

                              1 réponse Dernière réponse Répondre Citer 0
                              • doekiaD Hors-ligne
                                doekia @camille
                                dernière édition par

                                @camille Bravo pour nous avoir donné les pistes d'un problème dont nous n'arrivions pas à reproduire le scénario. @Eolia vous a donné un correctif et nous allons rendre celui-ci encore plus robuste sur la version à venir. Si je puis me permettre, évitez de penser qu'un outils comme ChatGPT peut vous sauver si vous n'avez pas suffisamment de connaissance sur un sujet. Les IA sont impressionnante mais quasiment exclusivement sur des sujets des milliers/millions de fois vu et revu dans leurs apprentissages. En dehors de ces cas, les IA font 60% bien 30% bof et 10% BS.
                                Encore un fois ce n'est pas une critique, juste qu'il faut être conscient du problème. Des outils très puissant mais qui requièrent une connaissance amont pour remettre en cause leurs "output"

                                Encore merci d'avoir ciblé le problème avec vos tests clairement documentés.

                                https://store.enter-solutions.com modules, support et assistance.

                                Je précise que je n'ai pas fait ni Paco-Rabane, ni Poudlard 2ème langue - je ne suis ni devin, ni magicien.
                                Fournissez un maximum d'information dans vos questions, version exacte du coeur et de vos modules, si besoin un peu d'histoire sur votre shop et vos recherches, les modules tiers installés, ...

                                Si mon intervention vous a aidé, n'hésitez pas à me remercier: https://ko-fi.com/A153227G

                                1 réponse Dernière réponse Répondre Citer 1
                                • C Hors-ligne
                                  camille
                                  dernière édition par

                                  Merci Eolia, je vais de ce pas tester cela sur le dev.

                                  Doekia, vous avez tout à fait raison concernant l'IA. Mais, d'une part, je voulais être honnête en disant que je m'étais fait aider par elle. Et d'autre part, ce problème d'images devenait vraiment très ch..ant à gérer. N'ayant plus eu de nouvelles depuis mon message du 21 juillet, je ne savais pas que vous travailliez dessus. Je pouvais être la seule à qui cela arrivait, vu que Herve_02 n'a plus rien dit. Donc ce we j'ai fouillé partout pour arriver à trouver la logique de cette perte d'images, la reproduire sur un site de test. J'ai cherché dans les class et controllers ce qui jouait sur la suppression et lui ai fourni les functions en lui expliquant ce qui se passait. Il m'a indiqué pourquoi la suppression d'une image supprimait également ses "soeurs". On était dimanche, PhenixSuite est un travail bénévole, je ne voulais pas enquiquiner les gens, mais il fallait que je trouve une solution rapidement. Et l'IA, on a moins mauvaise conscience de l'embêter le dimanche :-). J'ai testé plusieurs fois ses propositions jusqu'à ce que cela fasse exactement ce que je voulais. Et là encore, j'ai testé sur deux clones du site. Je ne suis pas dev PHP mais je crée des sites depuis plusieurs années, à force de réparer certains bugs grâce à l'aide des forums, j'arrive à comprendre le PHP dans la mesure du possible. Le code qu'il m'a fourni me semblait ok. Mais si vous voyez des erreurs, ce serait gentil de me les indiquer. A 64 ans, j'aime continuer à apprendre 🙂

                                  1 réponse Dernière réponse Répondre Citer 0
                                  • eoliaE Hors-ligne
                                    eolia
                                    dernière édition par

                                    C'est ok avec la mise à jour de la fonction delete() ?

                                    Créateur de PhenixSuite. Pour plus d'infos : https://eoliashop.com

                                    1 réponse Dernière réponse Répondre Citer 0
                                    • Premier message
                                      Dernier message
                                    bug
                                    26 sujets
                                    1.6
                                    24 sujets
                                    front-office
                                    11 sujets
                                    1.5
                                    8 sujets
                                    1.7
                                    5 sujets
                                    système
                                    4 sujets
                                    administration
                                    3 sujets
                                    hack
                                    3 sujets
                                    module
                                    3 sujets
                                    performance
                                    3 sujets
                                    smtp
                                    3 sujets
                                    transporteurs
                                    3 sujets
                                    dashboard
                                    2 sujets
                                    https
                                    2 sujets
                                    paypal
                                    2 sujets
                                    promotions
                                    2 sujets