To get the updates, I ended up loading update text from the themes.php page by doing this:
HTML:
<div id="ajax-test"></div>
jQuery:
$('#ajax-test').load('<?php bloginfo('url'); ?>/wp-admin/themes.php .theme.active .update-message', function(){
$('#ajax-test').append('<a class="update-now" href="<?php bloginfo('url'); ?>/wp-admin/themes.php?theme=your-theme-name" target="_blank">Update Now</a>');
$('#ajax-test').addClass('active');
});
Css to hide unless update is found:
#ajax-test .button-link{
display:none;
}
.update-now{
display:none;
}
.update-message + .update-now{
display:inline-block;
}
For a non-admin user, you need to give them access to theme editing and theme updating using add_cap( $role, $cap )
, and styling out everything that isn't necessary for theme updating.
There are two issues with this that I can see: If a user edits CSS, they can use dashboard navigation, and they can change their theme.
I have a redirect set up in my functions.php that only allows access to this page in wp_admin:
$role = get_role( 'editor' );
$role->add_cap( 'update_themes' );
$role->add_cap( 'switch_themes' );
add_action( 'init', 'blockusers_init' );
function blockusers_init() {
if ( is_admin() && ! current_user_can( 'administrator' ) && strpos($_SERVER['REQUEST_URI'], 'wp-admin/themes.php') == false && strpos($_SERVER['REQUEST_URI'], 'wp-admin/update.php?action=upgrade-theme') == false &&
! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
wp_redirect( home_url() );
exit;
};
For the theme updating, if a user wants to deliberately edit the html to brick their own site, I'm willing to let them.
Maybe it's not the most elegant solution, but it's the best option I've found for my situation.