Skip to content

Instantly share code, notes, and snippets.

@jonshipman
Created January 31, 2025 16:59
Show Gist options
  • Save jonshipman/21960ef56853a3b9f54c119de4e20509 to your computer and use it in GitHub Desktop.
Save jonshipman/21960ef56853a3b9f54c119de4e20509 to your computer and use it in GitHub Desktop.
Custom Post Type Metabox Class
<?php
/**
* Custom Post Type Meta Box.
*
* @package Heartland
*/
/**
* Meta box class.
*/
class Heartland_Core_Meta_Box {
/**
* Meta box data.
*
* @var array
*/
protected $meta_box;
/**
* Create meta box based on given data.
*
* @param array $meta_box Meta box data.
*/
public function __construct( $meta_box ) {
$this->meta_box = $meta_box;
add_action( 'admin_menu', array( $this, 'add' ) );
add_action( 'save_post', array( $this, 'save' ) );
add_action( 'admin_menu', array( $this, 'metahide' ) );
}
/**
* Hides the custom meta box from locations.
*/
public function metahide() {
if ( empty( $this->meta_box['posts'] ) ) {
return;
}
remove_meta_box( 'postcustom', $this->meta_box['posts'], 'normal' );
}
/**
* Add meta box for multiple post types.
*/
public function add() {
if ( empty( $this->meta_box['posts'] ) ) {
return;
}
foreach ( $this->meta_box['posts'] as $page ) {
add_meta_box( $this->meta_box['id'], $this->meta_box['title'], array( $this, 'show' ), $page, $this->meta_box['context'], $this->meta_box['priority'] );
}
}
/**
* Callback function to show fields in meta box.
*/
public function show() {
global $post;
/**
* Use nonce for verification.
*/
echo '<input type="hidden" name="heartland_core_prefix_meta_box_nonce" value="' . esc_attr( wp_create_nonce( basename( __FILE__ ) ) ), '" />';
echo '<table class="form-table">';
foreach ( $this->meta_box['fields'] as $field ) {
/**
* Get current post meta data.
*/
$meta = get_post_meta( $post->ID, $field['id'], true );
$field_name = 'heartland_core_' . $field['id'];
?>
<tr>
<th style="width:20%">
<label for="<?php echo esc_attr( $field_name ); ?>"><?php echo esc_html( $field['name'] ); ?></label>
</th>
<td>
<?php
switch ( $field['type'] ) {
case 'thumbnail':
$default_url = \Elementor\Utils::get_placeholder_image_src();
$featured_img_url = $default_url;
if ( $meta ) {
$featured_img_url = wp_get_attachment_url( $meta, 'medium' );
}
?>
<div class="editor-post-featured-image__preview" style="display: inline-block; max-width: 160px;">
<img data-default-url="<?php echo esc_url( $default_url ); ?>" id="<?php echo esc_attr( $field_name ); ?>_image" src="<?php echo esc_url( $featured_img_url ); ?>" class="editor-post-featured-image__preview-image" />
</div>
<input type="hidden" name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>" value="<?php echo esc_attr( $meta ); ?>" />
<button type="button" id="<?php echo esc_attr( $field_name ); ?>_select" class="button heartland-core-upload-button"><?php esc_html_e( 'Select Image', 'heartland' ); ?></button>
<button type="button" id="<?php echo esc_attr( $field_name ); ?>_remove" class="button heartland-core-remove-button"><?php esc_html_e( 'Remove Image', 'heartland' ); ?></button>
<br>
<script>
document.getElementById('<?php echo esc_attr( $field_name ); ?>_select').addEventListener('click', function() {
var custom_uploader = wp.media({
title: 'Select Image',
button: {
text: 'Use this image',
},
multiple: false,
}).on('select', function() {
var attachment = custom_uploader.state().get('selection').first().toJSON();
document.getElementById('<?php echo esc_attr( $field_name ); ?>').value = attachment.id;
document.getElementById('<?php echo esc_attr( $field_name ); ?>_image').src = attachment.url;
}).open();
});
document.getElementById('<?php echo esc_attr( $field_name ); ?>_remove').addEventListener('click', function() {
document.getElementById('<?php echo esc_attr( $field_name ); ?>').value = '';
const image = document.getElementById('<?php echo esc_attr( $field_name ); ?>_image');
image.src = image.getAttribute('data-default-url');
});
</script>
<?php
echo esc_html( $field['desc'] );
break;
case 'text':
?>
<input type="text" name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>" value="<?php echo esc_attr( $meta ? $meta : $field['std'] ); ?>" size="30" style="width:97%" />
<br>
<?php
echo esc_html( $field['desc'] );
break;
case 'textarea':
?>
<textarea name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>" cols="60" rows="4" style="width:97%"><?php echo esc_html( $meta ? $meta : $field['std'] ); ?></textarea>
<br>
<?php
echo esc_html( $field['desc'] );
break;
case 'select':
?>
<select name="<?php echo esc_attr( $field_name ); ?>" id="<?php echo esc_attr( $field_name ); ?>">
<?php
foreach ( $field['options'] as $option ) {
?>
<option value="<?php echo esc_attr( $option['value'] ); ?>"<?php selected( $meta, $option['value'] ); ?>><?php echo esc_html( $option['name'] ); ?></option>
<?php
}
?>
</select>
<br>
<?php
echo esc_html( $field['desc'] );
break;
case 'radio':
foreach ( $field['options'] as $option ) {
?>
<input type="radio" name="<?php echo esc_attr( $field_name ); ?>" value="<?php echo esc_attr( $option['value'] ); ?>"<?php checked( $meta, $option['value'] ); ?> />
<?php
echo esc_html( $option['name'] );
}
echo '<br>' . esc_html( $field['desc'] );
break;
case 'checkbox':
foreach ( $field['options'] as $option ) {
?>
<input type="checkbox" name="<?php echo esc_attr( $field_name ); ?>" value="<?php echo esc_attr( $option['value'] ); ?>"<?php checked( $meta, $option['value'] ); ?> />
<?php
echo esc_html( $option['name'] );
}
echo '<br>' . esc_html( $field['desc'] );
break;
}
echo '<td></tr>';
}
echo '</table>';
}
/**
* Save data from meta box
*
* @param int $post_id Post ID.
*/
public function save( $post_id ) {
/**
* Verify nonce.
*/
$nonce_safe = isset( $_POST['heartland_core_prefix_meta_box_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['heartland_core_prefix_meta_box_nonce'] ) ) : false;
if ( ! isset( $_POST['heartland_core_prefix_meta_box_nonce'] ) || ! wp_verify_nonce( $nonce_safe, basename( __FILE__ ) ) ) {
return $post_id;
}
/**
* Check autosave.
*/
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
/**
* Check permissions.
*/
if ( ! empty( $_POST['post_type'] ) && 'page' === $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} elseif ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
foreach ( $this->meta_box['fields'] as $field ) {
$old = get_post_meta( $post_id, $field['id'], true );
$field_name = 'heartland_core_' . $field['id'];
$new = empty( $_POST[ $field_name ] ) ? '' : sanitize_text_field( wp_unslash( $_POST[ $field_name ] ) );
if ( $new && $new !== $old ) {
update_post_meta( $post_id, $field['id'], $new );
} elseif ( '' === $new && $old ) {
delete_post_meta( $post_id, $field['id'], $old );
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment