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?

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.

  • I tried this approach but I could not get it working, also the first part. – luke Dec 16 '14 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 Dec 16 '14 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 Dec 16 '14 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 Dec 16 '14 at 23:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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