Comprima todas las imágenes que se muestran en una [galería] y ofrézcalas como enlace de descarga

13

Me gustaría ofrecer a mis visitantes la opción de descargar toda la galería de fotos (que se muestra en páginas dedicadas [galería]) como un archivo ZIP que se muestra en la parte inferior de cada página de la galería. - La imagen a tamaño completo tendrá que ser incluida.

David Walsh ha dado un código en su publicación aquí para comprimir archivos, pero tengo problemas para integrarlo con las funciones de Wordpress.

Soy consciente de que hay un complemento de descarga de la galería NextGEN, pero no estoy en condiciones de usarlo, ya que utilizo las funciones nativas de la galería de WordPress.

Aquí puede encontrar una pregunta similar con una alternativa (método manual) para completar lo anterior: ¿ Complemento para descargar archivos multimedia adjuntos?

Cualquier ayuda sería muy apreciada. Gracias.

Paul Thomson
fuente
¿Qué quieres decir con páginas dedicadas de la galería?
NoBugs
publicaciones estándar que SOLO muestran el shortcode de la galería [gallery columnas = "4" link = "file"] y ningún otro contenido en la página. Incluí eso en la descripción solo en caso de que ayudara a los desarrolladores.
Paul Thomson

Respuestas:

14

Primero tienes que obtener las imágenes. Aquí se describe cómo obtener todas las imágenes de una galería .

WordPress usa dos clases para descomprimir archivos. El PHP bilt in ZipArchive()(uso ver David Walsh). Y PclZip , puedes encontrar esta clase en wp-admin/includes/class-pclzip.php. Si tienes problemas con ZipArchive()probar la clase PclZip.

Ahora solo tienes que pegar ambos juntos. Tal vez pueda publicar un código de muestra más tarde, actualmente no estoy en mi escritorio.

Actualizar

Su pregunta se puede dividir en dos partes. El primero es obtener todas las imágenes de una galería. El segundo es comprimir las imágenes y enviar el archivo zip.
Solo explicaré la primera parte, obtener todas las imágenes de una galería, porque comprimir los archivos es un poco fuera de tema.

Quizás haya otras soluciones, pero en este ejemplo, reemplazo el shortcode de la galería original por uno personalizado para obtener las imágenes. La razón es que WordPress cambió un poco las galerías en v3.5.
Antes de 3.5, las imágenes de una galería son archivos adjuntos de la publicación. Después de 3.5, las imágenes se pasan al shortcode como un atributo. Desde WP3.5 ya no podemos obtener las imágenes adjuntas de una publicación, tenemos que obtener la lista de los atributos de código corto. Mi estrategia es reemplazar el shortcode original con un shortcode personalizado, tomar los atributos y llamar al shortcode original para obtener la salida de la galería.

Todas las cosas relacionadas con la galería están dentro de una clase. Para crear un archivo zip, podemos usar otra clase que tome como entrada la salida de la clase de la galería. Comencemos con una clase y un constructor 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' ) );
    }
}

Llamaremos al método get_instance()más adelante en el complemento con el gancho plugins_loaded. En el constructor, eliminamos el shortcode original y lo reemplazamos con nuestro shortcode personalizado gallery_zip_shortcode(). Ahora necesitamos la devolución de llamada 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;

}

Lo primero en este método es obtener la publicación porque necesitamos la ID de la publicación. De lo que incluimos wp-includes/media.php, este archivo contiene la función de devolución de llamada para el shortcode de la galería original. Ahora llamamos a un método para obtener una matriz con todas las imágenes, crear la salida de la galería llamando a la devolución de llamada de la galería original, crear un enlace y agregar el enlace a la salida de la galería. Las imágenes en sí, respectivamente, las rutas a las imágenes, se almacenan en la variable de clase $images, necesitamos esta matriz más adelante.
La variable de clase $imagecontiene una entrada para cada publicación con una galería, por lo que podemos usar la función en la página principal o en una vista única. Cada entrada contiene una matriz para cada galería, porque puede haber más de una galería en cada publicación.

El núcleo del complemento es el método para obtener las imágenes del 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;

}

Al principio decidimos si es una publicación única o una lista de ID de publicaciones. Si se trata de una lista de ID de publicaciones, manejamos una galería de WP3.5 +. Después de eso, tenemos que manejar el excludeatributo. Después de configurar todas las variables, finalmente podemos obtener las imágenes de la galería. Las imágenes recuperadas se insertarán en la clase var $imagespara su uso posterior.

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;
}

Este es el oro del complemento. Simplemente configure una matriz con argumentos de consulta, obtenga los archivos adjuntos get_posts()y recorra los archivos adjuntos recuperados. Para manejar diferentes tamaños, obtenemos la imagen adjunta y la tira de la url. Desde el archivo adjunto, tomamos la ruta y la juntamos con el nombre del archivo. En la matriz $imagesahora están todas las imágenes y sus patrones de la galería.

Básicamente su pregunta es respondida en este punto. Pero también desea crear un archivo zip a partir de las imágenes. Puede crear un archivo zip desde la matriz $imagesen el último método. Pero este método se llama cada vez que se muestra una galería y la creación de un archivo zip puede llevar un tiempo. Quizás nadie solicite el archivo zip que creó aquí, esto es un desperdicio de recursos.

¿Cómo podemos hacerlo mejor? ¿Recuerdas que puse todas las imágenes en la variable de clase $images? Podemos usar esta clase var para una solicitud ajax. Pero una solicitud ajax es solo otra carga de página y podemos acceder a las imágenes solo cuando se crea la salida de la galería. Tenemos que guardar nuestras imágenes en un lugar donde podamos acceder a ellas incluso después de una solicitud de otra página.
En este ejemplo, uso una variable de sesión para almacenar la matriz con imágenes. Se puede acceder a una variable de sesión incluso después de volver a cargar otra página. Para almacenar las imágenes, registro un método con el shutdowngancho. Después de que WordPress termine de renderizar la página, shutdownse llamará al gancho. En este punto, deberíamos haber recopilado todas las imágenes de todas las galerías mostradas. Simplemente almacenamos las imágenes y podemos acceder a ellas en una solicitud ajax.

Cuando se activa la solicitud ajax, recuperamos la sesión var y creamos un archivo zip a partir de los datos. Pero esto es un poco fuera de tema para esta pregunta.

Creé un repositorio en GitHub con el código completo del complemento. Espero que te indique la dirección correcta.

Ralf912
fuente
tenga en cuenta que si se trata de nuevas galerías de estilo 3.5, ese método para recuperar imágenes de una galería puede no funcionar para usted.
Milo
Para aclarar, estoy usando la última versión de Wordpress 3.5.1. Johannes, estaría muy agradecido si pudieras proporcionar algún código de muestra la próxima vez que estés en tu escritorio. Gracias, Paul
Paul Thomson
Hola Ralf, ¡este es un trabajo fantástico! Gracias por compartir. Para que las imágenes de mi galería se muestren correctamente, debo incluir link = "file" en el shortcode, es decir: [gallery link = "file"] ya que el shortcode se reescribe a través de su código, creo que se está omitiendo y como Como resultado, mis galerías no se muestran correctamente. ¿Hay alguna forma de arreglar ese argumento en su código?
Paul Thomson
Normalmente, los atributos se pasan simplemente al shortcode original y no se modificarán. Las galerías se muestran normalmente, pero con algo de HTML añadido. En mis pruebas (con veinte y doce temas standrad) las galerías se muestran correctamente.
Ralf912
@PaulThomson Solucioné algunos problemas en el repositorio de github. El código no estaba limpio.
Ralf912
0

Me gusta la idea del complemento de Ralf para poder descargar una galería completa de una vez, pero no he podido hacer que funcione. Se me ocurrió una solución alternativa que funciona para nuestros propósitos. El método consiste en reemplazar la galería WP nativa con la suya que coloca al final del functions.phparchivo de su tema Y agregar el siguiente archivo, nombrado download.phpen la carpeta del tema activo. En la galería personalizada, un enlace debajo del archivo llama al archivo download.php que automáticamente fuerza la descarga de su archivo al disco duro. He probado esto en las últimas versiones de Chrome, Firefox y Safari y funciona bien. He estado usando el tema Twenty Twelve, pero no hay razón para que no funcione en otros también.

a) Agregue lo siguiente al final de functions.php. Esto simplemente está tomado 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) Copie y pegue lo siguiente en un archivo llamado download.phpen el directorio base del tema.

<?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). ¡¡No olvides enlazar al archivo en la galería !! ¡Importante!

Sam Edgecombe
fuente
No creo que sea una buena idea, usando download.phpel $_GETparámetro y puedo descargar todos los archivos que quiera de su carpeta web (también en recursos compartidos de red), comowp-config.php
Diego Betto