Obiettivo: leggere tutti i prodotti del negozio su Magento 2 e eliminare tutte le immagini duplicate per ciascun prodotto.
In Magento 2 può capitare di ritrovarsi prodotti con immagini duplicate, specialmente a seguito di una importazione di dati. Inoltre sembra che ci siano anche dei bug, o almeno ci sono stati nelle diverse versioni, che producevano questo fastidioso problema.
Quello che vogliamo fare è creare una pagina correggi_immagini.php, nella root del sito, richiamando la quale percorreremo tutti i prodotti in cerca di immagini duplicate e le elimineremo.
Come piccolo accorgimento voglio che lo script sia eseguito solo a seguito di una specifica chiamata GET sulla pagina, per esempio /correggi_immagini.php?auth=1234567890abcdefghilmnopqrstuv
Al posto di 1234567890abcdefghilmnopqrstuv
raccomando di sostituire un codice sufficientemente complesso.
Nei commenti ho inserito i dettagli sullo sviluppo dello script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
use Magento\Framework\App\Bootstrap; if( $_GET['auth'] == '1234567890abcdefghilmnopqrstuv' ) { // includiamo le funzionalità di Magento require __DIR__ . '/app/bootstrap.php'; $bootstrap = Bootstrap::create(BP, $_SERVER); $obj = $bootstrap->getObjectManager(); // questo passaggio, sebbene un po' assurdo, è necessario per stabilire l'area nella quale si lavora // le modifiche al catalogo devono avvenire, per qualche irrazionale ragione, dentro ad una sessione $stato = $obj->get('Magento\Framework\App\State'); $stato->setAreaCode('frontend'); // creiamo il collegamento con l'istanza dell'object manager // con questo potremo richiamare tutte le altre istanze del framework $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // creiamo il collegamento al catalogo $catalogo = $objectManager->create('\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory'); // creiamo il collegamento alle cartelle, questo ci servirà per trovare il percorso assoluto dei file $cartelle = $objectManager->get('\Magento\Framework\App\Filesystem\DirectoryList'); // leggiamo tutta la collezione $collezione = $catalogo->create(); $collezione->addAttributeToSelect('*'); $collezione->addMediaGalleryData(); // questo passaggio è importante per includere la galleria nell'elenco dei prodotti // controlliamo tutta la collezione foreach( $collezione as $prodotto ) { // nel mio caso voglio controllare SOLO i prodotti raggruppati, ovvero quelli contenenti altre variazioni // questo IF si può anche omettere, se si vogliono controllare TUTTI i prodotti if( $prodotto->getTypeId() == 'grouped' ) { // variabile di controllo se avrò fatto delle modifiche da salvare $modificato = false; // utilizzo la product repository per salvare i prodotti $productRepository = $objectManager->create('Magento\Catalog\Api\ProductRepositoryInterface'); // creo due vettori con gli MD5 delle immagini lette $md5imgs = array(); // qui mettiamo gli MD5 $md5files = array(); // qui la relazione tra MD5 e ID dell'immagine, dopo vediamo perché // leggiamo tutte le immagini $imgs = $prodotto->getMediaGalleryEntries(); // se $imgs è un vettore lo percorriamo tutto // occhio perché $imgs non è visualizzabile sempre con print_r if( is_array( $imgs ) ) foreach( $imgs as $ik => $iv ) { // costruiamo il percorso assoluto al file $path = $cartelle->getPath('media') . '/catalog/product' . $iv->getFile(); // se il file esiste procediamo if( file_exists( $path ) ) { // leggiamo l'immagine e creiamo l'md5 corrispondente $md5 = md5(file_get_contents($path)); // se l'md5 si trova nel vettore allora eliminiamo l'immagine if( in_array($md5,$md5imgs) ) { // normalmente basterebbe il seguente comando commentato //unset($imgs[$ik]); // ci sono casi in cui, però, l'immagine da eliminare è impostata come immagine principale // questo succede di solito a seguito di importazioni in CSV o tramite Api // allora elimineremo l'immagine trovata in precedenza, in caso contrario il salvataggio // potrebbe sembrare andare a vuoto unset($imgs[$md5files[$md5]]); // segnalo che ho apportato delle modifiche $modificato = true; } else { // se l'immagine non si trova tra gli md5 la aggiungiamo $md5imgs[] = $md5; $md5files[$md5]=$ik; } } } // se ci sono state modifiche le applico if( $modificato ) { // reimposto il vettore delle immagini $prodotto->setMediaGalleryEntries($imgs); // salvo il tutto $productRepository->save($prodotto); } } } } |