😽
WordPress で他サイトからのブログ記事インポートで、画像をメディアに追加する
Tl,DR
- プラグインなどを使わず標準機能で記事移設したい
- しかし画像はそのまま移設されない事が多い
- 記事移設後にダウンロードして、出来ればメディアに追加したい
以下のコードを貼り付けて実行
どのファイルでも構わないですが、アクセスして実行したいので、一旦page.phpに貼り付けて、固定ページアクセスで実行されるようにしてみます。
page.php
$args = [
'posts_per_page' => -1,
];
$the_query = new WP_Query($args);
if ($the_query->have_posts()) :
while ($the_query->have_posts()) :
$the_query->the_post();
$post_id = get_the_ID();
$post_content = get_post_field('post_content', $post_id);
$matches = [];
$output = preg_match_all('/<img.*?src\s*=\s*[\"|\'](.*?)[\"|\'].*?>/i', $post_content, $matches);
$first_img_set = false;
if (!empty($matches[1])) {
// 画像URLを新しいURLに置き換える処理
$updated_post_content = replace_post_image_urls($post_id, $post_content, $matches);
}
endwhile;
endif;
wp_reset_postdata();
// 投稿内容中の画像URLを新しいURLに置き換える部分の更新
function replace_post_image_urls($post_id, $post_content, $matches)
{
foreach ($matches[1] as $index => $image_url) {
$original_url = get_original_image_url($image_url);
$attach_id = import_image_to_media_library($original_url, $post_id);
if (!is_wp_error($attach_id)) {
// インポートした画像のURLを取得
$new_image_url = wp_get_attachment_url($attach_id);
// srcsetの生成
$image_meta = wp_get_attachment_metadata($attach_id);
$srcset = wp_get_attachment_image_srcset($attach_id, 'full', $image_meta);
// 投稿内容中の画像タグを新しいタグに置き換える
$new_img_tag = sprintf('<img src="%s" srcset="%s">', $new_image_url, $srcset);
$post_content = str_replace($matches[0][$index], $new_img_tag, $post_content);
}
}
// 投稿内容を更新
wp_update_post([
'ID' => $post_id,
'post_content' => $post_content,
]);
return $post_content; // 更新された投稿内容を返す
}
/**
* 画像URLから元の画像のURLを生成します。
*
* @param string $url 画像のURL
* @return string 元の画像のURL
*/
function get_original_image_url(string $url): string
{
// URLからファイル名を抽出
$path = parse_url($url, PHP_URL_PATH);
$filename = basename($path);
// サイズ指定があるファイル名から元のファイル名を導出
$original_filename = preg_replace('/-\d+x\d+(\.\w+)$/', '$1', $filename);
// 元のファイル名をパスに再組み込む
$original_url = str_replace($filename, $original_filename, $url);
return $original_url;
}
function import_image_to_media_library($image_url, $post_id)
{
require_once(ABSPATH . 'wp-admin/includes/image.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
// 画像ファイルをサーバーにダウンロード
$tmp = download_url($image_url);
// ダウンロードエラーをチェック
if (is_wp_error($tmp)) {
// エラーがあればそのまま返す
return $tmp;
}
$file_array = array(
'name' => basename($image_url), // 画像ファイル名
'tmp_name' => $tmp, // ダウンロードした一時ファイルのパス
);
// メディアライブラリにファイルを登録
$id = media_handle_sideload($file_array, $post_id);
// ファイル操作後のエラーチェック
if (is_wp_error($id)) {
// エラーがあれば一時ファイルを削除し、エラーを返す
if (file_exists($tmp)) {
unlink($tmp);
}
return $id;
}
// 成功した場合、一時ファイルがまだ存在するなら削除
if (file_exists($tmp)) {
unlink($tmp);
}
return $id; // メディアライブラリに登録した画像のIDを返す
}
ここでファイルをダウンロード出来ればそのまま進みますが、ダウンロード出来ない場合は失敗します。
遭遇したケースだと、何故か src="/wp-content" となっていたので、
function regexImgURL(string $url)
{
$url = 'https://www.example.com/' . $url;
if (file_get_contents($url, false, null, 0, 1)) {
return esc_url($url);
}
}
のように元URLに正規化する関数で、ダウンロード出来るようにすれば、うまく動くと思います
All in One WP Migration などのプラグインが普及して通常そちらを使った方がスムーズで楽だと思います。しかし、一部投稿タイプの記事だけ移設したい、などの要求があるときに、標準機能でエクスポート/インポートして、画像だけ処理するという方法は必要で便利だと思います
Discussion