Auto linking text string having image tags using Text Helper in CakePHP

Recently I found that auto linking urls and emails of a string having image tags within was not possible using text helper in CakePHP. It would try to autoLink url of image src and thus it is broken. I am not sure what the issue is in including a fix or solution which could avoid image tags while auto-linking. Then, perhaps you would have to consider other tags like object src and video urls etc. In fact it would be too tedious to handle all kind of html tags and so and so..

Anyway to make it work for myself i had to create my own patch (helper) and now i have no problem auto linking strings having image tags within, anymore. Someone facing similar problems can feel free to use this small piece of code or helper. If someone knows a better solution i would be very happy to know that as well.

Here is my fix. I created a new helper, app/views/helpers/auto_link.php (download auto_link.zip) and placed this code in it. There are two function in it, one is commented out though, which i shall discuss later. Okay, so here is the helper code:

if (!class_exists('HtmlHelper')) {
	App::import('Helper', 'Html');
}

class AutoLinkHelper extends Helper {

	//var $helpers = array('Text');

	function autoLinkUrls($text, $htmlOptions = array()) {
		$options = var_export($htmlOptions, true);
		$text = preg_replace_callback('#(?<![href|src]="|">)((?:https?|ftp|nntp)://[^\s<>()]+)#i', create_function('$matches',
		'$Html = new HtmlHelper(); $Html->tags = $Html->loadConfig();
		return $Html->link($matches[0],
		$matches[0],' . $options . ');'), $text);

		return preg_replace_callback(
		'#(?<![href|src]="|">)(?<!http://|https://|ftp://|nntp://)(www\.[^\n\%\ <]+[^<\n\%\,\.\ <])(?<!\))#i',
		create_function('$matches', '$Html = new HtmlHelper();
		$Html->tags = $Html->loadConfig();
		return $Html->link($matches[0],
		"http://" . $matches[0],' . $options . ');'), $text);
	}

	/*function autoLinkUrls($text, $htmlOptions = array())    {

		if(preg_match_all('#<img[^>]*>#i', $text, $matches))    {

			$placeHolders=array();$imgs=array();

			foreach($matches[0] as $k=>$v)    {
			$placeHolders[] = "{IMGREP$k}";
			$imgs[] = $v;
			}

			$text = str_replace($imgs, $placeHolders, $text);
			$text = $this->Text->autoLinkUrls($text, $htmlOptions);
			return str_replace($placeHolders, $imgs, $text);
		}    else    {
			return $this->Text->autoLinkUrls($text, $htmlOptions);
		}
	}*/
}

Now as usual you may have to load this helper in your controller’s var $helpers array like this:

var $helpers = array("AutoLink", ......your other helpers)

Now, for example you have a string which you want to autolink for both url and email address just do the similar in your view file:

$str = '<a href="http://www.google.com">GOOGLE</a>, http://www.google.com and anymailtoaddress@gmail.com works fine and the image <img src="http://www.givebackindia.com/img/3rdparty/LEH3_157614g.jpg" /> as well';

echo $text->autoLinkEmails($autoLink->autoLinkUrls($str));

It should autolink all urls and emails properly.

Okay. Now the commented out function with same name. In fact i had been using this commented out function as i didn’t had much time to figure the regular expression out and thus i had to create this somewhat manual process in which i would store all image tag links in a temp array replacing them with placeholders in the actual text string. Once auto-linking was done i replaced placeholders with their actual values. This still works fine so if you prefer this way just comment out the function with regular expression and un-comment the //var $helpers = array(‘Text’); line. Also you should comment out the (as Html would not be used in this case anymore)

if (!class_exists('HtmlHelper')) {
App::import('Helper', 'Html');
}

I hope it helps someone. As stated above,  if some knows a better way to do it, please let me know. You can download the auto_link helper here auto_link.zip

Leave a Reply