6

Is there any possibility to hook into the editor of WordPress so that if a link to an internal content is inserted via the WYSIWYG editor the post id of that linked post is added as a data attribute to the link?

1 Answer 1

6

The HTML for the inserted internal links are generated by Javascript, so I'm not aware of any easy way to change it.

The HTML generation is controlled from the wpLink.htmlUpdate method (HTML mode) and the wpLink.mceUpdate method (TinyMCE mode), in the /wp-includes/js/wplink.js file.

Here are some ideas:

Add a query parameter to the inserted links:

We could add a query parameter, containing the post ID info, to the url of the inserted links, for example:

http://example.dev/hello-world/?wpse_pid=475

with the following:

/**
 * Append the wpse_pid query argument to inserted links
 *
 * @see http://wordpress.stackexchange.com/a/170836/26350
 */

add_filter( 'wp_link_query_args', function( $query ) {
    add_filter( 'post_link', 'wpse_post_link', 10, 2 );
    return $query;
});

add_filter( 'wp_link_query', function( $query ) {
    remove_filter( 'post_link', 'wpse_post_link', 10 );
    return $query;   
});

function wpse_post_link( $permalink, $post )
{
    if( false === stripos( $permalink, '?p=' ) )
            $permalink = add_query_arg( array( 'wpse_pid' => $post->ID ), $permalink );
    return $permalink;
}

Here's a screenshot showing this in action:

link with the wpse_pid parameter

Override the wpLink.mceUpdate method:

The following hack is just for fun, since the method might change in the future.

This is addition to the above code snippets.

/** 
 * Override the wpLink.mceUpdate method to modify the inserted link HTML.
 *
 * @see http://wordpress.stackexchange.com/a/170836/26350
 */

add_action( 'admin_footer-post.php', function(){
?>
<script>
jQuery( document ).ready( function( $ ){
    wpLink.mceUpdate = function(){
            var link,
            attrs = wpLink.getAttrs(),
            editor = tinyMCE.activeEditor;

            wpLink.close();
            editor.focus();

            if ( tinymce.isIE ) {
                editor.selection.moveToBookmark( editor.windowManager.bookmark );
            }
            link = editor.dom.getParent( editor.selection.getNode(), 'a[href]' );

            // If the values are empty, unlink and return
            if ( ! attrs.href || attrs.href == 'http://' ) {        
                editor.execCommand( 'unlink' );
                return;
            }

            // Set the class attribute.
            attrs.class = 'wpse_pid';

            // Grab the value of the wpse_pid parameter and use as id attribute.
            // Modified version of http://www.sitepoint.com/url-parameters-jquery/
            var results = new RegExp('[\?&]wpse_pid=([^&#]*)').exec( attrs.href );
            attrs.id = ( results != null ) ? 'wpse_pid_' + results[1] : ''

            // Remove the ?wpse_pid=* part
            // Modified version of http://stackoverflow.com/a/7126657/2078474
            attrs.href = attrs.href.replace(/[\?&]?wpse_pid=([^&]$|[^&]*)/i, "");

            if ( link ) {
                editor.dom.setAttribs( link, attrs );
            } else {
                editor.execCommand( 'mceInsertLink', false, attrs );
            }

            // Move the cursor to the end of the selection
            editor.selection.collapse();
    }
});
</script>
<?php
}, 99 );

The HTML of the inserted link has now the form:

<a id="wpse_pid_475" 
   class="wpse_pid"  
   title="Hello World" 
   href="http://example.dev/hello-world/">Hello World</a>

where the unmodified link is:

<a title="Hello World" 
   href="http://example.dev/hello-world/">Hello World</a>

Here I used the class and id attributes, since they seems to be supported attributes by the tinyMCE editor. I tried attrs.data but that didn't work. You might want to look deeper into that.

It should be similar to override the wpLink.htmlUpdate method. But this is just proof of concept ;-)

Another idea would be to scan the links of the post content during updates and modify them with some clever regexp replaces or some PHP DOM modifications.

Hopefully you can take this further and modify to your needs.

4
  • I tried this approach but I could not get it working, also the first part.
    – luke
    Commented Dec 16, 2014 at 0:00
  • Hi, can you elaborate? With the first part, what happened? Note that I assumed WP 3.7+ with pretty permalinks (i.e. not example.dev?p=123) and PHP 5.3+.
    – birgire
    Commented Dec 16, 2014 at 10:45
  • Hey, I am using the same setup. The query argument is not appended. But also if I add it manually, the link html is not modified. Thanks for your help!
    – luke
    Commented Dec 16, 2014 at 22:59
  • Strange, does it work on your test install with the TwentyTwelve default theme and no plugins installed, except our plugin ;-) That's how I tested it on WP 4.0.1.
    – birgire
    Commented Dec 16, 2014 at 23:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.