web-dev-qa-db-fra.com

ZIP toutes les images affichées dans une [galerie] et offre comme lien de téléchargement

J'aimerais offrir à mes visiteurs la possibilité de télécharger toute la galerie de photos (affichée sur des pages [galerie] dédiées) sous forme de fichier Zip affiché au bas de chaque page de la galerie. - L'image en taille réelle devra être incluse.

David Walsh a donné du code dans son article ici pour compresser des fichiers, mais je ne parviens pas à l’intégrer aux fonctions Wordpress.

Je suis conscient qu'il existe un plugin de téléchargement de galerie NextGEN, mais je ne suis pas en mesure de l'utiliser car j'utilise les fonctions natives de la galerie wordpress.

Une question similaire avec une alternative (méthode manuelle) pour compléter ce qui précède peut être trouvée ici: Plugin pour télécharger des fichiers multimédia joints?

Toute aide serait grandement appréciée. Merci.

13
Paul Thomson

Vous devez d'abord obtenir les images. Comment obtenir toutes les images d'une galerie est décrit ici .

WordPress utilise deux classes pour décompresser des fichiers. Le PHP bilt dans ZipArchive() (utilisation voir David Walsh). Et PclZip , vous pouvez trouver cette classe dans wp-admin/includes/class-pclzip.php. Si vous avez des problèmes avec ZipArchive(), essayez la classe PclZip.

Maintenant, il ne vous reste plus qu'à les coller ensemble. Peut-être que je pourrai poster un exemple de code plus tard, actuellement je ne suis pas à mon bureau.

Mise à jour

Votre question peut être scindée en deux parties. Le premier est d'obtenir toutes les images d'une galerie. Le second est de compresser les images et d'envoyer le fichier Zip.
Je n’expliquerai que la première partie, en obtenant toutes les images d’une galerie, car la compression des fichiers est un peu décalée.

Peut-être existe-t-il d'autres solutions, mais dans cet exemple, je remplace le shortcode de la galerie d'origine par un autre personnalisé pour obtenir les images. La raison en est que WordPress a un peu changé les galeries en v3.5.
Avant 3.5, les images d’une galerie sont des pièces jointes à la publication. Après 3.5, les images sont transmises au shortcode en tant qu'attribut. Depuis WP3.5, nous ne pouvons plus obtenir les images attachées d’un message, nous devons récupérer la liste à partir des attributs de shortcode. Ma stratégie consiste à remplacer le shortcode original par un shortcode personnalisé, à saisir les attributs et à appeler le shortcode original pour obtenir la sortie de la galerie.

Toutes les choses liées à la galerie sont dans une classe. Pour créer un fichier Zip, nous pouvons utiliser une autre classe qui prend en entrée la sortie de la classe gallery. Commençons par une classe et un constructeur simple.

class GalleryZip
{
    private static $instance = null;

    public static $images = array();

    public static function get_instance() {
        if ( ! session_id() )
          session_start();

        if ( null === self::$instance )
            self::$instance = new self();

        return self::$instance;
    }

    private final function __construct() {
        remove_shortcode( 'gallery' );
        add_shortcode( 'gallery', array( __CLASS__, 'gallery_Zip_shortcode' ) );
    }
}

Nous appellerons la méthode get_instance() plus tard dans le plugin avec le hook plugins_loaded. Dans le constructeur, nous supprimons le shortcode d'origine et le remplaçons par notre shortcode personnalisé gallery_Zip_shortcode(). Maintenant nous avons besoin du rappel du shortcode

public static function gallery_Zip_shortcode( $atts ) {

    $post = get_post();

    if ( ! function_exists( 'gallery_shortcode' ) )
      require_once ABSPATH . 'wp-includes/media.php';

    self::get_gallery_images_from_shortcode( $post->ID, $atts );
    $output = gallery_shortcode( $atts );

    $gallery_id = count( self::$images[$post->ID] ) - 1;

    $link = sprintf( '<div><a href="#" gallery-id="%d" post-id="%d" class="gallery-Zip">%s</a></div>', $gallery_id, $post->ID, __( 'Get as Zip' ) );
    $output .= $link;

    return $output;

}

La première chose dans cette méthode est d’obtenir la publication car nous avons besoin de l’ID de publication. Ensuite, nous incluons wp-includes/media.php, ce fichier contient la fonction de rappel pour le shortcode de la galerie originale. Nous appelons maintenant une méthode pour obtenir un tableau avec toutes les images, créons la sortie de la galerie en appelant le rappel de la galerie d'origine, créons un lien et ajoutons le lien à la sortie de la galerie. Les images elles-mêmes, respectivement les chemins d'accès aux images, sont stockées dans la variable de classe $images, nous avons besoin de ce tableau ultérieurement.
La variable de classe $image contient une entrée pour chaque publication avec une galerie. Nous pouvons donc utiliser la fonction sur Frontpage ou en vue unique. Chaque entrée contient un tableau pour chaque galerie, car il peut y avoir plus d'une galerie dans chaque publication.

Le noyau du plugin est la méthode pour obtenir les images du shortcode.

protected static function get_gallery_images_from_shortcode( $id, $atts ) {

    // use the post ID if the attribute 'ids' is not set or empty
    $id = ( ! isset( $atts['ids'] ) || empty( $atts['ids'] ) ) ?
        (int) $id : $atts['ids'];

    $exclude = ( isset( $atts['exclude'] ) && ! empty( $atts['exclude'] ) ) ?
        $atts['exclude'] : '';

    if ( ! isset( self::$images[$id] ) || ! is_array( self::$images[$id] ) )
        self::$images[$id] = array();

    $images = self::get_gallery_images( $id, $exclude );

    array_Push( self::$images[$id], $images );

    return $images;

}

Au début, nous décidons s’il s’agit d’un message simple ou d’une liste d’ID de poste. S'il s'agit d'une liste d'ID de publication, nous gérons une galerie à partir de WP3.5 +. Après cela, nous devons gérer l'attribut exclude. Après avoir configuré toutes les variables, nous pouvons enfin obtenir les images de la galerie. Les images reçues seront insérées dans la classe var $images pour une utilisation ultérieure.

protected static function get_gallery_images( $id, $exclude ) {
    $images     = array();
    $query_args = array(
            'post_status'    => 'inherit',
            'post_type'      => 'attachment',
            'post_mime_type' => 'image',
    );

    // handle gallery WP3.5+
    // if $id contains an comma, it is a list of post IDs
    if ( false !== strpos( $id, ',' ) ) {
        $query_args['include'] = $id;
    } elseif ( ! empty( $exclude ) ) {
        // handle excluding posts
        $query_args['post_parent'] = $id;
        $query_args['exclude']     = $exclude;
    } else {
        // handle gallery before WP3.5
        $query_args['post_parent'] = $id;
    }

    $attachments = get_posts( $query_args );

    $img_sizes = array_merge( array( 'full' ), get_intermediate_image_sizes() );

    $img_size = ( in_array( self::IMAGE_SIZE, $img_sizes ) ) ?
            self::IMAGE_SIZE : 'full';

    foreach ( $attachments as $key => $post ) {
        $img = wp_get_attachment_image_src( $post->ID, $img_size, false, false );
        $images[] = sprintf( '%s/%s', dirname( get_attached_file( $post->ID ) ), basename( $img[0] ) );
    }

    return $images;
}

C'est l'or du plugin. Configurez simplement un tableau avec des arguments de requête, obtenez les pièces jointes avec get_posts() et passez en revue les pièces jointes récupérées. Pour gérer différentes tailles, nous obtenons l'image de la pièce jointe et la bande de l'URL. À partir du fichier joint, nous prenons le chemin et le plaçons avec le nom de fichier. Dans le tableau $images figurent désormais toutes les images et leurs chemins de la galerie.

Fondamentalement, votre question reçoit une réponse à ce stade. Mais vous voulez aussi créer un fichier Zip à partir des images. Vous pouvez créer un fichier Zip à partir du tableau $images dans la dernière méthode. Mais cette méthode est appelée à chaque fois qu'une galerie est affichée et la création d'un fichier Zip peut prendre un certain temps. Peut-être que personne ne demanderait le fichier Zip que vous avez créé ici, c'est un gaspillage de ressources.

Comment pouvons-nous faire mieux? Vous souvenez-vous que j'ai mis toutes les images dans la variable de classe $images? Nous pouvons utiliser cette classe var pour une requête ajax. Mais une demande ajax est juste un autre chargement de page et nous ne pouvons accéder aux images que lorsque la sortie de la galerie est créée. Nous devons enregistrer nos images dans un endroit où nous pouvons y accéder même après une autre demande de page.
Dans cet exemple, j'utilise une variable de session pour stocker le tableau avec des images. Une variable de session est accessible même après un autre rechargement de page. Pour stocker les images, j'enregistre une méthode avec le shutdownhook. Une fois que WordPress a terminé le rendu de la page, le hook shutdown sera appelé. À ce stade, nous aurions dû collecter toutes les images de toutes les galeries affichées. Nous stockons simplement les images et pouvons y accéder dans une requête ajax.

Lorsque la demande ajax est déclenchée, nous rappelons la session var et créons un fichier Zip à partir des données. Mais c'est un peu hors sujet pour cette question.

J'ai créé un répertoire sur GitHub avec le code complet du plugin. J'espère que cela vous oriente dans la bonne direction.

13
Ralf912

J'aime l'idée du plugin de Ralf pour pouvoir télécharger une galerie entière en une fois, mais je n'ai pas réussi à la faire fonctionner. J'ai mis au point une solution de contournement qui convient à nos besoins. La méthode consiste à remplacer la galerie native WP par la vôtre, que vous placez à la fin du fichier functions.php de votre thème ET ajoutez le fichier suivant, nommé download.php dans le dossier du thème actif. Dans la galerie personnalisée, un lien sous le fichier appelle le fichier download.php, ce qui force automatiquement le téléchargement de votre fichier sur le disque dur. J'ai testé cela sur les dernières versions de Chrome, Firefox et Safari et cela fonctionne bien. Avons utilisé le thème Twenty Twelve, mais aucune raison pour laquelle il ne devrait pas fonctionner aussi.

a) Ajoutez ce qui suit à la fin de functions.php. Ceci est simplement tiré de media.php

remove_shortcode('gallery');
function gallery_with_download_links($attr) {
    $post = get_post();
    static $instance = 0;
    $instance++;
    if ( ! empty( $attr['ids'] ) ) {
        // 'ids' is explicitly ordered, unless you specify otherwise.
        if ( empty( $attr['orderby'] ) )
            $attr['orderby'] = 'post__in';
        $attr['include'] = $attr['ids'];
    }
    // Allow plugins/themes to override the default gallery template.
    $output = apply_filters('post_gallery', '', $attr);
    if ( $output != '' )
        return $output;
    // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
    if ( isset( $attr['orderby'] ) ) {
        $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
        if ( !$attr['orderby'] )
            unset( $attr['orderby'] );
    }

    extract(shortcode_atts(array(
        'order'      => 'ASC',
        'orderby'    => 'menu_order ID',
        'id'         => $post->ID,
        'itemtag'    => 'dl',
        'icontag'    => 'dt',
        'captiontag' => 'dd',
        'columns'    => 3,
        'size'       => 'thumbnail',
        'include'    => '',
        'exclude'    => ''
    ), $attr));

    $id = intval($id);
    if ( 'Rand' == $order )
        $orderby = 'none';

    if ( !empty($include) ) {
        $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );

        $attachments = array();
        foreach ( $_attachments as $key => $val ) {
            $attachments[$val->ID] = $_attachments[$key];
        }
    } elseif ( !empty($exclude) ) {
        $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    } else {
        $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    }

    if ( empty($attachments) )
        return '';

    if ( is_feed() ) {
        $output = "\n";
        foreach ( $attachments as $att_id => $attachment )
            $output .= wp_get_attachment_link($att_id, $size, true) . "\n";
        return $output;
    }

    $itemtag = tag_escape($itemtag);
    $captiontag = tag_escape($captiontag);
    $icontag = tag_escape($icontag);
    $valid_tags = wp_kses_allowed_html( 'post' );
    if ( ! isset( $valid_tags[ $itemtag ] ) )
        $itemtag = 'dl';
    if ( ! isset( $valid_tags[ $captiontag ] ) )
        $captiontag = 'dd';
    if ( ! isset( $valid_tags[ $icontag ] ) )
        $icontag = 'dt';

    $columns = intval($columns);
    $itemwidth = $columns > 0 ? floor(100/$columns) : 100;
    $float = is_rtl() ? 'right' : 'left';

    $selector = "gallery-{$instance}";

    $gallery_style = $gallery_div = '';
    if ( apply_filters( 'use_default_gallery_style', true ) )
        $gallery_style = "
        <style type='text/css'>
            #{$selector} {
                margin: auto;
            }
            #{$selector} .gallery-item {
                float: {$float};
                margin-top: 10px;
                text-align: center;
                width: {$itemwidth}%;
            }
            #{$selector} img {
                border: 2px solid #cfcfcf;
            }
            #{$selector} .gallery-caption {
                margin-left: 0;
            }
        </style>
        <!-- see gallery_shortcode() in wp-includes/media.php -->";
    $size_class = sanitize_html_class( $size );
    $gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
    $output = apply_filters( 'gallery_style', $gallery_style . "\n\t\t" . $gallery_div );

    $i = 0;
    foreach ( $attachments as $id => $attachment ) {
        $link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, $size, false, false) : wp_get_attachment_link($id, $size, true, false);

        $output .= "<{$itemtag} class='gallery-item'>";
        $output .= "
            <{$icontag} class='gallery-icon'>
                $link
            </{$icontag}>";
        if ( $captiontag && trim($attachment->post_excerpt) ) {
            $output .= "
                <{$captiontag} class='wp-caption-text gallery-caption'>
                " . wptexturize($attachment->post_excerpt) . "
                </{$captiontag}>";
        }
// This is my addon which outputs a link to download the file through download.php . NB your file uri will be public! 
        $output .= '<br/ ><a href="'.get_template_directory_uri().'/download.php?file='.get_attached_file( $id ).'">Download image</a>';
        $output .= "</{$itemtag}>";
        if ( $columns > 0 && ++$i % $columns == 0 )
            $output .= '<br style="clear: both" />';
    }

    $output .= "
            <br style='clear: both;' />
        </div>\n";

    return $output;
}
add_shortcode( 'gallery' , 'gallery_with_download_links' );

b) Copiez et collez le texte suivant dans un fichier appelé download.php dans le répertoire de base du thème.

<?php
$file = $_GET['file'];
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>

c) N'oubliez pas de créer un lien vers le fichier dans la galerie !! Important!

0
Sam Edgecombe