I want to add few exactly gallery metaboxes. Yes, I know about ACF - I wanna dig deeper and to learn how to do it manually, and to know the right way, understand where I'm wrong.
I've found that code, and if the metabox is only one, all works brilliant - the data is saving, all can be appeared on the frontend. Php-part
function gallery_metabox_enqueue($hook) {
if ( 'post.php' == $hook || 'post-new.php' == $hook ) {
wp_enqueue_script('gallery-metabox', get_template_directory_uri() . '/js/gallery-metabox.js', array('jquery', 'jquery-ui-sortable'));
wp_add_inline_style( 'gallery-metabox', '#gallery-metabox-list li {float: left; width: 30%; text-align: center; margin: 10px 10px 10px 0; cursor: move;}' );
}
}
add_action('admin_enqueue_scripts', 'gallery_metabox_enqueue');
function gallery_meta_save($post_id) {
if (!isset($_POST['gallery_meta_nonce']) || !wp_verify_nonce($_POST['gallery_meta_nonce'], basename(__FILE__))) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (isset($_POST['gallery_images']) && is_array($_POST['gallery_images'])) {
$images = array_map('sanitize_text_field', $_POST['gallery_images']);
update_post_meta($post_id, 'gallery_images', $images);
}
}
add_action('save_post', 'gallery_meta_save');
function gallery_meta_callback($post) {
wp_nonce_field(basename(__FILE__), 'gallery_meta_nonce');
$gallery_images = get_post_meta($post->ID, 'gallery_images', true);
?>
<table class="form-table">
<tr>
<td>
<ul id="gallery-metabox-list">
<?php if ($gallery_images) : ?>
<?php foreach ($gallery_images as $image_id) : ?>
<li>
<?php echo wp_get_attachment_image($image_id, 'thumbnail'); ?>
<input type="hidden" name="gallery_images[]" value="<?php echo esc_attr($image_id); ?>">
<a class="remove-image" href="#">Remove image</a>
</li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
<a class="gallery-add button" href="#" data-uploader-title="Add image(s) to gallery" data-uploader-button-text="Add image(s)">Add Images</a>
</td>
</tr>
</table>
<?php
}
function add_gallery_metabox($post_type) {
add_meta_box(
'gallery-metabox',
'Gallery',
'gallery_meta_callback',
$post_type,
'normal',
'high'
);
}
add_action('add_meta_boxes', 'add_gallery_metabox');
gallery-metabox.js
jQuery(function($) {
var file_frame;
$(document).on('click', 'a.gallery-add', function(e) {
e.preventDefault();
if (file_frame) {
file_frame.open();
return;
}
file_frame = wp.media({
title: $(this).data('uploader-title'),
button: {
text: $(this).data('uploader-button-text'),
},
multiple: true
});
file_frame.on('select', function() {
var list = $('#gallery-metabox-list'),
selection = file_frame.state().get('selection');
selection.each(function(attachment) {
attachment = attachment.toJSON();
list.append('<li><input type="hidden" name="gallery_images[]" value="' + attachment.id + '"><img class="image-preview" src="' + attachment.sizes.thumbnail.url + '"><a class="remove-image" href="#">Remove image</a></li>');
});
});
file_frame.open();
});
$(document).on('click', 'a.remove-image', function(e) {
e.preventDefault();
$(this).parent().remove();
});
});
I tried to add the second metabox, but then data doesn't save, I upload photos, save the post, and don't see the photos - they don't save. I asked GPT, it adviced to check the log file and to check nonces, anything helped.I tried many things, for example
function add_gallery_metaboxes($post_type) {
$types = array('post', 'product', 'custom-post-type');
if (in_array($post_type, $types)) {
// Add the first metabox
add_meta_box(
'gallery-metabox-first', // Unique identifier for the first metabox
'Gallery First', // Title of the first metabox
'gallery_meta_callback_first', // Callback function to display the first metabox content
$post_type,
'normal',
'high',
array('id' => 'first') // Pass a unique ID as an argument
);
// Add the second metabox
add_meta_box(
'gallery-metabox-second', // Unique identifier for the second metabox
'Gallery Second', // Title of the second metabox
'gallery_meta_callback_second', // Callback function to display the second metabox content
$post_type,
'normal',
'high',
array('id' => 'second') // Pass a unique ID as an argument
);
}
}
add_action('add_meta_boxes', 'add_gallery_metaboxes');
function gallery_meta_callback_first($post, $metabox) {
wp_nonce_field(basename(__FILE__), 'gallery_meta_nonce_first');
$gallery_id = isset($metabox['args']['id']) ? $metabox['args']['id'] : 'first'; // Get the unique ID
?>
<table class="form-table">
<tr>
<td>
<ul id="gallery-metabox-list-<?php echo $gallery_id; ?>" style="display:flex; flex-wrap:wrap;gap: 10px;">
<!-- Your code to display images and input fields for the first metabox here -->
</ul>
<a class="gallery-add button" href="#" data-gallery-id="<?php echo $gallery_id; ?>" data-uploader-title="Add image(s) to gallery" data-uploader-button-text="Add image(s)">Add Images</a>
</td>
</tr>
</table>
<?php
}
function gallery_meta_callback_second($post, $metabox) {
wp_nonce_field(basename(__FILE__), 'gallery_meta_nonce_second');
$gallery_id = isset($metabox['args']['id']) ? $metabox['args']['id'] : 'second'; // Get the unique ID
?>
<table class="form-table">
<tr>
<td>
<ul id="gallery-metabox-list-<?php echo $gallery_id; ?>" style="display:flex; flex-wrap:wrap;gap: 10px;">
<!-- Your code to display images and input fields for the second metabox here -->
</ul>
<a class="gallery-add button" href="#" data-gallery-id="<?php echo $gallery_id; ?>" data-uploader-title="Add image(s) to gallery" data-uploader-button-text="Add image(s)">Add Images</a>
</td>
</tr>
</table>
<?php
}
jQuery(function($) {
function handleGalleryMetabox(gallery_id) {
var file_frames = {};
$(document).on('click', 'a.gallery-add', function(e) {
e.preventDefault();
if (!file_frames[gallery_id]) {
file_frames[gallery_id] = wp.media({
title: $(this).data('uploader-title'),
button: {
text: $(this).data('uploader-button-text'),
},
multiple: true
});
file_frames[gallery_id].on('select', function() {
var list = $('#gallery-metabox-list-' + gallery_id),
listIndex = list.find('li').length,
selection = file_frames[gallery_id].state().get('selection');
selection.each(function(attachment) {
attachment = attachment.toJSON();
list.append('<li><input type="hidden" name="' + gallery_id + '[' + listIndex + ']" value="' + attachment.id + '"><img class="image-preview" src="' + attachment.sizes.thumbnail.url + '"><a class="change-image button button-small" href="#" data-uploader-title="Change image" data-uploader-button-text="Change image">Change image</a><br><small><a class="remove-image" href="#">Remove image</a></small></li>');
listIndex++;
});
makeSortable(gallery_id);
});
}
file_frames[gallery_id].open();
});
function resetIndex(gallery_id) {
$('#gallery-metabox-list-' + gallery_id + ' li').each(function(i) {
$(this).find('input:hidden').attr('name', gallery_id + '[' + i + ']');
});
}
function makeSortable(gallery_id) {
$('#gallery-metabox-list-' + gallery_id).sortable({
opacity: 0.6,
stop: function() {
resetIndex(gallery_id);
}
});
}
$(document).on('click', 'a.remove-image', function(e) {
e.preventDefault();
var gallery_id = $(this).data('gallery-id'); // Get the gallery ID
$(this).parents('li').animate({ opacity: 0 }, 200, function() {
$(this).remove();
resetIndex(gallery_id);
});
});
}
// Handle the first gallery metabox
handleGalleryMetabox('first');
// Handle the second gallery metabox
handleGalleryMetabox('second');
});
The thing I mentioned - when metabox is one - all is good, when 2 or multiple - it doesn't save photos, where I'm wrong?