1

I have a custom edit user interface where I allow the user to enter their own URL's, and so far I have the regex to find the URL's and turn them all into clickable html links. But I'd also like to give the user the option to enter their own link title, similar to the format here on StackOverflow:

[Name of Link](http://www.yourlink.com/)

How would I alter the code below to extract the title from the brackets, the URL from the parenthesis, AND also turn a regular URL into a clickable link (even if they just enter http://www.yourlink.com/ without a title)?

$text = preg_replace('/(((f|ht){1}tp:\/\/)[-a-zA-Z0-9@:%_\+.~#?&\/\/=]+)/i',
                       '<a href="\\1" target="_blank">\\1</a>', $text);
$text = preg_replace('/([[:space:]()[{}])(www.[-a-zA-Z0-9@:%_\+.~#?&\/\/=]+)/i',
                       '\\1<a href="http://\\2" target="_blank">\\2</a>', $text);
$text = preg_replace('/([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})/i',
                       '<a href="mailto:\\1">\\1</a>', $text);
seaofinformation
  • 809
  • 2
  • 12
  • 19

2 Answers2

4

Firstly you have to process these links with description, like this:

$text = preg_replace(
    '/\[([^\]]+)\]\((((f|ht){1}tp:\/\/)[-a-zA-Z0-9@:%_\+.~#?&\/\/=]+)\)/i',
    '<a href="\\2" target="_blank">\\1</a>', 
    $text
);

But now, regular URLs placed in href will match in next replace iteration for regular links, so we need to modify that to exclude it, for example match only when it is not preceded with ":

$text = preg_replace(
    '/(^|[^"])(((f|ht){1}tp:\/\/)[-a-zA-Z0-9@:%_\+.~#?&\/\/=]+)/i',
    '\\1<a href="\\2" target="_blank">\\2</a>', 
    $text
);
dev-null-dweller
  • 29,274
  • 3
  • 65
  • 85
  • Thanks so much for the reply. The second example you gave unfortunately doesn't work on any of the links. The first example you gave works for the links with the description as you said, but not ones without one. – seaofinformation Nov 04 '12 at 12:32
  • It's not an example, it's improvement of your first replace pattern. You still need to run all these in this order to cover all desired patterns. – dev-null-dweller Nov 04 '12 at 12:41
  • I thought that might have been the case so I ran all of them, but the URL's without descriptions still don't get made into links. Those with descriptions do. – seaofinformation Nov 04 '12 at 12:45
  • I know what's wrong...if you have a link without a description as the very first value, it doesn't seem to work on that link. All other links are fine. Not sure how to fix that..any ideas? http://codepad.viper-7.com/QMsbW5 – seaofinformation Nov 04 '12 at 13:03
  • OK, fixed by making non-apostrophe character optional – dev-null-dweller Nov 04 '12 at 13:08
  • No, that seems to mess up the others. Hmmm. I am royally bad at regex and I'm not sure how to fix this. http://codepad.viper-7.com/ozY1bb – seaofinformation Nov 04 '12 at 13:19
  • Yeah, I figured and edited accordingly, but seems that you have grabbed previous version – dev-null-dweller Nov 04 '12 at 13:56
  • to add https support, change `...(f|ht){1}tp:\/...` to `...(f|ht){1}tp(s)?:\/...` – younes0 Aug 15 '14 at 14:16
1

try this :

<?php
$text = "hello http://example.com sample
[Name of Link](http://www.yourlink.com/)
[Name of a](http://www.world.com/)
[Name of Link](http://www.hello.com/)
<a href=\"http://stackoverflow.com\">hello world</a>
<a href='http://php.net'>php</a>
";
echo nl2br(make_clickable($text));
function make_clickable($text) {
   $text = preg_replace_callback(
    '#\[(.+)\]\((\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|)/))\)#', 
    create_function(
      '$matches',
      'return "<a href=\'{$matches[2]}\'>{$matches[1]}</a>";'
    ),
    $text
  );
  $text = preg_replace_callback('#(?<!href\=[\'"])(https?|ftp|file)://[-A-Za-z0-9+&@\#/%()?=~_|$!:,.;]*[-A-Za-z0-9+&@\#/%()=~_|$]#', create_function(
      '$matches',
      'return "<a href=\'{$matches[0]}\'>{$matches[0]}</a>";'
    ), $text);
  return $text;
}

written (edited) based on following links :

Best way to make links clickable in block of text

Make links clickable with regex

and ...

Community
  • 1
  • 1
Shahrokhian
  • 1,100
  • 13
  • 28