[WordPress] 掃描上傳資料夾(uploads)的圖檔,重新建立媒體庫連結

本篇文章更新時間:2022/08/31
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知。
一介資男的 LINE 社群開站囉!歡迎入群聊聊~
如果本站內容對你有幫助,歡迎使用 BFX Pay 加密貨幣新台幣 贊助支持。


一般來說,應該是不會碰到 WordPress 媒體庫沒資料,然後上傳資料夾 wp-content/uploads 裡有圖檔。畢竟系統的作業流程,不會先接觸到檔案目錄,都是從後台上架圖片等資料。

目前想到唯一就是你後台整批刪除媒體庫連結,但主機上沒刪到(權限問題),不過,既然都刪除了,又幹嘛連結回來?XD

這個需求會碰到,純粹是因為客戶把主站拆出去後,沒確實上架兩邊(測試站、主站),導致測試站開發完成要轉正式後,發現有一堆圖片都還在「原本的主站」目錄裡沒有帶過來。

於是,這個修復的過程分兩階段:

  1. 先把整個上傳目錄打包,到新主站上傳目錄去比對差異來互補到最完整的圖庫檔案。
  2. 補上差異的圖檔只能先救掉圖內容,但後台還無法找到這個圖檔來管理。

本文就是筆記「第二步」的作業,流程如下:

  1. 掃描 wp-content/uploads 目錄下所有圖片檔案(含PDF)
  2. 將這些檔案整理,找到原始檔案
  3. 判斷這個檔案是否已經有建立媒體庫連結
  4. 沒有建立過就開始建立的程序

整體運作我都寫成 Headless 的方式來處理,程式碼如下:(Gist)

 $file_path) {
    // print_r($file_path . PHP_EOL);
    $current_ext = pathinfo($file_path, PATHINFO_EXTENSION);
    if (isset($collects[$current_ext])) {
        $collects[$current_ext] += 1;
    } else {
        $collects[$current_ext] = 0;
    }
    //找到圖片原始檔案
    if (in_array(strtolower($current_ext), $img_allow_list)) {
        if (preg_match("/-\d*x\d*\." . $current_ext . "$/", $file_path)) {
            $file_without_ext        = str_replace('.' . $current_ext, '', $file_path);
            $origin_file             = explode('-', $file_without_ext);
            $size_info               = end($origin_file);
            $origin_file             = str_replace('-' . $size_info, '', $file_path);
            $origin_file_without_ext = str_replace($current_ext, '', $origin_file);

            if (file_exists($origin_file)) {
                $main_file[] = $origin_file;
            }
        } else {
            print_r($file_path . PHP_EOL);
            $main_file[] = $file_path;
        }
    } else if (in_array(strtolower($current_ext), $other_allow_list)) {
        $main_file[] = $file_path;
    }
    $main_file = array_unique($main_file);
}
// print_r($main_file);
// print_r($collects);
print_r(mxp_import_image_from_local($main_file));

// Ref: https://gist.github.com/UziTech/3b65b2543cee57cd6d2ecfcccf846f20
function glob_recursive($base, $pattern, $flags = 0) {
    $glob_nocheck = $flags & GLOB_NOCHECK;
    $flags        = $flags & ~GLOB_NOCHECK;
    function check_folder($base, $pattern, $flags) {
        if (substr($base, -1) !== DIRECTORY_SEPARATOR) {
            $base .= DIRECTORY_SEPARATOR;
        }
        $files = glob($base . $pattern, $flags);
        if (!is_array($files)) {
            $files = [];
        }
        $dirs = glob($base . '*', GLOB_ONLYDIR | GLOB_NOSORT | GLOB_MARK);
        if (!is_array($dirs)) {
            return $files;
        }
        foreach ($dirs as $dir) {
            $dirFiles = check_folder($dir, $pattern, $flags);
            $files    = array_merge($files, $dirFiles);
        }
        return $files;
    }
    $files = check_folder($base, $pattern, $flags);
    if ($glob_nocheck && count($files) === 0) {
        return [$pattern];
    }
    return $files;
}

function mxp_import_image_from_local($imgs) {
    require_once ABSPATH . 'wp-admin/includes/media.php';
    require_once ABSPATH . 'wp-admin/includes/file.php';
    require_once ABSPATH . 'wp-admin/includes/image.php';
    global $wpdb;
    $uploads    = array();
    $upload_dir = wp_upload_dir();
    for ($i = 0; $i < count($imgs); ++$i) {
        $img_filename = basename($imgs[$i]);
        $img_dir_path = $imgs[$i];

        if (file_exists($img_dir_path)) {
            $uploads[] = array(
                'filename'    => $img_filename,
                'upload_file' => $img_dir_path,
            );
        }
    }
    $att_id = array();
    //如果上傳沒失敗,就附加到剛剛那篇文章
    for ($i = 0; $i < count($uploads); ++$i) {
        if (isset($uploads[$i]['upload_file']) && $uploads[$i]['upload_file'] != "" && isset($uploads[$i]['filename']) && $uploads[$i]['filename'] != "") {
            $wp_filetype = wp_check_filetype($uploads[$i]['filename'], null);
            $attachment  = array(
                'post_mime_type' => $wp_filetype['type'],
                // 'post_parent'    => $post_id,
                'post_title'     => preg_replace('/\.[^.]+$/', '', $uploads[$i]['filename']),
                'post_content'   => '',
                'post_status'    => 'inherit',
                'post_author'    => 1,
            );

            //有新增過該檔案就不再新增了
            $find_file_post = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT ID FROM $wpdb->posts WHERE post_title LIKE %s", '%' . preg_replace('/\.[^.]+$/', '', $uploads[$i]['filename']) . '%'
                ),
                ARRAY_A
            );
            if (count($find_file_post) == 0) {
                $attachment_id = wp_insert_attachment($attachment, $uploads[$i]['upload_file']);
                if (!is_wp_error($attachment_id)) {
                    // wp_create_image_subsizes($uploads[$i]['upload_file'], $attachment_id);
                    //產生附加檔案中繼資料
                    $attachment_data = wp_generate_attachment_metadata($attachment_id, $uploads[$i]['upload_file']);
                    wp_update_attachment_metadata($attachment_id, $attachment_data);
                    $att_id[] = $attachment_id;
                }
            } else {
                $att_id[] = $find_file_post[0]['ID'];
            }
        }
    }
    return $att_id;
}

適逢準備 WordPress 6.1 正式開始 webp 圖檔格式的切換,這份程式除了可以針對 webp 的作業來強化運作邏輯,還可以再補上掃描資料庫裡有用到的貼文來關聯文章。

要特別注意的是主題內用到的縮圖版本,整個切換過主題又保有過去主題縮圖版本的那種可能會有管理不到的問題。


Share:

作者: Chun

資訊愛好人士。主張「人人都該為了偷懶而進步」。期許自己成為斜槓到變進度條 100% 的年輕人。[///////////____36%_________]

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


文章
Filter
Apply Filters
Mastodon