問題描述

我想向訪問者提供下載整個照片庫的選項 (顯示在專用 [圖庫] 頁面上) 作為每個圖庫頁面底部顯示的 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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。