wordpress
WordPressのメディアモーダル-添付ファイルの詳細に生成されたサムネールを表示されるコード
最終更新日: 2025年6月28日
サイト運営でも単なる投稿でもそうだが、画像使いまわしはするわけで、その際にフルサイズを毎度用いるわけでもないからサムネを探す。
この手間がけっこう面倒なのだ。
投稿用にアップした画像を別のページやテンプレで用いることなど当たり前、ましてやこのテーマではサムネールサイズもsourceやsrcset用にデフォルトから増やしてるので余計面倒くさい。
ってことで、例によってプラグインを探すのではなく、AI使って作った。
仕様概略
- PHP8up
- Mysql8(だっけ?5じゃない)
- WordPress8up
- プラグインはACFとTinyMce関連(Gotenberg嫌い)とAdvanced Editor Toolsにxmlサイトマップ系利用
- メディアモーダルの表示数を変更するコードと併用
- 一応このテーマで
こんな環境で動作確認。
JavaScriptを上書きして表示させてるから、そこが競合するテーマやプラグイン利用の場合は動かないかシステムエラーなど起きるかも。
実装した画面。
サイズとサムネ(あまり意味はないが)と画像のパスが表示される。
コード
// メディアモーダル-添付ファイルの詳細に生成されたサムネール一覧を表示
// 管理画面のフッターに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かな。