Steamer Lane Studio技術備忘録WordPress

WordPressのメディアモーダル-添付ファイルの詳細に生成されたサムネールを表示されるコード

wordpress WordPressのメディアモーダル-添付ファイルの詳細に生成されたサムネールを表示されるコード
最終更新日: 2025年6月28日

サイト運営でも単なる投稿でもそうだが、画像使いまわしはするわけで、その際にフルサイズを毎度用いるわけでもないからサムネを探す。
この手間がけっこう面倒なのだ。
投稿用にアップした画像を別のページやテンプレで用いることなど当たり前、ましてやこのテーマではサムネールサイズもsourceやsrcset用にデフォルトから増やしてるので余計面倒くさい。

ってことで、例によってプラグインを探すのではなく、AI使って作った。

仕様概略

  • PHP8up
  • Mysql8(だっけ?5じゃない)
  • WordPress8up
  • プラグインはACFとTinyMce関連(Gotenberg嫌い)とAdvanced Editor Toolsにxmlサイトマップ系利用
  • メディアモーダルの表示数を変更するコードと併用
  • 一応このテーマで

こんな環境で動作確認。
JavaScriptを上書きして表示させてるから、そこが競合するテーマやプラグイン利用の場合は動かないかシステムエラーなど起きるかも。

WordPressのメディアモーダル-添付ファイルの詳細に生成されたサムネールを表示されるコード実装した画面。
サイズとサムネ(あまり意味はないが)と画像のパスが表示される。

コード

// メディアモーダル-添付ファイルの詳細に生成されたサムネール一覧を表示// 管理画面のフッターにJavaScriptを追加add_action('admin_footer', function() {?><script>jQuery(document).ready(function($) {// wp.mediaが利用可能か確認if (typeof wp === 'undefined' || typeof wp.media === 'undefined') {console.error('Error: wp.media is not defined');return;}

// デバッグ:スクリプト初期化console.log('Custom Media Modal script initialized at ' + new Date().toISOString());

// モーダルイベントを監視wp.media.events.on('editor:frame-create', function(frame) {console.log('Media frame created:', frame);});

wp.media.events.on('open', function(modal) {console.log('Media modal opened:', modal);});

// 「添付ファイルの詳細」ビューを拡張(標準とTwoColumn)var extendAttachmentDetails = function(view, viewName) {var OriginalView = view;if (!OriginalView) {console.error('Error: ' + viewName + ' is undefined');return;}

wp.media.view.Attachment.Details[viewName] = OriginalView.extend({initialize: function() {OriginalView.prototype.initialize.apply(this, arguments);console.log('Attachment Details initialized for ID:', this.model.get('id'), 'View:', viewName);},render: function() {OriginalView.prototype.render.apply(this, arguments);console.log('Rendering Attachment Details for ID:', this.model.get('id'));console.log('Model:', this.model.toJSON());

if (this.model.get('type') === 'image') {var sizes = this.model.get('sizes');console.log('Client-side sizes:', sizes);

var thumbnailList = '<div class="thumbnail-sizes"><h4>生成されたサムネイル</h4>';if (sizes && Object.keys(sizes).length > 0) {thumbnailList += '<ul>';$.each(sizes, function(sizeName, sizeData) {console.log('Size:', sizeName, sizeData);// URLが有効かチェックif (sizeData.url && typeof sizeData.url === 'string') {thumbnailList += '<li>';thumbnailList += '<strong>' + sizeName + '</strong>: ';thumbnailList += (sizeData.width || 'N/A') + '×' + (sizeData.height || 'N/A') + '<br>';thumbnailList += '<a href="' + sizeData.url + '" target="_blank">表示</a><br>';thumbnailList += '<img src="' + sizeData.url + '" style="max-width: 100px; margin-top: 5px;" /><br>';thumbnailList += '<span style="word-break: break-all; font-size: 12px;">' + sizeData.url + '</span>';thumbnailList += '</li>';} else {console.warn('Invalid URL for size:', sizeName);thumbnailList += '<li>';thumbnailList += '<strong>' + sizeName + '</strong>: ';thumbnailList += (sizeData.width || 'N/A') + '×' + (sizeData.height || 'N/A') + '<br>';thumbnailList += '<span style="color: #d63638;">画像URLが無効</span>';thumbnailList += '</li>';}});thumbnailList += '</ul>';} else {thumbnailList += '<p style="color: #d63638;">サムネイル情報が取得できませんでした</p>';}thumbnailList += '</div>';

// .attachment-detailsに追加、なければ末尾var $target = this.$el.find('.attachment-details');if ($target.length) {$target.append(thumbnailList);console.log('Thumbnail list appended to .attachment-details for ' + viewName);} else {this.$el.append(thumbnailList);console.log('Thumbnail list appended to modal root for ' + viewName);}}

return this;}});};

// 標準とTwoColumnを拡張extendAttachmentDetails(wp.media.view.Attachment.Details, 'Standard');if (wp.media.view.Attachment.Details.TwoColumn) {extendAttachmentDetails(wp.media.view.Attachment.Details.TwoColumn, 'TwoColumn');}

// スタイル(flexで横表示、スマホ対応)$('<style>').text(`.thumbnail-sizes {margin-top: 20px;padding: 10px;border-top: 1px solid #ddd;background: #f9f9f9;}.thumbnail-sizes h4 {margin: 0 0 10px;font-size: 14px;}.thumbnail-sizes ul {display: flex;flex-wrap: wrap;list-style: none;margin: 0;padding: 0;gap: 20px;}.thumbnail-sizes li {flex: 0 1 auto;min-width: 150px;padding: 10px;box-sizing: border-box;text-align: center;}.thumbnail-sizes img {max-width: 100px;height: auto;margin-top: 5px;}.thumbnail-sizes span {display: block;margin-top: 5px;font-size: 12px;color: #555;word-break: break-all;}.thumbnail-sizes p {color: #d63638;}`).appendTo('head');});</script><?php});

// サーバー側で画像メタデータを確認(デバッグ用)add_action('wp_ajax_check_thumbnail_metadata', function() {check_ajax_referer('thumbnail_metadata_nonce', 'nonce');$attachment_id = isset($_POST['attachment_id']) ? absint($_POST['attachment_id']) : 0;if ($attachment_id) {$metadata = wp_get_attachment_metadata($attachment_id);error_log('Metadata for ID ' . $attachment_id . ': ' . print_r($metadata, true));wp_send_json_success(['metadata' => $metadata]);} else {wp_send_json_error(['message' => 'Invalid attachment ID']);}});

// AJAXクエリの競合を回避add_filter('ajax_query_attachments_args', function($query) {if (isset($query['post_type']) && $query['post_type'] === 'attachment') {$desired_posts_per_page = get_option('media_posts_per_page', 80);$query['posts_per_page'] = absint($desired_posts_per_page);$query['orderby'] = 'date';$query['order'] = 'DESC';$query['paged'] = isset($_REQUEST['paged']) ? absint($_REQUEST['paged']) :(isset($_REQUEST['query']['paged']) ? absint($_REQUEST['query']['paged']) : 1);error_log('Custom AJAX query args applied: ' . print_r($query, true));}return $query;}, 9999);

// サムネイル再生成add_action('admin_init', function() {if (isset($_GET['regenerate_thumbnails']) && current_user_can('manage_options')) {$attachment_id = absint($_GET['regenerate_thumbnails']);if ($attachment_id) {$file = get_attached_file($attachment_id);if ($file) {$metadata = wp_generate_attachment_metadata($attachment_id, $file);wp_update_attachment_metadata($attachment_id, $metadata);error_log('Regenerated metadata for ID ' . $attachment_id . ': ' . print_r($metadata, true));} else {error_log('Error: Attachment file not found for ID ' . $attachment_id);}}}});

//登録済みサイズをログ出力add_action('admin_init', function() {global $_wp_additional_image_sizes;$sizes = get_intermediate_image_sizes();error_log('Registered Image Sizes: ' . print_r($sizes, true));foreach ($sizes as $size) {$width = get_option("{$size}_size_w");$height = get_option("{$size}_size_h");error_log("Size: $size, Width: $width, Height: $height");}});

これをfunction.phpに張り付ければOKかな。