What’s the correct way to add capabilites to user roles?

The best place to add this would be in the plugin’s activation hook. You can either call the dynamic activate_{$plugin} hook, or better yet use the provided register_activation_hook method. Using your code example above – something like this would be what you’re looking for: register_activation_hook( __FILE__, function() { $role = get_role( ‘editor’ ); $role->add_cap( ‘edit_booked_appointments’, … Read more

Adding JavaScript file in Admin Panel

Yes, your code is good. And that my_custom_script is a unique identifier for the script you’re enqueueing. You can find the default script handlers/identifiers here — e.g. jquery for the jQuery library that ships with WordPress. There you can also find more details about the wp_enqueue_script() function, e.g. where should you use the function, the … Read more

New bulk action to resend welcome emails

I don’t think the plugin is helpful for your case, and you can just call the WordPress API yourself directly: wp_new_user_notification( $user_id, null, ‘both’ ); This is all the plugin does: get’s the user ID from request parameters, verifies the user exists and then calls wp_new_user_notifications (see plugin code here).

save_post_{$post->post_type} action firing on second save

I think you’d have to move the check for whether or not the $location === header into the metabox then use the following to save the meta data. Like this: //In your metabox before the fields $location = get_post_meta( $post->ID, ‘_est_template_location’, true ); if( empty( $location ) || $location != ‘header’ ) : $location = … Read more

Action Scheduler not running

require_once( plugin_dir_path( __FILE__ ) . ‘/libraries/action-scheduler/action-scheduler.php’ ); /** * Schedule an action with the hook ‘eg_midnight_log’ to run at midnight each day * so that our callback is run then. */ function eg_log_action_data() { if ( false === as_next_scheduled_action( ‘eg_midnight_log’ ) ) { as_schedule_recurring_action( strtotime( ‘midnight tonight’ ), DAY_IN_SECONDS, ‘eg_midnight_log’ ); } } add_action( ‘init’, … Read more