问题描述

我想向访问者提供下载整个照片库的选项 (显示在专用 [图库] 页面上) 作为每个图库页面底部显示的 ZIP 文件。 – 必须包括 full-sized 图像。

David Walsh 在他的帖子 here 中给了一些代码来压缩文件,但是我遇到了与 Wordpress 功能集成的麻烦。

我知道有一个 NextGEN 图库下载插件,但我不能使用,因为我使用本机 wordpress 画廊功能。

有关完成以上操作的另一种 (手动方法) 的类似问题可以在这里找到:Plugin to download attached media files?

任何帮助将不胜感激。谢谢。

最佳解决方案

首先你必须得到图像。如何获取图库的所有图像描述为 here

WordPress 使用两个类来解压文件。 PHP 在 ZipArchive()中使用 (用法见 David Walsh) 。和 PclZip,你可以在 wp-admin/includes/class-pclzip.php 中找到这个类。如果您有 ZipArchive()的问题,请尝试使用 PclZip 类。

现在你只需要粘在一起。也许我可以稍后再发一些示例代码,目前我不在我的桌子上。

更新

你的问题可以分为两部分。第一个是从画廊获取所有图像。第二个是压缩图像并发送 zip 文件。我将仅解释第一部分,获取画廊的所有图像,因为压缩文件略有偏离。

也许还有其他的解决方案,但在这个例子中,我用原来的图库短代码来替换图片。原因是 WordPress 在 v3.5 中改变了画廊。在 3.5 之前,画廊的图片是帖子的附件。 3.5 之后,将图像作为属性传递给短码。由于 WP3.5 我们不能再收到附件的贴子,所以我们必须从短代码属性中获取列表。我的策略是用自定义的短代码替换原始的短码,抓住属性,并调用原始的短码来获得图库的输出。

所有画廊的相关内容都在课堂内。要创建一个 zip 文件,我们可以使用另一个类作为输入的 gallery 类的输出。我们从一个类和一个简单的构造函数开始。

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

我们将在挂接 plugins_loaded 的插件后面调用方法 get_instance()。在构造函数中,我们删除原来的短码,并用我们的自定义短码 gallery_zip_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;

}

这个方法的第一件事就是得到帖子,因为我们需要帖子 ID 。比较我们包括 wp-includes/media.php,这个文件包含原始图库短代码的回调函数。现在我们调用一个方法来获取一个包含所有图像的数组,通过调用原始图库回调来创建图库输出,创建一个链接并追加到图库输出的链接。图像本身分别对图像进行编辑,存储在类变量 $images 中,稍后我们需要这个数组。类变量 $image 为每个具有库的文章保存一个条目,因此我们可以在首页或单个视图中使用该函数。每个条目包含每个画廊的数组,因为每个职位中可以有多个画廊。

插件的核心是从短码中获取图像的方法。

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;

}

起初我们决定是单个帖子还是帖子 ID 列表。如果它是一个帖子 ID 的列表,我们处理从 WP3.5 +的画廊。之后,我们必须处理 exclude 属性。在设置所有可变量之后,我们终于可以从画廊获取图像。被删除的图像将被推入类别 $images 以备将来使用。

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

这是插件的金子。只需设置一个带有查询参数的数组,即可使用 get_posts()获取附件,然后浏览检索到的附件。为了处理不同的大小,我们得到了 URL 的附件图像和条。从附件文件中,我们将路径放在文件名中。在阵列 $images 现在是所有的图像和他们的画廊从画廊。

基本上你的问题在这一点上得到回答。但是您也想从图像创建 zip 文件。您可以在上一个方法中从数组 $images 创建一个 zip 文件。但是,每当显示画廊时都会调用此方法,并创建一个 zip 文件可能需要一段时间。也许没有人会请求您在这里创建的 zip 文件,这是浪费资源。

我们怎么能做得更好?你还记得我将所有图像放在类变量 $images 中吗?我们可以使用这个类 var 进行 ajax 请求。但是 ajax 请求只是另一个页面加载,只有创建库的输出时,才能访问图像。我们必须将图像保存在我们可以访问它们的地方,即使在另一个页面请求之后。在这个例子中,我使用会话变量来存储数组的图像。即使再次重新加载页面,也可以访问会话变量。要存储图像,我用 shutdown 钩子注册一个方法。 WordPress 完成渲染页面后,将调用 shutdown 钩子。在这一点上,我们应该收集所有展示的画廊的所有图像。我们只需存储图像,并可以在 ajax 请求中访问它们。

当 ajax 请求被触发时,我们记住会话 var 并从数据中创建一个 zip 文件。但这是一个有关这个问题的话题。

我创建了一个带有完整插件代码的 repository on GitHub 。我希望它指向正确的方向。

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。