Quantcast
Channel: Programming – Roy Tanck's weblog
Viewing all articles
Browse latest Browse all 14

Opening links inside WordPress comments in a new window

$
0
0

A project I’m working on requires all links to external sites to open in a new browser window or tab. This is easy enough for regular content, but I’ll have to figure out a way to add a target-attribute to links inside comments left by readers. WordPress automatically transforms URLs into links, but does not add this attribute. Unfortunately, many of the solutions I found a less than ideal. Somehow, the same piece of code keeps turning up in Google. Most search results are a variation of the following snippet (from Cats Who Code).

function autoblank($text) {
	$return = str_replace('<a', '<a target="_blank"', $text);
	return $return;
}
add_filter('the_content', 'autoblank');

This will simply replace every occurrence of <a with <a target="_blank". There are two problems with this approach.

  1. The substitution will also happen with <abbr> and <aside> tags should they be present in the filtered content. This will result in malformed HTML.
  2. The snippet does not check whether a ‘target’ attribute is already present in the link. This means you could well end up with two (conflicting?) target attributes.

Below is my proposed solution. It uses PHP string operators instead of regular expressions or DOMDocument, in an effort to make it fast and easy to read. It’s aimed at comments, where the markup is usually relatively simple. It checks links against the current site’s URL, and only adds the target attibute if a link points to a different (sub)domain.

function rt_add_link_target( $content ){
	// use the <a> tag to split into segments
	$bits = explode( '<a ', $content );
	// loop though the segments
	foreach( $bits as $key=>$bit ){
		// find the end of each link
		$pos = strpos( $bit, '>' );
		// check if there is an end (only fails with malformed markup)
		if( $pos !== false ){
			// get a string with just the link's attibutes
			$part = substr( $bit, 0, $pos );
			// for comparison, get the current site/network url
			$siteurl = network_site_url();
			// if the site url is in the attributes, assume it's in the href and skip, also if a target is present
			if( strpos( $part, $siteurl ) === false && strpos( $part, 'target=' ) === false ){
				// add the target attribute
				$bits[$key] = 'target="_blank" ' . $bits[$key];
			}
		}
	}
	// re-assemble the content, and return it
	return implode( '<a ', $bits );
}

add_filter( 'comment_text', 'rt_add_link_target' );

Please feel free to improve this on GitHub.


Viewing all articles
Browse latest Browse all 14

Trending Articles