How to hook in and modify the new revisions UI (3.6+)?

Unfortunately, there is no standardized best practice instituted by WordPress for hooking into Backbone templates. There have been plans suggested to bring the familiar filters and actions API to Javascript in WordPress, but there is a lack of traction in this movement. Carl Danley created a library which does just that, which is helpful if you’re trying to build/jerry-rig code in the most minute way to all you to do what you’re trying to do.

Basically, you’re trying to override what’s going on in revisions.view.Meta‘s microtemplate.

There isn’t a simple way to override the microtemplate markup itself. What I’d suggest is overriding the .template() method of any constructor that extends from revisions.view.Meta, those being revisions.view.MetaFrom and revisions.view.MetaTo. To do this, here’s some boilerplate:

add_action( 'admin_footer-revision.php', function() {
    $post = get_post();
    ?>
    <script id="tmpl-revisions-meta-override" type="text/html">
        <# if ( ! _.isUndefined( data.attributes ) ) { #>
            <div class="diff-title">
                <# if ( 'from' === data.type ) { #>
                    <strong><?php _ex( 'From:', 'Followed by post revision info' ); ?></strong>
                <# } else if ( 'to' === data.type ) { #>
                    <strong><?php _ex( 'To:', 'Followed by post revision info' ); ?></strong>
                <# } #>
                <div class="author-card<# if ( data.attributes.autosave ) { #> autosave<# } #>">
                    {{{ data.attributes.author.avatar }}}
                    <div class="author-info">
                    <# if ( data.attributes.autosave ) { #>
                        <span class="byline"><?php printf( __( 'Autosave by %s' ),
                            '<span class="author-name">{{ data.attributes.author.name }}</span>' ); ?></span>
                    <# } else if ( data.attributes.current ) { #>
                        <span class="byline"><?php printf( __( 'Current Revision by %s' ),
                            '<span class="author-name">{{ data.attributes.author.name }}</span>' ); ?></span>
                    <# } else { #>
                        <span class="byline"><?php printf( __( 'Revision by %s' ),
                            '<span class="author-name">{{ data.attributes.author.name }}</span>' ); ?></span>
                    <# } #>
                        <span class="time-ago">{{ data.attributes.timeAgo }}</span>
                        <span class="date">({{ data.attributes.dateShort }})</span>
                    </div>
                    Your custom text here
                <# if ( 'to' === data.type && data.attributes.restoreUrl ) { #>
                    <input  <?php if ( wp_check_post_lock( $post->ID ) ) { ?>
                        disabled="disabled"
                    <?php } else { ?>
                        <# if ( data.attributes.current ) { #>
                            disabled="disabled"
                        <# } #>
                    <?php } ?>
                    <# if ( data.attributes.autosave ) { #>
                        type="button" class="restore-revision button button-primary" value="<?php esc_attr_e( 'Restore This Autosave' ); ?>" />
                    <# } else { #>
                        type="button" class="restore-revision button button-primary" value="<?php esc_attr_e( 'Restore This Revision' ); ?>" />
                    <# } #>
                <# } #>
            </div>
        <# if ( 'tooltip' === data.type ) { #>
            <div class="revisions-tooltip-arrow"><span></span></div>
        <# } #>
    <# } #>
    </script>
    <script>
    (function($) {
        wp.revisions.view.MetaFrom.prototype.template = wp.template('revisions-meta-override');
        wp.revisions.view.MetaTo.prototype.template = wp.template('revisions-meta-override');
    })(jQuery);
    </script>
    <?php
} );

And to explain that. We’re hooking into the footer of the revisions admin page, so we’re guaranteed that the constructors revisions.view.MetaFrom and revisions.view.MetaTo have been defined, but before the revisions module bootstrapper has been triggered. This is important, because we want to modify the constructors before they are put to use. I copied the contents of revisions.view.Meta‘s microtemplate verbatim into an overridden version of the template #tmpl-revisions-meta-override, but notice I’ve added Your custom text here in the template where it looks like you want your custom text. Then, I override both constructor’s template() method, using the modified microtemplate’s ID as a reference.

Voila. Now, it depends what you want to do with your custom text. If you want to plop some text in there, go for it. If you want to output text specific to that revision, you’ll want to check out Carl Danley’s aforementioned library, and trigger a filter hook passing along data so that you can output something specific to the data at hand.

I know, this is insane. But this is where we’re at with overriding Javascript in WordPress Backbone templates. We should be having discussions about how we can bake in customizability like you’re asking for into core, but we’re not because there’s a lack of interest/momentum. Feel free to spark conversation at our weekly WordPress core developer chats. I will be there.

Leave a Comment