Looking for feedback on an irritating issue (unlikely to be roots-related, but I can’t be sure, and so bad, that I’m turning to every channel I know with serious WP expertise): Have you encountered problems with admin meta boxes occasionally disappearing for just one user (sometimes an admin)?
So far, BTW, this has been experienced in a handful of sites, all running on Trellis and Bedrock (though I’d be surprised if either is the culprit here), but no Sage.
I’ve seen the admin boxes “come back” within a day (likely with a cache dump along the way, but I can’t be sure). All affected meta boxes have been created with direct calls to Core (rather than a meta-box-making plugin). And this generally happens such that multiple custom meta boxes added to a CPT all disappear at the same time.
Here is an example of the type of meta box that suddenly disappears sometimes:
new Prefix_Seminar_MB_Dates;
class Prefix_Seminar_MB_Dates {
public function __construct() {
if ( is_admin() ) {
add_action( 'load-post.php', array( $this, 'init_metabox' ) );
add_action( 'load-post-new.php', array( $this, 'init_metabox' ) );
}
}
public function init_metabox() {
add_action( 'add_meta_boxes', array( $this, 'add_metabox' ) );
add_action( 'save_post', array( $this, 'save_metabox' ), 10, 2 );
}
public function add_metabox() {
add_meta_box(
'prefix_seminar_mb_dates',
__( 'Seminar Dates', 'textdomain' ),
array( $this, 'prefix_seminar_mb_dates_render' ),
'cpt-seminar',
'under-title',
'core'
);
}
public function prefix_seminar_mb_dates_render( $post ) {
// Add nonce for security and authentication
wp_nonce_field( 'nonce_action', 'nonce' );
// Retrieve existing values from database
$prefix_seminar_mb_dates_start = get_post_meta( $post->ID, 'prefix_seminar_mb_dates_start', true );
$prefix_seminar_mb_dates_end = get_post_meta( $post->ID, 'prefix_seminar_mb_dates_end', true );
$prefix_seminar_mb_dates_year = get_post_meta( $post->ID, 'prefix_seminar_mb_dates_year', true );
// Set default values
if( empty( $prefix_seminar_mb_dates_start ) ) $prefix_seminar_mb_dates_start = '0001-01-01';
if( empty( $prefix_seminar_mb_dates_end ) ) $prefix_seminar_mb_dates_end = '0001-01-01';
if( empty( $prefix_seminar_mb_dates_year ) ) $prefix_seminar_mb_dates_year = '0001';
// Form fields
echo '<table class="form-table">';
echo ' <tr>';
echo ' <th style="text-align: right;"><label for="prefix_seminar_mb_dates_year" class="prefix_seminar_mb_dates_year_label">' . __( 'Seminar Year', 'textdomain' ) . '</label></th>';
echo ' <td>';
echo ' <input type="text" id="prefix_seminar_mb_dates_year" name="prefix_seminar_mb_dates_year" class="prefix_seminar_mb_dates_year_field" placeholder="' . esc_attr__( '', 'textdomain' ) . '" value="' . esc_attr( $prefix_seminar_mb_dates_year ) . '">';
echo ' </td>';
echo ' <th style="text-align: right;"><label for="prefix_seminar_mb_dates_start" class="prefix_seminar_mb_dates_start_label">' . __( 'Seminar Start Date', 'textdomain' ) . '</label></th>';
echo ' <td>';
echo ' <input type="date" id="prefix_seminar_mb_dates_start" name="prefix_seminar_mb_dates_start" class="prefix_seminar_mb_dates_start_field" placeholder="' . esc_attr__( '', 'textdomain' ) . '" value="' . esc_attr( $prefix_seminar_mb_dates_start ) . '">';
echo ' </td>';
echo ' <th style="text-align: right;"><label for="prefix_seminar_mb_dates_end" class="prefix_seminar_mb_dates_end_label">' . __( 'Seminar End Date', 'textdomain' ) . '</label></th>';
echo ' <td>';
echo ' <input type="date" id="prefix_seminar_mb_dates_end" name="prefix_seminar_mb_dates_end" class="prefix_seminar_mb_dates_end_field" placeholder="' . esc_attr__( '', 'textdomain' ) . '" value="' . esc_attr( $prefix_seminar_mb_dates_end ) . '">';
echo ' </td>';
echo ' </tr>';
echo '</table>';
}
public function save_metabox( $post_id, $post ) {
// Add nonce for security and authentication
$nonce_name = isset( $_POST['nonce'] ) ? $_POST['nonce'] : '';
$nonce_action = 'nonce_action';
if ( ! isset( $nonce_name ) ) return; // Check if nonce is set
if ( ! wp_verify_nonce( $nonce_name, $nonce_action ) ) return; // Check if nonce is valid
if ( ! current_user_can( 'edit_post', $post_id ) ) return; // Check if user has permissions to save data
if ( wp_is_post_autosave( $post_id ) ) return; // Check if not an autosave
if ( wp_is_post_revision( $post_id ) ) return; // Check if not a revision
// Sanitize user input.
$new_prefix_seminar_mb_dates_start = isset( $_POST[ 'prefix_seminar_mb_dates_start' ] ) ? sanitize_text_field( $_POST[ 'prefix_seminar_mb_dates_start' ] ) : '';
$new_prefix_seminar_mb_dates_end = isset( $_POST[ 'prefix_seminar_mb_dates_end' ] ) ? sanitize_text_field( $_POST[ 'prefix_seminar_mb_dates_end' ] ) : '';
$new_prefix_seminar_mb_dates_year = isset( $_POST[ 'prefix_seminar_mb_dates_year' ] ) ? sanitize_text_field( $_POST[ 'prefix_seminar_mb_dates_year' ] ) : '';
// Update the meta field in the database.
update_post_meta( $post_id, 'prefix_seminar_mb_dates_start', $new_prefix_seminar_mb_dates_start );
update_post_meta( $post_id, 'prefix_seminar_mb_dates_end', $new_prefix_seminar_mb_dates_end );
update_post_meta( $post_id, 'prefix_seminar_mb_dates_year', $new_prefix_seminar_mb_dates_year );
}
}
And here is the code that provides the “under-title” context:
// Move meta boxes in "under-title" custom context to between title and editor
add_action( 'edit_form_after_title', function() {
global $post, $wp_meta_boxes;
do_meta_boxes( get_current_screen(), 'under-title', $post );
unset( $wp_meta_boxes[get_post_type( $post )]['under-title']);
});