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
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:
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.– lukeCommented 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+.– birgireCommented 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!– lukeCommented 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.– birgireCommented Dec 16, 2014 at 23:19